blob: 82c4bead7722e8d69de2f9cd5976a5941e85e869 [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010/*
Daniel Veillardb0f397e2003-12-23 23:30:53 +000011 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015 * - if we don't intend to use the schema for schemas, we
Daniel Veillard01fa6152004-06-29 17:04:39 +000016 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018 * - Eliminate item creation for: ??
19 *
20 * NOTES:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021 * - Elimated item creation for: <restriction>, <extension>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022 * <simpleContent>, <complexContent>, <list>, <union>
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023 *
Daniel Veillardb0f397e2003-12-23 23:30:53 +000024 */
Daniel Veillard4255d502002-04-16 15:50:10 +000025#define IN_LIBXML
26#include "libxml.h"
27
28#ifdef LIBXML_SCHEMAS_ENABLED
29
30#include <string.h>
31#include <libxml/xmlmemory.h>
32#include <libxml/parser.h>
33#include <libxml/parserInternals.h>
34#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000035#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000036#include <libxml/xmlschemas.h>
37#include <libxml/schemasInternals.h>
38#include <libxml/xmlschemastypes.h>
39#include <libxml/xmlautomata.h>
40#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000041#include <libxml/dict.h>
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000042#include <libxml/encoding.h>
43#include <libxml/xmlIO.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000044#ifdef LIBXML_PATTERN_ENABLED
45#include <libxml/pattern.h>
46#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000047#ifdef LIBXML_READER_ENABLED
48#include <libxml/xmlreader.h>
49#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000050
Daniel Veillarda84c0b32003-06-02 16:58:46 +000051/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000052
Daniel Veillard82bbbd42003-05-11 20:16:09 +000053/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000054
Daniel Veillard82bbbd42003-05-11 20:16:09 +000055/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000056
Daniel Veillard118aed72002-09-24 14:13:13 +000057/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000058
Daniel Veillard4255d502002-04-16 15:50:10 +000059/* #define DEBUG_AUTOMATA 1 */
60
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000061#define DEBUG_ATTR_VALIDATION 0
Daniel Veillardc0826a72004-08-10 14:17:33 +000062
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000063/* #define DEBUG_IDC 1 */
64
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000065/* #define DEBUG_INCLUDES 1 */
66
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000067/* #define ENABLE_PARTICLE_RESTRICTION 1 */
68
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000069/* #define ENABLE_SCHEMA_SPACES */
70
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000071/* #define ENABLE_REDEFINE */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000072
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000073/* #define ENABLE_NAMED_LOCALS */
74
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000075#define DUMP_CONTENT_MODEL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000076
77#ifdef LIBXML_READER_ENABLED
78/* #define XML_SCHEMA_READER_ENABLED */
79#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000080
Daniel Veillard4255d502002-04-16 15:50:10 +000081#define UNBOUNDED (1 << 30)
82#define TODO \
83 xmlGenericError(xmlGenericErrorContext, \
84 "Unimplemented block at %s:%d\n", \
85 __FILE__, __LINE__);
86
William M. Brack2f2a6632004-08-20 23:09:47 +000087#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000088
Daniel Veillard4255d502002-04-16 15:50:10 +000089/*
90 * The XML Schemas namespaces
91 */
92static const xmlChar *xmlSchemaNs = (const xmlChar *)
93 "http://www.w3.org/2001/XMLSchema";
94
95static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
96 "http://www.w3.org/2001/XMLSchema-instance";
97
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000098static const xmlChar *xmlNamespaceNs = (const xmlChar *)
99 "http://www.w3.org/2000/xmlns/";
100
Daniel Veillardc0826a72004-08-10 14:17:33 +0000101static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000102 "element decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000103static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000104 "attribute decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000105static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000106 "attribute use";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000107static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000108 "model group";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000109
Daniel Veillard4255d502002-04-16 15:50:10 +0000110#define IS_SCHEMA(node, type) \
111 ((node != NULL) && (node->ns != NULL) && \
112 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
113 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
114
Daniel Veillardc0826a72004-08-10 14:17:33 +0000115#define FREE_AND_NULL(str) \
116 if (str != NULL) { \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000117 xmlFree((xmlChar *) str); \
Daniel Veillardc0826a72004-08-10 14:17:33 +0000118 str = NULL; \
119 }
120
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000121#define IS_ANYTYPE(item) \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000122 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
123 (item->builtInType == XML_SCHEMAS_ANYTYPE))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000124
125#define IS_COMPLEX_TYPE(item) \
126 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
127 (item->builtInType == XML_SCHEMAS_ANYTYPE))
128
129#define IS_SIMPLE_TYPE(item) \
130 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
131 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000132 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000133
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000134#define IS_ANY_SIMPLE_TYPE(item) \
135 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000136 (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000137
138#define IS_NOT_TYPEFIXED(item) \
139 ((item->type != XML_SCHEMA_TYPE_BASIC) && \
140 ((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
141
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000142#define TYPE_IS_NOT_FIXEDUP_1(item) \
143 (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
144 (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
145
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000146#define HAS_COMPLEX_CONTENT(item) \
147 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
148 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
149 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
150
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000151#define HAS_SIMPLE_CONTENT(item) \
152 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
153 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
154
155#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
156
157#define IS_PARTICLE_EMPTIABLE(item) \
158 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
159
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000160#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
161
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000162#define GET_LIST_ITEM_TYPE(item) item->subtypes
163
164#define VARIETY_ATOMIC(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
165#define VARIETY_LIST(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
166#define VARIETY_UNION(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
167
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000168#define IS_MODEL_GROUP(item) \
169 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
170 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
171 (item->type == XML_SCHEMA_TYPE_ALL))
172
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000173#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
174
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000175#define ELEM_TYPE(item) item->subtypes
176
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000177#define GET_PARTICLE(item) (xmlSchemaParticlePtr) item->subtypes;
178
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000179#define SUBST_GROUP_AFF(item) (item)->refDecl
180
181#define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000182
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000183#if 0
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000184#define WXS_GET_NEXT(item) \
185 xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000186#endif
187
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000188#define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
189
190#define HFAILURE if (res == -1) goto exit_failure;
191
192#define HERROR if (res != 0) goto exit_error;
193
194#define HSTOP(ctx) if ((ctx)->stop) goto exit;
195
196#define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
197
198#define WXS_HAS_BUCKETS(ctx) \
199( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
200(WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
201
202#define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
203
204#define WXS_SCHEMA_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
205
206#define WXS_SCHEMA(ctx) (ctx)->schema
207
208#define ADD_LOCAL_ITEM(ctx, item) \
209 xmlSchemaAddItem(&(WXS_SCHEMA_BUCKET(ctx)->locals), item)
210
211#define ADD_GLOBAL_ITEM(ctx, item) \
212 xmlSchemaAddItem(&(WXS_SCHEMA_BUCKET(ctx)->globals), item)
213
214#define WXS_ADD_PENDING_ITEM(ctx, item) \
215 xmlSchemaAddItem(&((ctx)->constructor->pending), item)
216
217#define WXS_IS_RESTRICTION(t) \
218 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
219
220#define WXS_IS_EXTENSION(t) \
221 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
222
223/*
224* @b: The schema bucket
225*/
226#define WXS_IS_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
227 ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
228
229#define WXS_IS_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
230 ((t) == XML_SCHEMA_SCHEMA_IMPORT))
231
232#define IMPBUCKET_CAST(b) ((xmlSchemaImportPtr) (b))
233#define INCBUCKET_CAST(b) ((xmlSchemaIncludePtr) (b))
234
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000235#define SUBSET_RESTRICTION 1<<0
236#define SUBSET_EXTENSION 1<<1
237#define SUBSET_SUBSTITUTION 1<<2
238#define SUBSET_LIST 1<<3
239#define SUBSET_UNION 1<<4
240
Daniel Veillard4255d502002-04-16 15:50:10 +0000241#define XML_SCHEMAS_PARSE_ERROR 1
242
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000243#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
244
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000245typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
246typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000247
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000248typedef struct _xmlSchemaItemList xmlSchemaItemList;
249typedef xmlSchemaItemList *xmlSchemaItemListPtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000250struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000251 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000252 int nbItems; /* used for dynamic addition of schemata */
253 int sizeItems; /* used for dynamic addition of schemata */
254};
255
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000256typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
257typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
258struct _xmlSchemaAbstractCtxt {
259 int type;
260};
261
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000262typedef struct _xmlSchemaBucket xmlSchemaBucket;
263typedef xmlSchemaBucket *xmlSchemaBucketPtr;
264
265#define XML_SCHEMA_SCHEMA_MAIN 0
266#define XML_SCHEMA_SCHEMA_IMPORT 1
267#define XML_SCHEMA_SCHEMA_INCLUDE 2
268#define XML_SCHEMA_SCHEMA_REDEFINE 3
269
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000270/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000271 * xmlSchemaSchemaRelation:
272 *
273 * Used to create a graph of schema relationships.
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000274 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000275typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
276typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
277struct _xmlSchemaSchemaRelation {
278 xmlSchemaSchemaRelationPtr next;
279 int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
280 const xmlChar *importNamespace;
281 xmlSchemaBucketPtr bucket;
282};
283
284struct _xmlSchemaBucket {
285 int type;
286 const xmlChar *schemaLocation;
287 const xmlChar *origTargetNamespace;
288 const xmlChar *targetNamespace;
289 xmlDocPtr doc;
290 xmlSchemaSchemaRelationPtr relations;
291 int located;
292 int parsed;
293 int imported;
294 int preserveDoc;
295 xmlSchemaItemListPtr globals; /* Global components. */
296 xmlSchemaItemListPtr locals; /* Local components. */
297};
298
299/**
300 * xmlSchemaImport:
301 * (extends xmlSchemaBucket)
302 *
303 * Reflects a schema. Holds some information
304 * about the schema and its toplevel components. Duplicate
305 * toplevel components are not checked at this level.
306 */
307typedef struct _xmlSchemaImport xmlSchemaImport;
308typedef xmlSchemaImport *xmlSchemaImportPtr;
309struct _xmlSchemaImport {
310 int type; /* Main OR import OR include. */
311 const xmlChar *schemaLocation; /* The URI of the schema document. */
312 /* For chameleon includes, @origTargetNamespace will be NULL */
313 const xmlChar *origTargetNamespace;
314 /*
315 * For chameleon includes, @targetNamespace will be the
316 * targetNamespace of the including schema.
317 */
318 const xmlChar *targetNamespace;
319 xmlDocPtr doc; /* The schema node-tree. */
320 /* @relations will hold any included/imported/redefined schemas. */
321 xmlSchemaSchemaRelationPtr relations;
322 int located;
323 int parsed;
324 int imported;
325 int preserveDoc;
326 xmlSchemaItemListPtr globals;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000327 xmlSchemaItemListPtr locals;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000328 /* The imported schema. */
329 xmlSchemaPtr schema;
330};
331
332/*
333* (extends xmlSchemaBucket)
334*/
335typedef struct _xmlSchemaInclude xmlSchemaInclude;
336typedef xmlSchemaInclude *xmlSchemaIncludePtr;
337struct _xmlSchemaInclude {
338 int type;
339 const xmlChar *schemaLocation;
340 const xmlChar *origTargetNamespace;
341 const xmlChar *targetNamespace;
342 xmlDocPtr doc;
343 xmlSchemaSchemaRelationPtr relations;
344 int located;
345 int parsed;
346 int imported;
347 int preserveDoc;
348 xmlSchemaItemListPtr globals; /* Global components. */
349 xmlSchemaItemListPtr locals; /* Local components. */
350
351 /* The owning main or import schema bucket. */
352 xmlSchemaImportPtr ownerImport;
353};
354
355typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
356typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
357struct _xmlSchemaConstructionCtxt {
358 xmlSchemaPtr schema; /* The main schema. */
359 xmlDictPtr dict;
360 xmlSchemaItemListPtr buckets; /* List of schema buckets. */
361 /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
362 xmlSchemaBucketPtr bucket; /* The current schema bucket */
363 /* All Components of all schemas that need to be fixed. */
364 xmlSchemaItemListPtr pending;
365 xmlHashTablePtr substGroups;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000366};
367
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000368#define XML_SCHEMA_CTXT_PARSER 1
369#define XML_SCHEMA_CTXT_VALIDATOR 2
370
Daniel Veillard4255d502002-04-16 15:50:10 +0000371struct _xmlSchemaParserCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000372 int type;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000373 void *userData; /* user specific data block */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000374 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
375 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000376 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000377 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000378 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000379
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000380 xmlSchemaConstructionCtxtPtr constructor;
381 int ownsConstructor; /* TODO: Move this to parser flags. */
382
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000383 /* xmlSchemaPtr topschema; The main schema */
384 /* xmlHashTablePtr namespaces; Hash table of namespaces to schemas */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000385
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000386 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillard4255d502002-04-16 15:50:10 +0000387 int counter;
388
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000389 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000390 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000391 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000392
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000393 const char *buffer;
394 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000395
Daniel Veillard4255d502002-04-16 15:50:10 +0000396 /*
397 * Used to build complex element content models
398 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000399 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000400 xmlAutomataStatePtr start;
401 xmlAutomataStatePtr end;
402 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000403
404 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000405 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000406 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000407 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000408 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +0000409 int isS4S;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000410 int isRedefine;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000411 int xsiAssemble;
412 int stop; /* If the parser should stop; i.e. a critical error. */
413 const xmlChar *targetNamespace;
Daniel Veillard4255d502002-04-16 15:50:10 +0000414};
415
Daniel Veillard4255d502002-04-16 15:50:10 +0000416#define XML_SCHEMAS_ATTR_UNKNOWN 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000417#define XML_SCHEMAS_ATTR_ASSESSED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000418#define XML_SCHEMAS_ATTR_PROHIBITED 3
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000419#define XML_SCHEMAS_ATTR_ERR_MISSING 4
Daniel Veillard3646d642004-06-02 19:19:14 +0000420#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000421#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
422#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000423#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000424#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000425#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
426#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
427#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
428#define XML_SCHEMAS_ATTR_WILD_SKIP 13
429#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
430#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
431#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
432#define XML_SCHEMAS_ATTR_META 17
Daniel Veillard4255d502002-04-16 15:50:10 +0000433
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000434/**
435 * xmlSchemaBasicItem:
436 *
437 * The abstract base type for schema components.
438 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000439typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
440typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
441struct _xmlSchemaBasicItem {
442 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000443};
444
445/**
446 * xmlSchemaAnnotItem:
447 *
448 * The abstract base type for annotated schema components.
449 * (Extends xmlSchemaBasicItem)
450 */
451typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
452typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
453struct _xmlSchemaAnnotItem {
454 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000455 xmlSchemaAnnotPtr annot;
456};
457
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000458/**
459 * xmlSchemaTreeItem:
460 *
461 * The abstract base type for tree-like structured schema components.
462 * (Extends xmlSchemaAnnotItem)
463 */
464typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
465typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
466struct _xmlSchemaTreeItem {
467 xmlSchemaTypeType type;
468 xmlSchemaAnnotPtr annot;
469 xmlSchemaTreeItemPtr next;
470 xmlSchemaTreeItemPtr children;
471};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000472
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000473/**
474 * xmlSchemaQNameRef:
475 *
476 * A component reference item (not a schema component)
477 * (Extends xmlSchemaBasicItem)
478 */
479typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
480typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
481struct _xmlSchemaQNameRef {
482 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000483 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000484 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000485 const xmlChar *name;
486 const xmlChar *targetNamespace;
487};
488
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000489/**
490 * xmlSchemaParticle:
491 *
492 * A particle component.
493 * (Extends xmlSchemaTreeItem)
494 */
495typedef struct _xmlSchemaParticle xmlSchemaParticle;
496typedef xmlSchemaParticle *xmlSchemaParticlePtr;
497struct _xmlSchemaParticle {
498 xmlSchemaTypeType type;
499 xmlSchemaAnnotPtr annot;
500 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
501 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
502 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000503 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000504 xmlNodePtr node;
505};
506
507/**
508 * xmlSchemaModelGroup:
509 *
510 * A model group component.
511 * (Extends xmlSchemaTreeItem)
512 */
513typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
514typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
515struct _xmlSchemaModelGroup {
516 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
517 xmlSchemaAnnotPtr annot;
518 xmlSchemaTreeItemPtr next; /* not used */
519 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
520 xmlNodePtr node;
521};
522
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000523#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000524/**
525 * xmlSchemaModelGroupDef:
526 *
527 * A model group definition component.
528 * (Extends xmlSchemaTreeItem)
529 */
530typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
531typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
532struct _xmlSchemaModelGroupDef {
533 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
534 xmlSchemaAnnotPtr annot;
535 xmlSchemaTreeItemPtr next; /* not used */
536 xmlSchemaTreeItemPtr children; /* the "model group" */
537 const xmlChar *name;
538 const xmlChar *targetNamespace;
539 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000540 int flags;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000541 xmlSchemaModelGroupDefPtr redef; /* Redefinitions. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000542};
543
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000544typedef struct _xmlSchemaIDC xmlSchemaIDC;
545typedef xmlSchemaIDC *xmlSchemaIDCPtr;
546
547/**
548 * xmlSchemaIDCSelect:
549 *
550 * The identity-constraint "field" and "selector" item, holding the
551 * XPath expression.
552 */
553typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
554typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000555struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000556 xmlSchemaIDCSelectPtr next;
557 xmlSchemaIDCPtr idc;
558 int index; /* an index position if significant for IDC key-sequences */
559 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000560 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000561};
562
563/**
564 * xmlSchemaIDC:
565 *
566 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000567 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000568 */
569
570struct _xmlSchemaIDC {
571 xmlSchemaTypeType type;
572 xmlSchemaAnnotPtr annot;
573 xmlSchemaIDCPtr next;
574 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000575 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000576 const xmlChar *targetNamespace;
577 xmlSchemaIDCSelectPtr selector;
578 xmlSchemaIDCSelectPtr fields;
579 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000580 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000581};
582
583/**
584 * xmlSchemaIDCAug:
585 *
586 * The augmented IDC information used for validation.
587 */
588typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
589typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
590struct _xmlSchemaIDCAug {
591 xmlSchemaIDCAugPtr next; /* next in a list */
592 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000593 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000594 tables need to be bubbled upwards */
595};
596
597/**
598 * xmlSchemaPSVIIDCKeySequence:
599 *
600 * The key sequence of a node table item.
601 */
602typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
603typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
604struct _xmlSchemaPSVIIDCKey {
605 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000606 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000607};
608
609/**
610 * xmlSchemaPSVIIDCNode:
611 *
612 * The node table item of a node table.
613 */
614typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
615typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
616struct _xmlSchemaPSVIIDCNode {
617 xmlNodePtr node;
618 xmlSchemaPSVIIDCKeyPtr *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000619 int nodeLine;
620 int nodeQNameID;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000621
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000622};
623
624/**
625 * xmlSchemaPSVIIDCBinding:
626 *
627 * The identity-constraint binding item of the [identity-constraint table].
628 */
629typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
630typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
631struct _xmlSchemaPSVIIDCBinding {
632 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
633 xmlSchemaIDCPtr definition; /* the IDC definition */
634 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
635 int nbNodes; /* number of entries in the node table */
636 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000637 int nbDupls; /* number of already identified duplicates in the node
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000638 table */
639 /* int nbKeys; number of keys in each key-sequence */
640};
641
642#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
643#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
644
645#define XPATH_STATE_OBJ_MATCHES -2
646#define XPATH_STATE_OBJ_BLOCKED -3
647
648typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
649typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
650
651/**
652 * xmlSchemaIDCStateObj:
653 *
654 * The state object used to evaluate XPath expressions.
655 */
656typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
657typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
658struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000659 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000660 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000661 int depth; /* depth of creation */
662 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000663 int nbHistory;
664 int sizeHistory;
665 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
666 matcher */
667 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000668 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000669};
670
671#define IDC_MATCHER 0
672
673/**
674 * xmlSchemaIDCMatcher:
675 *
676 * Used to IDC selectors (and fields) successively.
677 */
678struct _xmlSchemaIDCMatcher {
679 int type;
680 int depth; /* the tree depth at creation time */
681 xmlSchemaIDCMatcherPtr next; /* next in the list */
682 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
683 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
684 elements */
685 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000686 int targetDepth;
687};
688
689/*
690* Element info flags.
691*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000692#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
693#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
694#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
695#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
696
697#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
698#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
699#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
700
701#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
702#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
703#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
704#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000705
706/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000707 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000708 *
709 * Holds information of an element node.
710 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000711struct _xmlSchemaNodeInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000712 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000713 xmlNodePtr node;
714 int nodeLine;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000715 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000716 const xmlChar *nsName;
717 const xmlChar *value;
718 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000719 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000720
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000721 int flags; /* combination of node info flags */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000722
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000723 int valNeeded;
724 int normVal;
725
726 xmlSchemaElementPtr decl; /* the element/attribute declaration */
727 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000728 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
729 for the scope element*/
730 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
731 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000732 xmlRegExecCtxtPtr regexCtxt;
733
734 const xmlChar **nsBindings; /* Namespace bindings on this element */
735 int nbNsBindings;
736 int sizeNsBindings;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000737};
738
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000739/*
740* @metaType values of xmlSchemaAttrInfo.
741*/
742#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
743#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
744#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
745#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
746#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000747
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000748typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
749typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
750struct _xmlSchemaAttrInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000751 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000752 xmlNodePtr node;
753 int nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000754 const xmlChar *localName;
755 const xmlChar *nsName;
756 const xmlChar *value;
757 xmlSchemaValPtr val; /* the pre-computed value if any */
758 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
759 int flags; /* combination of node info flags */
760
761 xmlSchemaAttributePtr decl; /* the attribute declaration */
762 xmlSchemaAttributePtr use; /* the attribute use */
763 int state;
764 int metaType;
765 const xmlChar *vcValue; /* the value constraint value */
766 xmlSchemaNodeInfoPtr parent;
767};
768
769
770#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000771/**
772 * xmlSchemaValidCtxt:
773 *
774 * A Schemas validation context
775 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000776struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000777 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000778 void *userData; /* user specific data block */
779 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000780 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000781 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000782
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000783 xmlSchemaPtr schema; /* The schema in use */
784 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000785 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000786 xmlCharEncoding enc;
787 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000788 xmlParserCtxtPtr parserCtxt;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000789 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000790
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000791 int err;
792 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000793
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000794 xmlNodePtr node;
795 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000796 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000797
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000798 xmlRegExecCtxtPtr regexp;
799 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000800
Daniel Veillardc0826a72004-08-10 14:17:33 +0000801 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000802 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000803 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000804 xmlSchemaParserCtxtPtr pctxt;
805 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000806
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000807 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000808 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000809 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000810 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000811
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000812 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
813
814 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
815 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000816
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000817 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
818 int nbIdcNodes;
819 int sizeIdcNodes;
820
821 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
822 int nbIdcKeys;
823 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000824
825 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000826
827 xmlDictPtr dict;
828
Daniel Veillard39e5c892005-07-03 22:48:50 +0000829#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000830 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +0000831#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000832
833 xmlSchemaAttrInfoPtr *attrInfos;
834 int nbAttrInfos;
835 int sizeAttrInfos;
836
837 int skipDepth;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000838 xmlSchemaItemListPtr nodeQNames;
Daniel Veillard4255d502002-04-16 15:50:10 +0000839};
840
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000841/**
842 * xmlSchemaSubstGroup:
843 *
844 *
845 */
846typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
847typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
848struct _xmlSchemaSubstGroup {
849 xmlSchemaElementPtr head;
850 xmlSchemaItemListPtr members;
851};
852
Daniel Veillard4255d502002-04-16 15:50:10 +0000853/************************************************************************
854 * *
855 * Some predeclarations *
856 * *
857 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000858
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000859static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
860 xmlSchemaPtr schema,
861 xmlNodePtr node);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000862static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
863 xmlSchemaPtr schema,
864 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000865static int
866xmlSchemaTypeFixup(xmlSchemaTypePtr type,
867 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000868static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000869xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
870static int
William M. Brack2f2a6632004-08-20 23:09:47 +0000871xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
872 xmlNodePtr node);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000873static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000874xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
875 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000876static void
877xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000878static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000879xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000880static xmlSchemaTreeItemPtr
881xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
882 xmlNodePtr node, xmlSchemaTypeType type,
883 int withParticle);
884static const xmlChar *
885xmlSchemaCompTypeToString(xmlSchemaTypeType type);
886static xmlSchemaTypeLinkPtr
887xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000888static void
889xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
890 const char *funcName,
891 const char *message);
892static int
893xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
894 xmlSchemaTypePtr baseType,
895 int subset);
896static void
897xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000898 xmlSchemaParserCtxtPtr ctxt);
899static void
900xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
William M. Brack87640d52004-04-17 14:58:15 +0000901
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000902/************************************************************************
903 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000904 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000905 * *
906 ************************************************************************/
907
908/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000909 * xmlSchemaCompTypeToString:
910 * @type: the type of the schema item
911 *
912 * Returns the component name of a schema item.
913 */
914static const xmlChar *
915xmlSchemaCompTypeToString(xmlSchemaTypeType type)
916{
917 switch (type) {
918 case XML_SCHEMA_TYPE_SIMPLE:
919 return(BAD_CAST "simple type definition");
920 case XML_SCHEMA_TYPE_COMPLEX:
921 return(BAD_CAST "complex type definition");
922 case XML_SCHEMA_TYPE_ELEMENT:
923 return(BAD_CAST "element declaration");
924 case XML_SCHEMA_TYPE_ATTRIBUTE:
925 return(BAD_CAST "attribute declaration");
926 case XML_SCHEMA_TYPE_GROUP:
927 return(BAD_CAST "model group definition");
928 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
929 return(BAD_CAST "attribute group definition");
930 case XML_SCHEMA_TYPE_NOTATION:
931 return(BAD_CAST "notation declaration");
932 case XML_SCHEMA_TYPE_SEQUENCE:
933 return(BAD_CAST "model group (sequence)");
934 case XML_SCHEMA_TYPE_CHOICE:
935 return(BAD_CAST "model group (choice)");
936 case XML_SCHEMA_TYPE_ALL:
937 return(BAD_CAST "model group (all)");
938 case XML_SCHEMA_TYPE_PARTICLE:
939 return(BAD_CAST "particle");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +0000940 case XML_SCHEMA_TYPE_IDC_UNIQUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000941 return(BAD_CAST "unique identity-constraint");
942 /* return(BAD_CAST "IDC (unique)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +0000943 case XML_SCHEMA_TYPE_IDC_KEY:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000944 return(BAD_CAST "key identity-constraint");
945 /* return(BAD_CAST "IDC (key)"); */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +0000946 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +0000947 return(BAD_CAST "keyref identity-constraint");
948 /* return(BAD_CAST "IDC (keyref)"); */
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +0000949 case XML_SCHEMA_TYPE_ANY:
950 return(BAD_CAST "wildcard (any)");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +0000951 case XML_SCHEMA_EXTRA_QNAMEREF:
952 return(BAD_CAST "[helper component] QName reference");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000953 default:
954 return(BAD_CAST "Not a schema component");
955 }
956}
957
958/**
959 * xmlSchemaGetComponentNode:
960 * @item: a schema component
961 *
962 * Returns node associated with the schema component.
963 * NOTE that such a node need not be available; plus, a component's
964 * node need not to reflect the component directly, since there is no
965 * one-to-one relationship between the XML Schema representation and
966 * the component representation.
967 */
968static xmlNodePtr
969xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
970{
971 switch (item->type) {
972 case XML_SCHEMA_TYPE_ELEMENT:
973 return (((xmlSchemaElementPtr) item)->node);
974 case XML_SCHEMA_TYPE_ATTRIBUTE:
975 return (((xmlSchemaAttributePtr) item)->node);
976 case XML_SCHEMA_TYPE_COMPLEX:
977 case XML_SCHEMA_TYPE_SIMPLE:
978 return (((xmlSchemaTypePtr) item)->node);
979 case XML_SCHEMA_TYPE_ANY:
980 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
981 return (((xmlSchemaWildcardPtr) item)->node);
982 case XML_SCHEMA_TYPE_PARTICLE:
983 return (((xmlSchemaParticlePtr) item)->node);
984 case XML_SCHEMA_TYPE_SEQUENCE:
985 case XML_SCHEMA_TYPE_CHOICE:
986 case XML_SCHEMA_TYPE_ALL:
987 return (((xmlSchemaModelGroupPtr) item)->node);
988 case XML_SCHEMA_TYPE_GROUP:
989 return (((xmlSchemaModelGroupDefPtr) item)->node);
990 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
991 return (((xmlSchemaAttributeGroupPtr) item)->node);
992 case XML_SCHEMA_TYPE_IDC_UNIQUE:
993 case XML_SCHEMA_TYPE_IDC_KEY:
994 case XML_SCHEMA_TYPE_IDC_KEYREF:
995 return (((xmlSchemaIDCPtr) item)->node);
996 default:
997 return (NULL);
998 }
999}
1000
1001#if 0
1002/**
1003 * xmlSchemaGetNextComponent:
1004 * @item: a schema component
1005 *
1006 * Returns the next sibling of the schema component.
1007 */
1008static xmlSchemaBasicItemPtr
1009xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1010{
1011 switch (item->type) {
1012 case XML_SCHEMA_TYPE_ELEMENT:
1013 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1014 case XML_SCHEMA_TYPE_ATTRIBUTE:
1015 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1016 case XML_SCHEMA_TYPE_COMPLEX:
1017 case XML_SCHEMA_TYPE_SIMPLE:
1018 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1019 case XML_SCHEMA_TYPE_ANY:
1020 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1021 return (NULL);
1022 case XML_SCHEMA_TYPE_PARTICLE:
1023 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1024 case XML_SCHEMA_TYPE_SEQUENCE:
1025 case XML_SCHEMA_TYPE_CHOICE:
1026 case XML_SCHEMA_TYPE_ALL:
1027 return (NULL);
1028 case XML_SCHEMA_TYPE_GROUP:
1029 return (NULL);
1030 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1031 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1032 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1033 case XML_SCHEMA_TYPE_IDC_KEY:
1034 case XML_SCHEMA_TYPE_IDC_KEYREF:
1035 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1036 default:
1037 return (NULL);
1038 }
1039}
1040#endif
1041
1042/**
1043 * xmlSchemaGetAttrName:
1044 * @attr: the attribute declaration/use
1045 *
1046 * Returns the name of the attribute; if the attribute
1047 * is a reference, the name of the referenced global type will be returned.
1048 */
1049static const xmlChar *
1050xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
1051{
1052 if (attr->ref != NULL)
1053 return(attr->ref);
1054 else
1055 return(attr->name);
1056}
1057
1058/**
1059 * xmlSchemaGetAttrTargetNsURI:
1060 * @type: the type (element or attribute)
1061 *
1062 * Returns the target namespace URI of the type; if the type is a reference,
1063 * the target namespace of the referenced type will be returned.
1064 */
1065static const xmlChar *
1066xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
1067{
1068 if (attr->ref != NULL)
1069 return (attr->refNs);
1070 else
1071 return(attr->targetNamespace);
1072}
1073
1074/**
1075 * xmlSchemaFormatQName:
1076 * @buf: the string buffer
1077 * @namespaceName: the namespace name
1078 * @localName: the local name
1079 *
1080 * Returns the given QName in the format "{namespaceName}localName" or
1081 * just "localName" if @namespaceName is NULL.
1082 *
1083 * Returns the localName if @namespaceName is NULL, a formatted
1084 * string otherwise.
1085 */
1086static const xmlChar*
1087xmlSchemaFormatQName(xmlChar **buf,
1088 const xmlChar *namespaceName,
1089 const xmlChar *localName)
1090{
1091 FREE_AND_NULL(*buf)
1092 if (namespaceName == NULL)
1093 return(localName);
1094
1095 *buf = xmlStrdup(BAD_CAST "{");
1096 *buf = xmlStrcat(*buf, namespaceName);
1097 *buf = xmlStrcat(*buf, BAD_CAST "}");
1098 *buf = xmlStrcat(*buf, localName);
1099
1100 return ((const xmlChar *) *buf);
1101}
1102
1103static const xmlChar*
1104xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1105{
1106 if (ns != NULL)
1107 return (xmlSchemaFormatQName(buf, ns->href, localName));
1108 else
1109 return (xmlSchemaFormatQName(buf, NULL, localName));
1110}
1111
1112static const xmlChar *
1113xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1114{
1115 switch (item->type) {
1116 case XML_SCHEMA_TYPE_ELEMENT:
1117 return (((xmlSchemaElementPtr) item)->name);
1118 case XML_SCHEMA_TYPE_ATTRIBUTE:
1119 return (((xmlSchemaAttributePtr) item)->name);
1120 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1121 return (((xmlSchemaAttributeGroupPtr) item)->name);
1122 case XML_SCHEMA_TYPE_BASIC:
1123 case XML_SCHEMA_TYPE_SIMPLE:
1124 case XML_SCHEMA_TYPE_COMPLEX:
1125 return (((xmlSchemaTypePtr) item)->name);
1126 case XML_SCHEMA_TYPE_GROUP:
1127 return (((xmlSchemaModelGroupDefPtr) item)->name);
1128 case XML_SCHEMA_TYPE_IDC_KEY:
1129 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1130 case XML_SCHEMA_TYPE_IDC_KEYREF:
1131 return (((xmlSchemaIDCPtr) item)->name);
1132 default:
1133 /*
1134 * Other components cannot have names.
1135 */
1136 break;
1137 }
1138 return (NULL);
1139}
1140
1141static const xmlChar *
1142xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1143{
1144 switch (item->type) {
1145 case XML_SCHEMA_TYPE_ELEMENT:
1146 return (((xmlSchemaElementPtr) item)->targetNamespace);
1147 case XML_SCHEMA_TYPE_ATTRIBUTE:
1148 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1149 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1150 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1151 case XML_SCHEMA_TYPE_BASIC:
1152 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1153 case XML_SCHEMA_TYPE_SIMPLE:
1154 case XML_SCHEMA_TYPE_COMPLEX:
1155 return (((xmlSchemaTypePtr) item)->targetNamespace);
1156 case XML_SCHEMA_TYPE_GROUP:
1157 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1158 case XML_SCHEMA_TYPE_IDC_KEY:
1159 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1160 case XML_SCHEMA_TYPE_IDC_KEYREF:
1161 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1162 default:
1163 /*
1164 * Other components cannot have names.
1165 */
1166 break;
1167 }
1168 return (NULL);
1169}
1170
1171static const xmlChar*
1172xmlSchemaGetComponentQName(xmlChar **buf,
1173 void *item)
1174{
1175 return (xmlSchemaFormatQName(buf,
1176 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1177 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1178}
1179
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001180static const xmlChar*
1181xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1182{
1183 xmlChar *str = NULL;
1184
1185 *buf = xmlStrcat(*buf, xmlSchemaCompTypeToString(idc->type));
1186 *buf = xmlStrcat(*buf, BAD_CAST " '");
1187 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, idc));
1188 *buf = xmlStrcat(*buf, BAD_CAST "'");
1189 FREE_AND_NULL(str);
1190 return(*buf);
1191}
1192
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001193/**
1194 * xmlSchemaWildcardPCToString:
1195 * @pc: the type of processContents
1196 *
1197 * Returns a string representation of the type of
1198 * processContents.
1199 */
1200static const xmlChar *
1201xmlSchemaWildcardPCToString(int pc)
1202{
1203 switch (pc) {
1204 case XML_SCHEMAS_ANY_SKIP:
1205 return (BAD_CAST "skip");
1206 case XML_SCHEMAS_ANY_LAX:
1207 return (BAD_CAST "lax");
1208 case XML_SCHEMAS_ANY_STRICT:
1209 return (BAD_CAST "strict");
1210 default:
1211 return (BAD_CAST "invalid process contents");
1212 }
1213}
1214
1215/**
1216 * xmlSchemaGetCanonValueWhtspExt:
1217 * @val: the precomputed value
1218 * @retValue: the returned value
1219 * @ws: the whitespace type of the value
1220 *
1221 * Get a the cononical representation of the value.
1222 * The caller has to free the returned retValue.
1223 *
1224 * Returns 0 if the value could be built and -1 in case of
1225 * API errors or if the value type is not supported yet.
1226 */
1227static int
1228xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1229 xmlSchemaWhitespaceValueType ws,
1230 xmlChar **retValue)
1231{
1232 int list;
1233 xmlSchemaValType valType;
1234 const xmlChar *value, *value2 = NULL;
1235
1236
1237 if ((retValue == NULL) || (val == NULL))
1238 return (-1);
1239 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1240 *retValue = NULL;
1241 do {
1242 value = NULL;
1243 valType = xmlSchemaGetValType(val);
1244 switch (valType) {
1245 case XML_SCHEMAS_STRING:
1246 case XML_SCHEMAS_NORMSTRING:
1247 case XML_SCHEMAS_ANYSIMPLETYPE:
1248 value = xmlSchemaValueGetAsString(val);
1249 if (value != NULL) {
1250 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1251 value2 = xmlSchemaCollapseString(value);
1252 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1253 value2 = xmlSchemaWhiteSpaceReplace(value);
1254 if (value2 != NULL)
1255 value = value2;
1256 }
1257 break;
1258 default:
1259 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1260 if (value2 != NULL)
1261 xmlFree((xmlChar *) value2);
1262 goto internal_error;
1263 }
1264 value = value2;
1265 }
1266 if (*retValue == NULL)
1267 if (value == NULL) {
1268 if (! list)
1269 *retValue = xmlStrdup(BAD_CAST "");
1270 } else
1271 *retValue = xmlStrdup(value);
1272 else if (value != NULL) {
1273 /* List. */
1274 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1275 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1276 }
1277 FREE_AND_NULL(value2)
1278 val = xmlSchemaValueGetNext(val);
1279 } while (val != NULL);
1280
1281 return (0);
1282internal_error:
1283 if (*retValue != NULL)
1284 xmlFree((xmlChar *) (*retValue));
1285 if (value2 != NULL)
1286 xmlFree((xmlChar *) value2);
1287 return (-1);
1288}
1289
1290/**
1291 * xmlSchemaFormatItemForReport:
1292 * @buf: the string buffer
1293 * @itemDes: the designation of the item
1294 * @itemName: the name of the item
1295 * @item: the item as an object
1296 * @itemNode: the node of the item
1297 * @local: the local name
1298 * @parsing: if the function is used during the parse
1299 *
1300 * Returns a representation of the given item used
1301 * for error reports.
1302 *
1303 * The following order is used to build the resulting
1304 * designation if the arguments are not NULL:
1305 * 1a. If itemDes not NULL -> itemDes
1306 * 1b. If (itemDes not NULL) and (itemName not NULL)
1307 * -> itemDes + itemName
1308 * 2. If the preceding was NULL and (item not NULL) -> item
1309 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1310 *
1311 * If the itemNode is an attribute node, the name of the attribute
1312 * will be appended to the result.
1313 *
1314 * Returns the formatted string and sets @buf to the resulting value.
1315 */
1316static xmlChar*
1317xmlSchemaFormatItemForReport(xmlChar **buf,
1318 const xmlChar *itemDes,
1319 xmlSchemaTypePtr item,
1320 xmlNodePtr itemNode)
1321{
1322 xmlChar *str = NULL;
1323 int named = 1;
1324
1325 if (*buf != NULL) {
1326 xmlFree(*buf);
1327 *buf = NULL;
1328 }
1329
1330 if (itemDes != NULL) {
1331 *buf = xmlStrdup(itemDes);
1332 } else if (item != NULL) {
1333 switch (item->type) {
1334 case XML_SCHEMA_TYPE_BASIC:
1335 if (VARIETY_ATOMIC(item))
1336 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1337 else if (VARIETY_LIST(item))
1338 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1339 else if (VARIETY_UNION(item))
1340 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1341 else
1342 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1343 *buf = xmlStrcat(*buf, item->name);
1344 *buf = xmlStrcat(*buf, BAD_CAST "'");
1345 break;
1346 case XML_SCHEMA_TYPE_SIMPLE:
1347 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1348 *buf = xmlStrdup(BAD_CAST"");
1349 } else {
1350 *buf = xmlStrdup(BAD_CAST "local ");
1351 }
1352 if (VARIETY_ATOMIC(item))
1353 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1354 else if (VARIETY_LIST(item))
1355 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1356 else if (VARIETY_UNION(item))
1357 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1358 else
1359 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1360 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1361 *buf = xmlStrcat(*buf, BAD_CAST " '");
1362 *buf = xmlStrcat(*buf, item->name);
1363 *buf = xmlStrcat(*buf, BAD_CAST "'");
1364 }
1365 break;
1366 case XML_SCHEMA_TYPE_COMPLEX:
1367 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1368 *buf = xmlStrdup(BAD_CAST "");
1369 else
1370 *buf = xmlStrdup(BAD_CAST "local ");
1371 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1372 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1373 *buf = xmlStrcat(*buf, BAD_CAST " '");
1374 *buf = xmlStrcat(*buf, item->name);
1375 *buf = xmlStrcat(*buf, BAD_CAST "'");
1376 }
1377 break;
1378 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1379 xmlSchemaAttributePtr attr;
1380
1381 attr = (xmlSchemaAttributePtr) item;
1382 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
1383 (attr->ref == NULL)) {
1384 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1385 *buf = xmlStrcat(*buf, BAD_CAST " '");
1386 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1387 attr->targetNamespace, attr->name));
1388 FREE_AND_NULL(str)
1389 *buf = xmlStrcat(*buf, BAD_CAST "'");
1390 } else {
1391 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1392 *buf = xmlStrcat(*buf, BAD_CAST " '");
1393 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1394 attr->refNs, attr->ref));
1395 FREE_AND_NULL(str)
1396 *buf = xmlStrcat(*buf, BAD_CAST "'");
1397 }
1398 }
1399 break;
1400 case XML_SCHEMA_TYPE_ELEMENT: {
1401 xmlSchemaElementPtr elem;
1402
1403 elem = (xmlSchemaElementPtr) item;
1404 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
1405 (elem->ref == NULL)) {
1406 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1407 *buf = xmlStrcat(*buf, BAD_CAST " '");
1408 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1409 elem->targetNamespace, elem->name));
1410 *buf = xmlStrcat(*buf, BAD_CAST "'");
1411 }
1412 }
1413 break;
1414 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1415 case XML_SCHEMA_TYPE_IDC_KEY:
1416 case XML_SCHEMA_TYPE_IDC_KEYREF:
1417 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1418 *buf = xmlStrdup(BAD_CAST "unique '");
1419 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1420 *buf = xmlStrdup(BAD_CAST "key '");
1421 else
1422 *buf = xmlStrdup(BAD_CAST "keyRef '");
1423 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1424 *buf = xmlStrcat(*buf, BAD_CAST "'");
1425 break;
1426 case XML_SCHEMA_TYPE_ANY:
1427 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1428 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1429 ((xmlSchemaWildcardPtr) item)->processContents));
1430 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1431 break;
1432 case XML_SCHEMA_FACET_MININCLUSIVE:
1433 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1434 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1435 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1436 case XML_SCHEMA_FACET_TOTALDIGITS:
1437 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1438 case XML_SCHEMA_FACET_PATTERN:
1439 case XML_SCHEMA_FACET_ENUMERATION:
1440 case XML_SCHEMA_FACET_WHITESPACE:
1441 case XML_SCHEMA_FACET_LENGTH:
1442 case XML_SCHEMA_FACET_MAXLENGTH:
1443 case XML_SCHEMA_FACET_MINLENGTH:
1444 *buf = xmlStrdup(BAD_CAST "facet '");
1445 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1446 *buf = xmlStrcat(*buf, BAD_CAST "'");
1447 break;
1448 case XML_SCHEMA_TYPE_NOTATION:
1449 *buf = xmlStrdup(BAD_CAST "notation");
1450 break;
1451 case XML_SCHEMA_TYPE_GROUP: {
1452 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1453 *buf = xmlStrcat(*buf, BAD_CAST " '");
1454 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1455 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1456 ((xmlSchemaModelGroupDefPtr) item)->name));
1457 *buf = xmlStrcat(*buf, BAD_CAST "'");
1458 FREE_AND_NULL(str)
1459 }
1460 break;
1461 case XML_SCHEMA_TYPE_SEQUENCE:
1462 case XML_SCHEMA_TYPE_CHOICE:
1463 case XML_SCHEMA_TYPE_ALL:
1464 case XML_SCHEMA_TYPE_PARTICLE:
1465 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1466 break;
1467 default:
1468 named = 0;
1469 }
1470 } else
1471 named = 0;
1472
1473 if ((named == 0) && (itemNode != NULL)) {
1474 xmlNodePtr elem;
1475
1476 if (itemNode->type == XML_ATTRIBUTE_NODE)
1477 elem = itemNode->parent;
1478 else
1479 elem = itemNode;
1480 *buf = xmlStrdup(BAD_CAST "Element '");
1481 if (elem->ns != NULL) {
1482 *buf = xmlStrcat(*buf,
1483 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1484 FREE_AND_NULL(str)
1485 } else
1486 *buf = xmlStrcat(*buf, elem->name);
1487 *buf = xmlStrcat(*buf, BAD_CAST "'");
1488
1489 }
1490 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1491 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1492 if (itemNode->ns != NULL) {
1493 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1494 itemNode->ns->href, itemNode->name));
1495 FREE_AND_NULL(str)
1496 } else
1497 *buf = xmlStrcat(*buf, itemNode->name);
1498 *buf = xmlStrcat(*buf, BAD_CAST "'");
1499 }
1500 FREE_AND_NULL(str)
1501
1502 return (*buf);
1503}
1504
1505/**
1506 * xmlSchemaFormatFacetEnumSet:
1507 * @buf: the string buffer
1508 * @type: the type holding the enumeration facets
1509 *
1510 * Builds a string consisting of all enumeration elements.
1511 *
1512 * Returns a string of all enumeration elements.
1513 */
1514static const xmlChar *
1515xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1516 xmlChar **buf, xmlSchemaTypePtr type)
1517{
1518 xmlSchemaFacetPtr facet;
1519 xmlSchemaWhitespaceValueType ws;
1520 xmlChar *value = NULL;
1521 int res;
1522
1523 if (*buf != NULL)
1524 xmlFree(*buf);
1525 *buf = NULL;
1526
1527 do {
1528 /*
1529 * Use the whitespace type of the base type.
1530 */
1531 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1532 for (facet = type->facets; facet != NULL; facet = facet->next) {
1533 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1534 continue;
1535 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1536 ws, &value);
1537 if (res == -1) {
1538 xmlSchemaInternalErr(actxt,
1539 "xmlSchemaFormatFacetEnumSet",
1540 "compute the canonical lexical representation");
1541 if (*buf != NULL)
1542 xmlFree(*buf);
1543 *buf = NULL;
1544 return (NULL);
1545 }
1546 if (*buf == NULL)
1547 *buf = xmlStrdup(BAD_CAST "'");
1548 else
1549 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1550 *buf = xmlStrcat(*buf, BAD_CAST value);
1551 *buf = xmlStrcat(*buf, BAD_CAST "'");
1552 if (value != NULL) {
1553 xmlFree((xmlChar *)value);
1554 value = NULL;
1555 }
1556 }
1557 type = type->baseType;
1558 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1559
1560 return ((const xmlChar *) *buf);
1561}
1562
1563/************************************************************************
1564 * *
1565 * Error functions *
1566 * *
1567 ************************************************************************/
1568
1569#if 0
1570static void
1571xmlSchemaErrMemory(const char *msg)
1572{
1573 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1574 msg);
1575}
1576#endif
1577
1578/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001579 * xmlSchemaPErrMemory:
1580 * @node: a context node
1581 * @extra: extra informations
1582 *
1583 * Handle an out of memory condition
1584 */
1585static void
1586xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1587 const char *extra, xmlNodePtr node)
1588{
1589 if (ctxt != NULL)
1590 ctxt->nberrors++;
1591 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1592 extra);
1593}
1594
1595/**
1596 * xmlSchemaPErr:
1597 * @ctxt: the parsing context
1598 * @node: the context node
1599 * @error: the error code
1600 * @msg: the error message
1601 * @str1: extra data
1602 * @str2: extra data
1603 *
1604 * Handle a parser error
1605 */
1606static void
1607xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1608 const char *msg, const xmlChar * str1, const xmlChar * str2)
1609{
1610 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001611 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001612 void *data = NULL;
1613
1614 if (ctxt != NULL) {
1615 ctxt->nberrors++;
1616 channel = ctxt->error;
1617 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001618 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001619 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001620 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001621 error, XML_ERR_ERROR, NULL, 0,
1622 (const char *) str1, (const char *) str2, NULL, 0, 0,
1623 msg, str1, str2);
1624}
1625
1626/**
1627 * xmlSchemaPErr2:
1628 * @ctxt: the parsing context
1629 * @node: the context node
1630 * @node: the current child
1631 * @error: the error code
1632 * @msg: the error message
1633 * @str1: extra data
1634 * @str2: extra data
1635 *
1636 * Handle a parser error
1637 */
1638static void
1639xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1640 xmlNodePtr child, int error,
1641 const char *msg, const xmlChar * str1, const xmlChar * str2)
1642{
1643 if (child != NULL)
1644 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1645 else
1646 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1647}
1648
Daniel Veillard01fa6152004-06-29 17:04:39 +00001649
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001650/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001651 * xmlSchemaPErrExt:
1652 * @ctxt: the parsing context
1653 * @node: the context node
1654 * @error: the error code
1655 * @strData1: extra data
1656 * @strData2: extra data
1657 * @strData3: extra data
1658 * @msg: the message
1659 * @str1: extra parameter for the message display
1660 * @str2: extra parameter for the message display
1661 * @str3: extra parameter for the message display
1662 * @str4: extra parameter for the message display
1663 * @str5: extra parameter for the message display
1664 *
1665 * Handle a parser error
1666 */
1667static void
1668xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1669 const xmlChar * strData1, const xmlChar * strData2,
1670 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1671 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1672 const xmlChar * str5)
1673{
1674
1675 xmlGenericErrorFunc channel = NULL;
1676 xmlStructuredErrorFunc schannel = NULL;
1677 void *data = NULL;
1678
1679 if (ctxt != NULL) {
1680 ctxt->nberrors++;
1681 channel = ctxt->error;
1682 data = ctxt->userData;
1683 schannel = ctxt->serror;
1684 }
1685 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1686 error, XML_ERR_ERROR, NULL, 0,
1687 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001688 (const char *) strData3, 0, 0, msg, str1, str2,
1689 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001690}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001691
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001692/************************************************************************
1693 * *
1694 * Allround error functions *
1695 * *
1696 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001697
1698/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001699 * xmlSchemaVTypeErrMemory:
1700 * @node: a context node
1701 * @extra: extra informations
1702 *
1703 * Handle an out of memory condition
1704 */
1705static void
1706xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1707 const char *extra, xmlNodePtr node)
1708{
1709 if (ctxt != NULL) {
1710 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001711 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001712 }
1713 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1714 extra);
1715}
1716
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001717static void
1718xmlSchemaPSimpleInternalErr(xmlNodePtr node,
1719 const char *msg, const xmlChar *str)
1720{
1721 __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
1722 msg, (const char *) str);
1723}
1724
1725#define WXS_ERROR_TYPE_ERROR 1
1726#define WXS_ERROR_TYPE_WARNING 2
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001727/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001728 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001729 * @ctxt: the validation context
1730 * @node: the context node
1731 * @error: the error code
1732 * @msg: the error message
1733 * @str1: extra data
1734 * @str2: extra data
1735 * @str3: extra data
1736 *
1737 * Handle a validation error
1738 */
1739static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001740xmlSchemaErr3Line(xmlSchemaAbstractCtxtPtr ctxt,
1741 xmlErrorLevel errorLevel,
1742 int error, xmlNodePtr node, int line, const char *msg,
1743 const xmlChar *str1, const xmlChar *str2,
1744 const xmlChar *str3)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001745{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001746 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001747 xmlGenericErrorFunc channel = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001748 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001749
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001750 if (ctxt != NULL) {
1751 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1752 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00001753 const char *file = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001754 if (errorLevel != XML_ERR_WARNING) {
1755 vctxt->nberrors++;
1756 vctxt->err = error;
1757 channel = vctxt->error;
1758 } else {
1759 channel = vctxt->warning;
1760 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001761 schannel = vctxt->serror;
1762 data = vctxt->userData;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001763
1764 /*
1765 * Error node. If we specify a line number, then
1766 * do not channel any node to the error function.
1767 */
1768 if (line == 0) {
1769 if ((node == NULL) &&
1770 (vctxt->depth >= 0) &&
1771 (vctxt->inode != NULL)) {
1772 node = vctxt->inode->node;
1773 }
1774 /*
1775 * Get filename and line if no node-tree.
1776 */
1777 if ((node == NULL) &&
1778 (vctxt->parserCtxt != NULL) &&
1779 (vctxt->parserCtxt->input != NULL)) {
1780 file = vctxt->parserCtxt->input->filename;
1781 line = vctxt->parserCtxt->input->line;
1782 }
1783 } else {
1784 /*
1785 * Override the given node's (if any) position
1786 * and channel only the given line number.
1787 */
1788 node = NULL;
1789 /*
1790 * Get filename.
1791 */
1792 if (vctxt->doc != NULL)
1793 file = (const char *) vctxt->doc->URL;
1794 else if ((vctxt->parserCtxt != NULL) &&
1795 (vctxt->parserCtxt->input != NULL))
1796 file = vctxt->parserCtxt->input->filename;
1797 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001798 __xmlRaiseError(schannel, channel, data, ctxt,
1799 node, XML_FROM_SCHEMASV,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001800 error, errorLevel, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001801 (const char *) str1, (const char *) str2,
1802 (const char *) str3, 0, 0, msg, str1, str2, str3);
1803
1804 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
1805 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001806 if (errorLevel != XML_ERR_WARNING) {
1807 pctxt->nberrors++;
1808 pctxt->err = error;
1809 channel = pctxt->error;
1810 } else {
1811 channel = pctxt->warning;
1812 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001813 schannel = pctxt->serror;
1814 data = pctxt->userData;
1815 __xmlRaiseError(schannel, channel, data, ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001816 node, XML_FROM_SCHEMASP, error,
1817 errorLevel, NULL, 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001818 (const char *) str1, (const char *) str2,
1819 (const char *) str3, 0, 0, msg, str1, str2, str3);
1820 } else {
1821 TODO
1822 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001823 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001824}
1825
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001826/**
1827 * xmlSchemaErr3:
1828 * @ctxt: the validation context
1829 * @node: the context node
1830 * @error: the error code
1831 * @msg: the error message
1832 * @str1: extra data
1833 * @str2: extra data
1834 * @str3: extra data
1835 *
1836 * Handle a validation error
1837 */
1838static void
1839xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
1840 int error, xmlNodePtr node, const char *msg,
1841 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
1842{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001843 xmlSchemaErr3Line(actxt, XML_ERR_ERROR, error, node, 0,
1844 msg, str1, str2, str3);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001845}
1846
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001847static void
1848xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
1849 int error, xmlNodePtr node, const char *msg,
1850 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001851{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001852 xmlSchemaErr3(actxt, error, node, msg, str1, str2, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001853}
1854
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001855static xmlChar *
1856xmlSchemaFormatNodeForError(xmlChar ** msg,
1857 xmlSchemaAbstractCtxtPtr actxt,
1858 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001859{
1860 xmlChar *str = NULL;
1861
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001862 if (node != NULL) {
1863 /*
1864 * Work on tree nodes.
1865 */
1866 if (node->type == XML_ATTRIBUTE_NODE) {
1867 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001868
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001869 *msg = xmlStrdup(BAD_CAST "Element '");
1870 if (elem->ns != NULL)
1871 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1872 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001873 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001874 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1875 NULL, elem->name));
1876 FREE_AND_NULL(str);
1877 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1878 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1879 } else {
1880 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001881 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001882 if (node->ns != NULL)
1883 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1884 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001885 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001886 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1887 NULL, node->name));
1888 FREE_AND_NULL(str);
1889 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1890 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1891 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
1892 /*
1893 * Work on node infos.
1894 */
1895 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
1896 xmlSchemaNodeInfoPtr ielem =
1897 vctxt->elemInfos[vctxt->depth];
1898
1899 *msg = xmlStrdup(BAD_CAST "Element '");
1900 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1901 ielem->nsName, ielem->localName));
1902 FREE_AND_NULL(str);
1903 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1904 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1905 } else {
1906 *msg = xmlStrdup(BAD_CAST "Element '");
1907 }
1908 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1909 vctxt->inode->nsName, vctxt->inode->localName));
1910 FREE_AND_NULL(str);
1911 *msg = xmlStrcat(*msg, BAD_CAST "': ");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001912 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
1913 /*
1914 * Hmm, no node while parsing?
1915 * Return an empty string, in case NULL will break something.
1916 */
1917 *msg = xmlStrdup(BAD_CAST "");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001918 } else {
1919 TODO
1920 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001921 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001922 /*
1923 * VAL TODO: The output of the given schema component is currently
1924 * disabled.
1925 */
1926#if 0
1927 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
1928 *msg = xmlStrcat(*msg, BAD_CAST " [");
1929 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
1930 NULL, type, NULL, 0));
1931 FREE_AND_NULL(str)
1932 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001933 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001934#endif
1935 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001936}
1937
Daniel Veillardc0826a72004-08-10 14:17:33 +00001938static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001939xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001940 const char *funcName,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001941 const char *message,
1942 const xmlChar *str1,
1943 const xmlChar *str2)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001944{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001945 xmlChar *msg = NULL;
1946
1947 msg = xmlStrdup(BAD_CAST "Internal error: ");
1948 msg = xmlStrcat(msg, BAD_CAST funcName);
1949 msg = xmlStrcat(msg, BAD_CAST ", ");
1950 msg = xmlStrcat(msg, BAD_CAST message);
1951 msg = xmlStrcat(msg, BAD_CAST ".\n");
1952
1953 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
1954 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001955 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001956
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001957 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001958 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001959 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001960
1961 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001962}
1963
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001964static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001965xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1966 const char *funcName,
1967 const char *message)
1968{
1969 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
1970}
1971
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001972#if 0
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001973static void
1974xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
1975 const char *funcName,
1976 const char *message,
1977 const xmlChar *str1,
1978 const xmlChar *str2)
1979{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001980 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001981 str1, str2);
1982}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00001983#endif
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001984
1985static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001986xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
1987 xmlParserErrors error,
1988 xmlNodePtr node,
1989 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1990 const char *message,
1991 const xmlChar *str1,
1992 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001993{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001994 xmlChar *msg = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001995
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001996 xmlSchemaFormatNodeForError(&msg, actxt, node);
1997 msg = xmlStrcat(msg, (const xmlChar *) message);
1998 msg = xmlStrcat(msg, BAD_CAST ".\n");
1999 xmlSchemaErr(actxt, error, node,
2000 (const char *) msg, str1, str2);
2001 FREE_AND_NULL(msg)
2002}
2003
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002004static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002005xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2006 xmlParserErrors error,
2007 xmlNodePtr node,
2008 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2009 const char *message,
2010 const xmlChar *str1,
2011 const xmlChar *str2,
2012 const xmlChar *str3)
2013{
2014 xmlChar *msg = NULL;
2015
2016 xmlSchemaFormatNodeForError(&msg, actxt, node);
2017 msg = xmlStrcat(msg, (const xmlChar *) message);
2018 msg = xmlStrcat(msg, BAD_CAST ".\n");
2019
2020 /* URGENT TODO: Set the error code to something sane. */
2021 xmlSchemaErr3Line(actxt, XML_ERR_WARNING, error, node, 0,
2022 (const char *) msg, str1, str2, str3);
2023
2024 FREE_AND_NULL(msg)
2025}
2026
2027
2028
2029static void
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002030xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2031 xmlParserErrors error,
2032 xmlSchemaPSVIIDCNodePtr idcNode,
2033 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2034 const char *message,
2035 const xmlChar *str1,
2036 const xmlChar *str2)
2037{
2038 xmlChar *msg = NULL, *qname = NULL;
2039
2040 msg = xmlStrdup(BAD_CAST "Element '%s': ");
2041 msg = xmlStrcat(msg, (const xmlChar *) message);
2042 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002043 xmlSchemaErr3Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002044 error, NULL, idcNode->nodeLine, (const char *) msg,
2045 xmlSchemaFormatQName(&qname,
2046 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2047 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2048 str1, str2);
2049 FREE_AND_NULL(qname);
2050 FREE_AND_NULL(msg);
2051}
2052
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002053static int
2054xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2055 xmlNodePtr node)
2056{
2057 if (node != NULL)
2058 return (node->type);
2059 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2060 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2061 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2062 return (-1);
2063}
2064
2065static int
2066xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2067{
2068 switch (item->type) {
2069 case XML_SCHEMA_TYPE_COMPLEX:
2070 case XML_SCHEMA_TYPE_SIMPLE:
2071 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2072 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002073 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002074 case XML_SCHEMA_TYPE_GROUP:
2075 return (1);
2076 case XML_SCHEMA_TYPE_ELEMENT:
2077 if ( ((xmlSchemaElementPtr) item)->flags &
2078 XML_SCHEMAS_ELEM_GLOBAL)
2079 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002080 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002081 case XML_SCHEMA_TYPE_ATTRIBUTE:
2082 if ( ((xmlSchemaAttributePtr) item)->flags &
2083 XML_SCHEMAS_ATTR_GLOBAL)
2084 return(1);
2085 break;
2086 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002087 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002088 return(1);
2089 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00002090 return (0);
2091}
2092
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002093static void
2094xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2095 xmlParserErrors error,
2096 xmlNodePtr node,
2097 const xmlChar *value,
2098 xmlSchemaTypePtr type,
2099 int displayValue)
2100{
2101 xmlChar *msg = NULL;
2102
2103 xmlSchemaFormatNodeForError(&msg, actxt, node);
2104
2105 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2106 XML_ATTRIBUTE_NODE))
2107 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2108 else
2109 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2110 "value of ");
2111
2112 if (! xmlSchemaIsGlobalItem(type))
2113 msg = xmlStrcat(msg, BAD_CAST "the local ");
2114 else
2115 msg = xmlStrcat(msg, BAD_CAST "the ");
2116
2117 if (VARIETY_ATOMIC(type))
2118 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2119 else if (VARIETY_LIST(type))
2120 msg = xmlStrcat(msg, BAD_CAST "list type");
2121 else if (VARIETY_UNION(type))
2122 msg = xmlStrcat(msg, BAD_CAST "union type");
2123
2124 if (xmlSchemaIsGlobalItem(type)) {
2125 xmlChar *str = NULL;
2126 msg = xmlStrcat(msg, BAD_CAST " '");
2127 if (type->builtInType != 0) {
2128 msg = xmlStrcat(msg, BAD_CAST "xs:");
2129 msg = xmlStrcat(msg, type->name);
2130 } else
2131 msg = xmlStrcat(msg,
2132 xmlSchemaFormatQName(&str,
2133 type->targetNamespace, type->name));
2134 msg = xmlStrcat(msg, BAD_CAST "'");
2135 FREE_AND_NULL(str);
2136 }
2137 msg = xmlStrcat(msg, BAD_CAST ".\n");
2138 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2139 XML_ATTRIBUTE_NODE))
2140 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2141 else
2142 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2143 FREE_AND_NULL(msg)
2144}
2145
Daniel Veillardc0826a72004-08-10 14:17:33 +00002146static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002147xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2148 xmlSchemaNodeInfoPtr ni,
2149 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002150{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002151 if (node != NULL) {
2152 if (node->ns != NULL)
2153 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2154 else
2155 return (xmlSchemaFormatQName(str, NULL, node->name));
2156 } else if (ni != NULL)
2157 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2158 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002159}
2160
Daniel Veillardc0826a72004-08-10 14:17:33 +00002161static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002162xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2163 xmlParserErrors error,
2164 xmlSchemaAttrInfoPtr ni,
2165 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002166{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002167 xmlChar *msg = NULL, *str = NULL;
2168
2169 xmlSchemaFormatNodeForError(&msg, actxt, node);
2170 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2171 xmlSchemaErr(actxt, error, node, (const char *) msg,
2172 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2173 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002174 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002175 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002176}
2177
Daniel Veillardc0826a72004-08-10 14:17:33 +00002178static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002179xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2180 xmlParserErrors error,
2181 xmlNodePtr node,
2182 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002183 const char *message,
2184 int nbval,
2185 int nbneg,
2186 xmlChar **values)
2187{
2188 xmlChar *str = NULL, *msg = NULL;
2189 xmlChar *localName, *nsName;
2190 const xmlChar *cur, *end;
Daniel Veillard77005e62005-07-19 16:26:18 +00002191 int i, is_not;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002192
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002193 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002194 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002195 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002196 /*
2197 * Note that is does not make sense to report that we have a
2198 * wildcard here, since the wildcard might be unfolded into
2199 * multiple transitions.
2200 */
2201 if (nbval + nbneg > 0) {
2202 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002203 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002204 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002205 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002206 nsName = NULL;
2207
2208 for (i = 0; i < nbval + nbneg; i++) {
2209 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00002210 if (cur == NULL)
2211 continue;
2212 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2213 (cur[3] == ' ')) {
2214 is_not = 1;
2215 cur += 4;
Daniel Veillard6e65e152005-08-09 11:09:52 +00002216 str = xmlStrcat(str, BAD_CAST "##other");
Daniel Veillard77005e62005-07-19 16:26:18 +00002217 } else {
2218 is_not = 0;
2219 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002220 /*
2221 * Get the local name.
2222 */
2223 localName = NULL;
2224
2225 end = cur;
2226 if (*end == '*') {
2227 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002228 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002229 } else {
2230 while ((*end != 0) && (*end != '|'))
2231 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002232 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002233 }
2234 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002235 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002236 /*
2237 * Skip "*|*" if they come with negated expressions, since
2238 * they represent the same negated wildcard.
2239 */
2240 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2241 /*
2242 * Get the namespace name.
2243 */
2244 cur = end;
2245 if (*end == '*') {
2246 nsName = xmlStrdup(BAD_CAST "{*}");
2247 } else {
2248 while (*end != 0)
2249 end++;
2250
2251 if (i >= nbval)
2252 nsName = xmlStrdup(BAD_CAST "{##other:");
2253 else
2254 nsName = xmlStrdup(BAD_CAST "{");
2255
2256 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2257 nsName = xmlStrcat(nsName, BAD_CAST "}");
2258 }
2259 str = xmlStrcat(str, BAD_CAST nsName);
2260 FREE_AND_NULL(nsName)
2261 } else {
2262 FREE_AND_NULL(localName);
2263 continue;
2264 }
2265 }
2266 str = xmlStrcat(str, BAD_CAST localName);
2267 FREE_AND_NULL(localName);
2268
2269 if (i < nbval + nbneg -1)
2270 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00002271 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002272 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002273 msg = xmlStrcat(msg, BAD_CAST str);
2274 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002275 } else
2276 msg = xmlStrcat(msg, BAD_CAST "\n");
2277 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002278 xmlFree(msg);
2279}
2280
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002281static void
2282xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2283 xmlParserErrors error,
2284 xmlNodePtr node,
2285 const xmlChar *value,
2286 unsigned long length,
2287 xmlSchemaTypePtr type,
2288 xmlSchemaFacetPtr facet,
2289 const char *message,
2290 const xmlChar *str1,
2291 const xmlChar *str2)
2292{
2293 xmlChar *str = NULL, *msg = NULL;
2294 xmlSchemaTypeType facetType;
2295 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2296
2297 xmlSchemaFormatNodeForError(&msg, actxt, node);
2298 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2299 facetType = XML_SCHEMA_FACET_ENUMERATION;
2300 /*
2301 * If enumerations are validated, one must not expect the
2302 * facet to be given.
2303 */
2304 } else
2305 facetType = facet->type;
2306 msg = xmlStrcat(msg, BAD_CAST "[");
2307 msg = xmlStrcat(msg, BAD_CAST "facet '");
2308 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2309 msg = xmlStrcat(msg, BAD_CAST "'] ");
2310 if (message == NULL) {
2311 /*
2312 * Use a default message.
2313 */
2314 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2315 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2316 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2317
2318 char len[25], actLen[25];
2319
2320 /* FIXME, TODO: What is the max expected string length of the
2321 * this value?
2322 */
2323 if (nodeType == XML_ATTRIBUTE_NODE)
2324 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2325 else
2326 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2327
2328 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2329 snprintf(actLen, 24, "%lu", length);
2330
2331 if (facetType == XML_SCHEMA_FACET_LENGTH)
2332 msg = xmlStrcat(msg,
2333 BAD_CAST "this differs from the allowed length of '%s'.\n");
2334 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2335 msg = xmlStrcat(msg,
2336 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2337 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2338 msg = xmlStrcat(msg,
2339 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2340
2341 if (nodeType == XML_ATTRIBUTE_NODE)
2342 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2343 value, (const xmlChar *) actLen, (const xmlChar *) len);
2344 else
2345 xmlSchemaErr(actxt, error, node, (const char *) msg,
2346 (const xmlChar *) actLen, (const xmlChar *) len);
2347
2348 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2349 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2350 "of the set {%s}.\n");
2351 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2352 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2353 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2354 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2355 "by the pattern '%s'.\n");
2356 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2357 facet->value);
2358 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2359 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2360 "minimum value allowed ('%s').\n");
2361 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2362 facet->value);
2363 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2364 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2365 "maximum value allowed ('%s').\n");
2366 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2367 facet->value);
2368 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2369 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2370 "'%s'.\n");
2371 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2372 facet->value);
2373 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2374 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2375 "'%s'.\n");
2376 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2377 facet->value);
2378 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2379 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2380 "digits than are allowed ('%s').\n");
2381 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2382 facet->value);
2383 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2384 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2385 "digits than are allowed ('%s').\n");
2386 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2387 facet->value);
2388 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2389 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2390 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2391 } else {
2392 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2393 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2394 }
2395 } else {
2396 msg = xmlStrcat(msg, (const xmlChar *) message);
2397 msg = xmlStrcat(msg, BAD_CAST ".\n");
2398 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2399 }
2400 FREE_AND_NULL(str)
2401 xmlFree(msg);
2402}
2403
2404#define VERROR(err, type, msg) \
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002405 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002406
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002407#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002408
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002409#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2410#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002411
2412#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2413
2414
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002415/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002416 * xmlSchemaPMissingAttrErr:
2417 * @ctxt: the schema validation context
2418 * @ownerDes: the designation of the owner
2419 * @ownerName: the name of the owner
2420 * @ownerItem: the owner as a schema object
2421 * @ownerElem: the owner as an element node
2422 * @node: the parent element node of the missing attribute node
2423 * @type: the corresponding type of the attribute node
2424 *
2425 * Reports an illegal attribute.
2426 */
2427static void
2428xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002429 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002430 xmlSchemaTypePtr ownerItem,
2431 xmlNodePtr ownerElem,
2432 const char *name,
2433 const char *message)
2434{
2435 xmlChar *des = NULL;
2436
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002437 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2438
Daniel Veillardc0826a72004-08-10 14:17:33 +00002439 if (message != NULL)
2440 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002441 else
2442 xmlSchemaPErr(ctxt, ownerElem, error,
2443 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002444 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002445 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002446}
2447
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002448
Daniel Veillardc0826a72004-08-10 14:17:33 +00002449/**
2450 * xmlSchemaPResCompAttrErr:
2451 * @ctxt: the schema validation context
2452 * @error: the error code
2453 * @ownerDes: the designation of the owner
2454 * @ownerItem: the owner as a schema object
2455 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002456 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002457 * @refName: the referenced local name
2458 * @refURI: the referenced namespace URI
2459 * @message: optional message
2460 *
2461 * Used to report QName attribute values that failed to resolve
2462 * to schema components.
2463 */
2464static void
2465xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002466 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002467 xmlSchemaTypePtr ownerItem,
2468 xmlNodePtr ownerElem,
2469 const char *name,
2470 const xmlChar *refName,
2471 const xmlChar *refURI,
2472 xmlSchemaTypeType refType,
2473 const char *refTypeStr)
2474{
2475 xmlChar *des = NULL, *strA = NULL;
2476
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002477 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002478 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002479 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2480 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002481 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002482 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2483 "%s.\n", BAD_CAST des, BAD_CAST name,
2484 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002485 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002486 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002487 FREE_AND_NULL(strA)
2488}
2489
William M. Brack2f2a6632004-08-20 23:09:47 +00002490/**
2491 * xmlSchemaPCustomAttrErr:
2492 * @ctxt: the schema parser context
2493 * @error: the error code
2494 * @ownerDes: the designation of the owner
2495 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002496 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002497 *
2498 * Reports an illegal attribute during the parse.
2499 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002500static void
2501xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002502 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002503 xmlChar **ownerDes,
2504 xmlSchemaTypePtr ownerItem,
2505 xmlAttrPtr attr,
2506 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002507{
2508 xmlChar *des = NULL;
2509
2510 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002511 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002512 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002513 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002514 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002515 } else
2516 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002517 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002518 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002519 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2520 if (ownerDes == NULL)
2521 FREE_AND_NULL(des);
2522}
2523
2524/**
2525 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002526 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002527 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002528 * @ownerDes: the designation of the attribute's owner
2529 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002530 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002531 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002532 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002533 */
2534static void
2535xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002536 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002537 xmlChar **ownerDes,
2538 xmlSchemaTypePtr ownerItem,
2539 xmlAttrPtr attr)
2540{
2541 xmlChar *des = NULL, *strA = NULL;
2542
2543 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002544 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002545 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002546 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002547 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002548 } else
2549 des = *ownerDes;
2550 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2551 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2552 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002553 if (ownerDes == NULL)
2554 FREE_AND_NULL(des);
2555 FREE_AND_NULL(strA);
2556}
2557
William M. Brack2f2a6632004-08-20 23:09:47 +00002558/**
2559 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002560 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002561 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002562 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002563 * @itemElem: the node of the schema item
2564 *
2565 * Creates a designation for an item.
2566 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002567static void
2568xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002569 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002570 xmlSchemaTypePtr item,
2571 xmlNodePtr itemElem)
2572{
2573 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002574 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002575 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002576 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002577 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002578 } else
2579 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002580}
2581
William M. Brack2f2a6632004-08-20 23:09:47 +00002582/**
2583 * xmlSchemaPCustomErr:
2584 * @ctxt: the schema parser context
2585 * @error: the error code
2586 * @itemDes: the designation of the schema item
2587 * @item: the schema item
2588 * @itemElem: the node of the schema item
2589 * @message: the error message
2590 * @str1: an optional param for the error message
2591 * @str2: an optional param for the error message
2592 * @str3: an optional param for the error message
2593 *
2594 * Reports an error during parsing.
2595 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002596static void
2597xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002598 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002599 xmlChar **itemDes,
2600 xmlSchemaTypePtr item,
2601 xmlNodePtr itemElem,
2602 const char *message,
2603 const xmlChar *str1,
2604 const xmlChar *str2,
2605 const xmlChar *str3)
2606{
2607 xmlChar *des = NULL, *msg = NULL;
2608
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002609 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002610 msg = xmlStrdup(BAD_CAST "%s: ");
2611 msg = xmlStrcat(msg, (const xmlChar *) message);
2612 msg = xmlStrcat(msg, BAD_CAST ".\n");
2613 if ((itemElem == NULL) && (item != NULL))
2614 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002615 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002616 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2617 if (itemDes == NULL)
2618 FREE_AND_NULL(des);
2619 FREE_AND_NULL(msg);
2620}
2621
William M. Brack2f2a6632004-08-20 23:09:47 +00002622/**
2623 * xmlSchemaPCustomErr:
2624 * @ctxt: the schema parser context
2625 * @error: the error code
2626 * @itemDes: the designation of the schema item
2627 * @item: the schema item
2628 * @itemElem: the node of the schema item
2629 * @message: the error message
2630 * @str1: the optional param for the error message
2631 *
2632 * Reports an error during parsing.
2633 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002634static void
2635xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002636 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002637 xmlChar **itemDes,
2638 xmlSchemaTypePtr item,
2639 xmlNodePtr itemElem,
2640 const char *message,
2641 const xmlChar *str1)
2642{
2643 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2644 str1, NULL, NULL);
2645}
2646
William M. Brack2f2a6632004-08-20 23:09:47 +00002647/**
2648 * xmlSchemaPAttrUseErr:
2649 * @ctxt: the schema parser context
2650 * @error: the error code
2651 * @itemDes: the designation of the schema type
2652 * @item: the schema type
2653 * @itemElem: the node of the schema type
2654 * @attr: the invalid schema attribute
2655 * @message: the error message
2656 * @str1: the optional param for the error message
2657 *
2658 * Reports an attribute use error during parsing.
2659 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002660static void
2661xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002662 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002663 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002664 const xmlSchemaAttributePtr attr,
2665 const char *message,
2666 const xmlChar *str1)
2667{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002668 xmlChar *str = NULL, *msg = NULL;
2669 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2670 msg = xmlStrcat(msg, BAD_CAST ", ");
2671 msg = xmlStrcat(msg,
2672 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2673 (xmlSchemaTypePtr) attr, NULL));
2674 FREE_AND_NULL(str);
2675 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002676 msg = xmlStrcat(msg, (const xmlChar *) message);
2677 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002678 xmlSchemaPErr(ctxt, attr->node, error,
2679 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002680 xmlFree(msg);
2681}
2682
William M. Brack2f2a6632004-08-20 23:09:47 +00002683/**
2684 * xmlSchemaPIllegalFacetAtomicErr:
2685 * @ctxt: the schema parser context
2686 * @error: the error code
2687 * @itemDes: the designation of the type
2688 * @item: the schema type
2689 * @baseItem: the base type of type
2690 * @facet: the illegal facet
2691 *
2692 * Reports an illegal facet for atomic simple types.
2693 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002694static void
2695xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002696 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002697 xmlChar **itemDes,
2698 xmlSchemaTypePtr item,
2699 xmlSchemaTypePtr baseItem,
2700 xmlSchemaFacetPtr facet)
2701{
2702 xmlChar *des = NULL, *strT = NULL;
2703
2704 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2705 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2706 "%s: The facet '%s' is not allowed on types derived from the "
2707 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002708 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002709 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002710 NULL, NULL);
2711 if (itemDes == NULL)
2712 FREE_AND_NULL(des);
2713 FREE_AND_NULL(strT);
2714}
2715
William M. Brack2f2a6632004-08-20 23:09:47 +00002716/**
2717 * xmlSchemaPIllegalFacetListUnionErr:
2718 * @ctxt: the schema parser context
2719 * @error: the error code
2720 * @itemDes: the designation of the schema item involved
2721 * @item: the schema item involved
2722 * @facet: the illegal facet
2723 *
2724 * Reports an illegal facet for <list> and <union>.
2725 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002726static void
2727xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002728 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002729 xmlChar **itemDes,
2730 xmlSchemaTypePtr item,
2731 xmlSchemaFacetPtr facet)
2732{
2733 xmlChar *des = NULL, *strT = NULL;
2734
2735 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002736 xmlSchemaPErr(ctxt, item->node, error,
2737 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002738 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002739 if (itemDes == NULL)
2740 FREE_AND_NULL(des);
2741 FREE_AND_NULL(strT);
2742}
2743
2744/**
2745 * xmlSchemaPMutualExclAttrErr:
2746 * @ctxt: the schema validation context
2747 * @error: the error code
2748 * @elemDes: the designation of the parent element node
2749 * @attr: the bad attribute node
2750 * @type: the corresponding type of the attribute node
2751 *
2752 * Reports an illegal attribute.
2753 */
2754static void
2755xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2756 xmlParserErrors error,
2757 xmlChar **ownerDes,
2758 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002759 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002760 const char *name1,
2761 const char *name2)
2762{
2763 xmlChar *des = NULL;
2764
2765 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002766 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002767 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002768 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002769 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002770 } else
2771 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002772 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002773 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002774 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2775 if (ownerDes == NULL)
2776 FREE_AND_NULL(des)
2777}
2778
2779/**
2780 * xmlSchemaPSimpleTypeErr:
2781 * @ctxt: the schema validation context
2782 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002783 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002784 * @ownerDes: the designation of the owner
2785 * @ownerItem: the schema object if existent
2786 * @node: the validated node
2787 * @value: the validated value
2788 *
2789 * Reports a simple type validation error.
2790 * TODO: Should this report the value of an element as well?
2791 */
2792static void
2793xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2794 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002795 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002796 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002797 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002798 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002799 const xmlChar *value,
2800 const char *message,
2801 const xmlChar *str1,
2802 const xmlChar *str2)
2803{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002804 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002805
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00002806 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002807 if (message == NULL) {
2808 /*
2809 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002810 */
2811 if (type != NULL) {
2812 if (node->type == XML_ATTRIBUTE_NODE)
2813 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2814 else
2815 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2816 "valid value of ");
2817 if (! xmlSchemaIsGlobalItem(type))
2818 msg = xmlStrcat(msg, BAD_CAST "the local ");
2819 else
2820 msg = xmlStrcat(msg, BAD_CAST "the ");
2821
2822 if (VARIETY_ATOMIC(type))
2823 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2824 else if (VARIETY_LIST(type))
2825 msg = xmlStrcat(msg, BAD_CAST "list type");
2826 else if (VARIETY_UNION(type))
2827 msg = xmlStrcat(msg, BAD_CAST "union type");
2828
2829 if (xmlSchemaIsGlobalItem(type)) {
2830 xmlChar *str = NULL;
2831 msg = xmlStrcat(msg, BAD_CAST " '");
2832 if (type->builtInType != 0) {
2833 msg = xmlStrcat(msg, BAD_CAST "xs:");
2834 msg = xmlStrcat(msg, type->name);
2835 } else
2836 msg = xmlStrcat(msg,
2837 xmlSchemaFormatQName(&str,
2838 type->targetNamespace, type->name));
2839 msg = xmlStrcat(msg, BAD_CAST "'.");
2840 FREE_AND_NULL(str);
2841 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002842 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002843 if (node->type == XML_ATTRIBUTE_NODE)
2844 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2845 else
2846 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2847 "valid.");
2848 }
2849 if (expected) {
2850 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2851 msg = xmlStrcat(msg, BAD_CAST expected);
2852 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2853 } else
2854 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002855 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002856 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2857 else
2858 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2859 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00002860 msg = xmlStrcat(msg, BAD_CAST message);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00002861 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002862 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00002863 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002864 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002865 /* Cleanup. */
2866 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002867}
2868
William M. Brack2f2a6632004-08-20 23:09:47 +00002869/**
2870 * xmlSchemaPContentErr:
2871 * @ctxt: the schema parser context
2872 * @error: the error code
2873 * @onwerDes: the designation of the holder of the content
2874 * @ownerItem: the owner item of the holder of the content
2875 * @ownerElem: the node of the holder of the content
2876 * @child: the invalid child node
2877 * @message: the optional error message
2878 * @content: the optional string describing the correct content
2879 *
2880 * Reports an error concerning the content of a schema element.
2881 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002882static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002883xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002884 xmlParserErrors error,
2885 xmlChar **ownerDes,
2886 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002887 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002888 xmlNodePtr child,
2889 const char *message,
2890 const char *content)
2891{
2892 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002893
Daniel Veillardc0826a72004-08-10 14:17:33 +00002894 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002895 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002896 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002897 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002898 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002899 } else
2900 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002901 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002902 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2903 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002904 BAD_CAST des, BAD_CAST message);
2905 else {
2906 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002907 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2908 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002909 BAD_CAST des, BAD_CAST content);
2910 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002911 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2912 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002913 BAD_CAST des, NULL);
2914 }
2915 }
2916 if (ownerDes == NULL)
2917 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002918}
2919
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002920/************************************************************************
2921 * *
2922 * Streamable error functions *
2923 * *
2924 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002925
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002926
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002927
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002928
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002929/************************************************************************
2930 * *
2931 * Validation helper functions *
2932 * *
2933 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002934
Daniel Veillardc0826a72004-08-10 14:17:33 +00002935
Daniel Veillard4255d502002-04-16 15:50:10 +00002936/************************************************************************
2937 * *
2938 * Allocation functions *
2939 * *
2940 ************************************************************************/
2941
2942/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002943 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002944 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002945 *
2946 * Allocate a new Schema structure.
2947 *
2948 * Returns the newly allocated structure or NULL in case or error
2949 */
2950static xmlSchemaPtr
2951xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2952{
2953 xmlSchemaPtr ret;
2954
2955 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2956 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002957 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002958 return (NULL);
2959 }
2960 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002961 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002962 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002963
2964 return (ret);
2965}
2966
2967/**
2968 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002969 *
2970 * Allocate a new Facet structure.
2971 *
2972 * Returns the newly allocated structure or NULL in case or error
2973 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002974xmlSchemaFacetPtr
2975xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002976{
2977 xmlSchemaFacetPtr ret;
2978
2979 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2980 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002981 return (NULL);
2982 }
2983 memset(ret, 0, sizeof(xmlSchemaFacet));
2984
2985 return (ret);
2986}
2987
2988/**
2989 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002990 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002991 * @node: a node
2992 *
2993 * Allocate a new annotation structure.
2994 *
2995 * Returns the newly allocated structure or NULL in case or error
2996 */
2997static xmlSchemaAnnotPtr
2998xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2999{
3000 xmlSchemaAnnotPtr ret;
3001
3002 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3003 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003004 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00003005 return (NULL);
3006 }
3007 memset(ret, 0, sizeof(xmlSchemaAnnot));
3008 ret->content = node;
3009 return (ret);
3010}
3011
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003012static xmlSchemaItemListPtr
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003013xmlSchemaItemListCreate(void)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003014{
3015 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003016
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003017 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3018 if (ret == NULL) {
3019 xmlSchemaPErrMemory(NULL,
3020 "allocating an item list structure", NULL);
3021 return (NULL);
3022 }
3023 memset(ret, 0, sizeof(xmlSchemaItemList));
3024 return (ret);
3025}
3026
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003027static void
3028xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3029{
3030 if (list->items != NULL) {
3031 xmlFree(list->items);
3032 list->items = NULL;
3033 }
3034 list->nbItems = 0;
3035 list->sizeItems = 0;
3036}
3037
3038static int
3039xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3040{
3041 if (list->items == NULL) {
3042 list->items = (void **) xmlMalloc(
3043 20 * sizeof(void *));
3044 if (list->items == NULL) {
3045 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3046 return(-1);
3047 }
3048 list->sizeItems = 20;
3049 } else if (list->sizeItems <= list->nbItems) {
3050 list->sizeItems *= 2;
3051 list->items = (void **) xmlRealloc(list->items,
3052 list->sizeItems * sizeof(void *));
3053 if (list->items == NULL) {
3054 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3055 list->sizeItems = 0;
3056 return(-1);
3057 }
3058 }
3059 /* ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item; */
3060 list->items[list->nbItems++] = item;
3061 return(0);
3062}
3063
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003064/**
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003065 * xmlSchemaItemListFree:
3066 * @annot: a schema type structure
3067 *
3068 * Deallocate a annotation structure
3069 */
3070static void
3071xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3072{
3073 if (list == NULL)
3074 return;
3075 if (list->items != NULL)
3076 xmlFree(list->items);
3077 xmlFree(list);
3078}
3079
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003080static void
3081xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003082{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003083 if (bucket == NULL)
3084 return;
3085 if (bucket->globals != NULL) {
3086 xmlSchemaComponentListFree(bucket->globals);
3087 xmlSchemaItemListFree(bucket->globals);
3088 }
3089 if (bucket->locals != NULL) {
3090 xmlSchemaComponentListFree(bucket->locals);
3091 xmlSchemaItemListFree(bucket->locals);
3092 }
3093 if (bucket->relations != NULL) {
3094 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3095 do {
3096 prev = cur;
3097 cur = cur->next;
3098 xmlFree(prev);
3099 } while (cur != NULL);
3100 }
3101 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3102 xmlFreeDoc(bucket->doc);
3103 }
3104 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3105 if (IMPBUCKET_CAST(bucket)->schema != NULL)
3106 xmlSchemaFree(IMPBUCKET_CAST(bucket)->schema);
3107 }
3108 xmlFree(bucket);
3109}
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003110
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003111static xmlSchemaBucketPtr
3112xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3113 int type,
3114 const xmlChar *targetNamespace)
3115{
3116 xmlSchemaBucketPtr ret;
3117 xmlSchemaConstructionCtxtPtr constr = pctxt->constructor;
3118 int size;
3119 xmlSchemaPtr mainSchema;
3120
3121 if (constr->schema == NULL) {
3122 PERROR_INT("xmlSchemaBucketCreate",
3123 "no main schema on constructor");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003124 return(NULL);
3125 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003126 mainSchema = constr->schema;
3127 /* Create the schema bucket. */
3128 if (WXS_IS_INCREDEF(type))
3129 size = sizeof(xmlSchemaInclude);
3130 else
3131 size = sizeof(xmlSchemaImport);
3132 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3133 if (ret == NULL) {
3134 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3135 return(NULL);
3136 }
3137 memset(ret, 0, size);
3138 ret->targetNamespace = targetNamespace;
3139 ret->type = type;
3140 /*
3141 * The following will assure that only the first bucket is marked as
3142 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3143 * For each following import buckets an xmlSchema will be created.
3144 */
3145 if (! WXS_HAS_BUCKETS(pctxt)) {
3146 if (WXS_IS_INCREDEF(type)) {
3147 PERROR_INT("xmlSchemaBucketCreate",
3148 "first bucket but it's an include or redefine");
3149 xmlSchemaBucketFree(ret);
3150 return(NULL);
3151 }
3152 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3153 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3154 /* Point to the *main* schema. */
3155 IMPBUCKET_CAST(ret)->schema = mainSchema;
3156 } else {
3157 if (type == XML_SCHEMA_SCHEMA_MAIN) {
3158 PERROR_INT("xmlSchemaBucketCreate",
3159 "main bucket but it's not the first one");
3160 xmlSchemaBucketFree(ret);
3161 return(NULL);
3162 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3163 /*
3164 * Create a schema for imports.
3165 */
3166 IMPBUCKET_CAST(ret)->schema = xmlSchemaNewSchema(pctxt);
3167 if (IMPBUCKET_CAST(ret)->schema == NULL) {
3168 xmlSchemaBucketFree(ret);
3169 return(NULL);
3170 }
3171 }
3172 }
3173 if (WXS_IS_IMPMAIN(type)) {
3174 int res;
3175 /* Imports got into the "schemasImports" slot of the main *schema*. */
3176 if (mainSchema->schemasImports == NULL) {
3177 mainSchema->schemasImports = xmlHashCreateDict(5, constr->dict);
3178 if (mainSchema->schemasImports == NULL) {
3179 xmlSchemaBucketFree(ret);
3180 return(NULL);
3181 }
3182 }
3183 if (targetNamespace == NULL)
3184 res = xmlHashAddEntry(mainSchema->schemasImports,
3185 XML_SCHEMAS_NO_NAMESPACE, ret);
3186 else
3187 res = xmlHashAddEntry(mainSchema->schemasImports,
3188 targetNamespace, ret);
3189 if (res != 0) {
3190 PERROR_INT("xmlSchemaBucketCreate",
3191 "failed to add the schema bucket to the hash");
3192 xmlSchemaBucketFree(ret);
3193 return(NULL);
3194 }
3195 } else {
3196 /* Set the @ownerImport of an include bucket. */
3197 if (WXS_IS_IMPMAIN(constr->bucket->type))
3198 INCBUCKET_CAST(ret)->ownerImport =
3199 IMPBUCKET_CAST(constr->bucket);
3200 else
3201 INCBUCKET_CAST(ret)->ownerImport =
3202 INCBUCKET_CAST(constr->bucket)->ownerImport;
3203
3204 /* Includes got into the "includes" slot of the *main* schema. */
3205 if (mainSchema->includes == NULL) {
3206 mainSchema->includes = xmlSchemaItemListCreate();
3207 if (mainSchema->includes == NULL) {
3208 xmlSchemaBucketFree(ret);
3209 return(NULL);
3210 }
3211 }
3212 xmlSchemaItemListAdd(mainSchema->includes, ret);
3213 }
3214 /*
3215 * Add to list of all buckets; this is used for lookup
3216 * during schema construction time only.
3217 */
3218 if (xmlSchemaItemListAdd(constr->buckets, ret) == -1)
3219 return(NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003220 return(ret);
3221}
3222
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003223static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003224xmlSchemaAddItem(xmlSchemaItemListPtr *list, void *item)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003225{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003226 if (*list == NULL) {
3227 *list = xmlSchemaItemListCreate();
3228 if (*list == NULL)
3229 return(-1);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003230 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003231 xmlSchemaItemListAdd(*list, item);
3232 return(0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003233}
3234
3235/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00003236 * xmlSchemaFreeAnnot:
3237 * @annot: a schema type structure
3238 *
3239 * Deallocate a annotation structure
3240 */
3241static void
3242xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3243{
3244 if (annot == NULL)
3245 return;
Kasimier T. Buchcik004b5462005-08-08 12:43:09 +00003246 if (annot->next == NULL) {
3247 xmlFree(annot);
3248 } else {
3249 xmlSchemaAnnotPtr prev;
3250
3251 do {
3252 prev = annot;
3253 annot = annot->next;
3254 xmlFree(prev);
3255 } while (annot != NULL);
3256 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00003257}
3258
3259/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003260 * xmlSchemaFreeNotation:
3261 * @schema: a schema notation structure
3262 *
3263 * Deallocate a Schema Notation structure.
3264 */
3265static void
3266xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3267{
3268 if (nota == NULL)
3269 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003270 xmlFree(nota);
3271}
3272
3273/**
3274 * xmlSchemaFreeAttribute:
3275 * @schema: a schema attribute structure
3276 *
3277 * Deallocate a Schema Attribute structure.
3278 */
3279static void
3280xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3281{
3282 if (attr == NULL)
3283 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003284 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003285 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003286 if (attr->defVal != NULL)
3287 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003288 xmlFree(attr);
3289}
3290
3291/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003292 * xmlSchemaFreeWildcardNsSet:
3293 * set: a schema wildcard namespace
3294 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003295 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003296 */
3297static void
3298xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3299{
3300 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003301
Daniel Veillard3646d642004-06-02 19:19:14 +00003302 while (set != NULL) {
3303 next = set->next;
3304 xmlFree(set);
3305 set = next;
3306 }
3307}
3308
3309/**
3310 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003311 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003312 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003313 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003314 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003315void
Daniel Veillard3646d642004-06-02 19:19:14 +00003316xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3317{
3318 if (wildcard == NULL)
3319 return;
3320 if (wildcard->annot != NULL)
3321 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003322 if (wildcard->nsSet != NULL)
3323 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3324 if (wildcard->negNsSet != NULL)
3325 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00003326 xmlFree(wildcard);
3327}
3328
3329/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003330 * xmlSchemaFreeAttributeGroup:
3331 * @schema: a schema attribute group structure
3332 *
3333 * Deallocate a Schema Attribute Group structure.
3334 */
3335static void
3336xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
3337{
3338 if (attr == NULL)
3339 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00003340 if (attr->annot != NULL)
3341 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003342 xmlFree(attr);
3343}
3344
3345/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003346 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003347 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00003348 *
3349 * Deallocate a list of schema attribute uses.
3350 */
3351static void
3352xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3353{
3354 xmlSchemaAttributeLinkPtr next;
3355
3356 while (attrUse != NULL) {
3357 next = attrUse->next;
3358 xmlFree(attrUse);
3359 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003360 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003361}
3362
3363/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003364 * xmlSchemaFreeQNameRef:
3365 * @item: a QName reference structure
3366 *
3367 * Deallocatea a QName reference structure.
3368 */
3369static void
3370xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3371{
3372 xmlFree(item);
3373}
3374
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003375/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003376 * xmlSchemaFreeTypeLinkList:
3377 * @alink: a type link
3378 *
3379 * Deallocate a list of types.
3380 */
3381static void
3382xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3383{
3384 xmlSchemaTypeLinkPtr next;
3385
3386 while (link != NULL) {
3387 next = link->next;
3388 xmlFree(link);
3389 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003390 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003391}
3392
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003393static void
3394xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3395{
3396 xmlSchemaIDCStateObjPtr next;
3397 while (sto != NULL) {
3398 next = sto->next;
3399 if (sto->history != NULL)
3400 xmlFree(sto->history);
3401 if (sto->xpathCtxt != NULL)
3402 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3403 xmlFree(sto);
3404 sto = next;
3405 }
3406}
3407
3408/**
3409 * xmlSchemaFreeIDC:
3410 * @idc: a identity-constraint definition
3411 *
3412 * Deallocates an identity-constraint definition.
3413 */
3414static void
3415xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3416{
3417 xmlSchemaIDCSelectPtr cur, prev;
3418
3419 if (idcDef == NULL)
3420 return;
3421 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003422 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003423 /* Selector */
3424 if (idcDef->selector != NULL) {
3425 if (idcDef->selector->xpathComp != NULL)
3426 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3427 xmlFree(idcDef->selector);
3428 }
3429 /* Fields */
3430 if (idcDef->fields != NULL) {
3431 cur = idcDef->fields;
3432 do {
3433 prev = cur;
3434 cur = cur->next;
3435 if (prev->xpathComp != NULL)
3436 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003437 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003438 } while (cur != NULL);
3439 }
3440 xmlFree(idcDef);
3441}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003442
Daniel Veillard01fa6152004-06-29 17:04:39 +00003443/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003444 * xmlSchemaFreeElement:
3445 * @schema: a schema element structure
3446 *
3447 * Deallocate a Schema Element structure.
3448 */
3449static void
3450xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3451{
3452 if (elem == NULL)
3453 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003454 if (elem->annot != NULL)
3455 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003456 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003457 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003458 if (elem->defVal != NULL)
3459 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003460 xmlFree(elem);
3461}
3462
3463/**
3464 * xmlSchemaFreeFacet:
3465 * @facet: a schema facet structure
3466 *
3467 * Deallocate a Schema Facet structure.
3468 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003469void
Daniel Veillard4255d502002-04-16 15:50:10 +00003470xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3471{
3472 if (facet == NULL)
3473 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003474 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003475 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003476 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003477 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003478 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003479 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003480 xmlFree(facet);
3481}
3482
3483/**
3484 * xmlSchemaFreeType:
3485 * @type: a schema type structure
3486 *
3487 * Deallocate a Schema Type structure.
3488 */
3489void
3490xmlSchemaFreeType(xmlSchemaTypePtr type)
3491{
3492 if (type == NULL)
3493 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003494 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003495 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003496 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003497 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003498
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003499 facet = type->facets;
3500 while (facet != NULL) {
3501 next = facet->next;
3502 xmlSchemaFreeFacet(facet);
3503 facet = next;
3504 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003505 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003506 if (type->type != XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00003507 /*
3508 * TODO: Why is this restricted to non built-in types?
3509 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003510 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003511 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003512 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003513 if (type->memberTypes != NULL)
3514 xmlSchemaFreeTypeLinkList(type->memberTypes);
3515 if (type->facetSet != NULL) {
3516 xmlSchemaFacetLinkPtr next, link;
3517
3518 link = type->facetSet;
3519 do {
3520 next = link->next;
3521 xmlFree(link);
3522 link = next;
3523 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003524 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003525 if (type->contModel != NULL)
3526 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003527 xmlFree(type);
3528}
3529
3530/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003531 * xmlSchemaFreeModelGroupDef:
3532 * @item: a schema model group definition
3533 *
3534 * Deallocates a schema model group definition.
3535 */
3536static void
3537xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3538{
3539 if (item->annot != NULL)
3540 xmlSchemaFreeAnnot(item->annot);
3541 xmlFree(item);
3542}
3543
3544/**
3545 * xmlSchemaFreeModelGroup:
3546 * @item: a schema model group
3547 *
3548 * Deallocates a schema model group structure.
3549 */
3550static void
3551xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3552{
3553 if (item->annot != NULL)
3554 xmlSchemaFreeAnnot(item->annot);
3555 xmlFree(item);
3556}
3557
3558/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003559 * xmlSchemaFreeTypeList:
3560 * @type: a schema type structure
3561 *
3562 * Deallocate a Schema Type structure.
3563 */
3564static void
3565xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3566{
3567 xmlSchemaTypePtr next;
3568
3569 while (type != NULL) {
3570 next = type->redef;
3571 xmlSchemaFreeType(type);
3572 type = next;
3573 }
3574}
3575
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003576static void
3577xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
3578{
3579 if ((list == NULL) || (list->nbItems == 0))
3580 return;
3581 {
3582 xmlSchemaTreeItemPtr item;
3583 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
3584 int i;
3585
3586 for (i = 0; i < list->nbItems; i++) {
3587 item = items[i];
3588 if (item == NULL)
3589 continue;
3590 switch (item->type) {
3591 case XML_SCHEMA_TYPE_SIMPLE:
3592 case XML_SCHEMA_TYPE_COMPLEX:
3593 xmlSchemaFreeTypeList((xmlSchemaTypePtr) item);
3594 break;
3595 case XML_SCHEMA_TYPE_ATTRIBUTE:
3596 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
3597 break;
3598 case XML_SCHEMA_TYPE_ELEMENT:
3599 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
3600 break;
3601 case XML_SCHEMA_TYPE_PARTICLE:
3602 if (item->annot != NULL)
3603 xmlSchemaFreeAnnot(item->annot);
3604 xmlFree(item);
3605 break;
3606 case XML_SCHEMA_TYPE_SEQUENCE:
3607 case XML_SCHEMA_TYPE_CHOICE:
3608 case XML_SCHEMA_TYPE_ALL:
3609 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3610 break;
3611 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
3612 xmlSchemaFreeAttributeGroup(
3613 (xmlSchemaAttributeGroupPtr) item);
3614 break;
3615 case XML_SCHEMA_TYPE_GROUP:
3616 xmlSchemaFreeModelGroupDef(
3617 (xmlSchemaModelGroupDefPtr) item);
3618 break;
3619 case XML_SCHEMA_TYPE_ANY:
3620 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3621 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3622 break;
3623 case XML_SCHEMA_TYPE_IDC_KEY:
3624 case XML_SCHEMA_TYPE_IDC_UNIQUE:
3625 case XML_SCHEMA_TYPE_IDC_KEYREF:
3626 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
3627 break;
3628 case XML_SCHEMA_TYPE_NOTATION:
3629 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
3630 break;
3631 case XML_SCHEMA_EXTRA_QNAMEREF:
3632 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3633 break;
3634 default: {
3635 /* TODO: This should never be hit. */
3636 xmlSchemaPSimpleInternalErr(NULL,
3637 "Internal error: xmlSchemaComponentListFree, "
3638 "unexpected component type '%s'\n",
3639 (const xmlChar *)
3640 xmlSchemaCompTypeToString(item->type));
3641 }
3642 break;
3643 }
3644 }
3645 list->nbItems = 0;
3646 }
3647}
3648
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003649/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003650 * xmlSchemaFree:
3651 * @schema: a schema structure
3652 *
3653 * Deallocate a Schema structure.
3654 */
3655void
3656xmlSchemaFree(xmlSchemaPtr schema)
3657{
3658 if (schema == NULL)
3659 return;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003660 /* @volatiles is not used anymore :-/ */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003661 if (schema->volatiles != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003662 TODO
3663 /*
3664 * Note that those slots are not responsible for freeing
3665 * schema components anymore; this will now be done by
3666 * the schema buckets.
3667 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003668 if (schema->notaDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003669 xmlHashFree(schema->notaDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003670 if (schema->attrDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003671 xmlHashFree(schema->attrDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003672 if (schema->attrgrpDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003673 xmlHashFree(schema->attrgrpDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003674 if (schema->elemDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003675 xmlHashFree(schema->elemDecl, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003676 if (schema->typeDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003677 xmlHashFree(schema->typeDecl, NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003678 if (schema->groupDecl != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003679 xmlHashFree(schema->groupDecl, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003680 if (schema->idcDef != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003681 xmlHashFree(schema->idcDef, NULL);
3682
Daniel Veillard1d913862003-11-21 00:28:39 +00003683 if (schema->schemasImports != NULL)
3684 xmlHashFree(schema->schemasImports,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003685 (xmlHashDeallocator) xmlSchemaBucketFree);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003686 if (schema->includes != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003687 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
3688 int i;
3689 for (i = 0; i < list->nbItems; i++) {
3690 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
3691 }
3692 xmlSchemaItemListFree(list);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003693 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003694 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003695 xmlSchemaFreeAnnot(schema->annot);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00003696 /* Never free the doc here, since this will be done by the buckets. */
3697
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003698 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003699 xmlFree(schema);
3700}
3701
3702/************************************************************************
3703 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003704 * Debug functions *
3705 * *
3706 ************************************************************************/
3707
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003708#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003709
Daniel Veillard4255d502002-04-16 15:50:10 +00003710/**
3711 * xmlSchemaElementDump:
3712 * @elem: an element
3713 * @output: the file output
3714 *
3715 * Dump the element
3716 */
3717static void
3718xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003719 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003720 const xmlChar * namespace ATTRIBUTE_UNUSED,
3721 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003722{
3723 if (elem == NULL)
3724 return;
3725
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003726 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3727 fprintf(output, "Particle: %s", name);
3728 fprintf(output, ", term element: %s", elem->ref);
3729 if (elem->refNs != NULL)
3730 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003731 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003732 fprintf(output, "Element");
3733 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3734 fprintf(output, " (global)");
3735 fprintf(output, ": %s ", elem->name);
3736 if (namespace != NULL)
3737 fprintf(output, "ns %s", namespace);
3738 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003739 fprintf(output, "\n");
3740 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003741 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003742 if (elem->maxOccurs >= UNBOUNDED)
3743 fprintf(output, "max: unbounded\n");
3744 else if (elem->maxOccurs != 1)
3745 fprintf(output, "max: %d\n", elem->maxOccurs);
3746 else
3747 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003748 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003749 /*
3750 * Misc other properties.
3751 */
3752 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3753 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3754 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3755 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3756 (elem->id != NULL)) {
3757 fprintf(output, " props: ");
3758 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3759 fprintf(output, "[fixed] ");
3760 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3761 fprintf(output, "[default] ");
3762 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3763 fprintf(output, "[abstract] ");
3764 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3765 fprintf(output, "[nillable] ");
3766 if (elem->id != NULL)
3767 fprintf(output, "[id: '%s'] ", elem->id);
3768 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003769 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003770 /*
3771 * Default/fixed value.
3772 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003773 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003774 fprintf(output, " value: '%s'\n", elem->value);
3775 /*
3776 * Type.
3777 */
3778 if (elem->namedType != NULL) {
3779 fprintf(output, " type: %s ", elem->namedType);
3780 if (elem->namedTypeNs != NULL)
3781 fprintf(output, "ns %s\n", elem->namedTypeNs);
3782 else
3783 fprintf(output, "\n");
3784 }
3785 /*
3786 * Substitution group.
3787 */
3788 if (elem->substGroup != NULL) {
3789 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3790 if (elem->substGroupNs != NULL)
3791 fprintf(output, "ns %s\n", elem->substGroupNs);
3792 else
3793 fprintf(output, "\n");
3794 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003795}
3796
3797/**
3798 * xmlSchemaAnnotDump:
3799 * @output: the file output
3800 * @annot: a annotation
3801 *
3802 * Dump the annotation
3803 */
3804static void
3805xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3806{
3807 xmlChar *content;
3808
3809 if (annot == NULL)
3810 return;
3811
3812 content = xmlNodeGetContent(annot->content);
3813 if (content != NULL) {
3814 fprintf(output, " Annot: %s\n", content);
3815 xmlFree(content);
3816 } else
3817 fprintf(output, " Annot: empty\n");
3818}
3819
3820/**
3821 * xmlSchemaTypeDump:
3822 * @output: the file output
3823 * @type: a type structure
3824 *
3825 * Dump a SchemaType structure
3826 */
3827static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003828xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3829{
3830 xmlChar *str = NULL;
3831 xmlSchemaTreeItemPtr term;
3832 char shift[100];
3833 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003834
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003835 if (particle == NULL)
3836 return;
3837 for (i = 0;((i < depth) && (i < 25));i++)
3838 shift[2 * i] = shift[2 * i + 1] = ' ';
3839 shift[2 * i] = shift[2 * i + 1] = 0;
3840 fprintf(output, shift);
3841 if (particle->children == NULL) {
3842 fprintf(output, "MISSING particle term\n");
3843 return;
3844 }
3845 term = particle->children;
3846 switch (term->type) {
3847 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003848 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003849 ((xmlSchemaElementPtr)term)->targetNamespace,
3850 ((xmlSchemaElementPtr)term)->name));
3851 break;
3852 case XML_SCHEMA_TYPE_SEQUENCE:
3853 fprintf(output, "SEQUENCE");
3854 break;
3855 case XML_SCHEMA_TYPE_CHOICE:
3856 fprintf(output, "CHOICE");
3857 break;
3858 case XML_SCHEMA_TYPE_ALL:
3859 fprintf(output, "ALL");
3860 break;
3861 case XML_SCHEMA_TYPE_ANY:
3862 fprintf(output, "ANY");
3863 break;
3864 default:
3865 fprintf(output, "UNKNOWN\n");
3866 return;
3867 }
3868 if (particle->minOccurs != 1)
3869 fprintf(output, " min: %d", particle->minOccurs);
3870 if (particle->maxOccurs >= UNBOUNDED)
3871 fprintf(output, " max: unbounded");
3872 else if (particle->maxOccurs != 1)
3873 fprintf(output, " max: %d", particle->maxOccurs);
3874 fprintf(output, "\n");
3875 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3876 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3877 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3878 (term->children != NULL)) {
3879 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3880 output, depth +1);
3881 }
3882 if (particle->next != NULL)
3883 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3884 output, depth);
3885}
3886/**
3887 * xmlSchemaTypeDump:
3888 * @output: the file output
3889 * @type: a type structure
3890 *
3891 * Dump a SchemaType structure
3892 */
3893static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003894xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3895{
3896 if (type == NULL) {
3897 fprintf(output, "Type: NULL\n");
3898 return;
3899 }
3900 fprintf(output, "Type: ");
3901 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003902 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003903 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003904 fprintf(output, "no name ");
3905 if (type->targetNamespace != NULL)
3906 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003907 switch (type->type) {
3908 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003909 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003910 break;
3911 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003912 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003913 break;
3914 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003915 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003916 break;
3917 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003918 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003919 break;
3920 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003921 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003922 break;
3923 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003924 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003925 break;
3926 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003927 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003928 break;
3929 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003930 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003931 break;
3932 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003933 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003934 break;
3935 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003936 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003937 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003938 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003939 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003940 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003941 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003942 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003943 break;
3944 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003945 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003946 break;
3947 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003948 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003949 break;
3950 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003951 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003952 break;
3953 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003954 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003955 break;
3956 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003957 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003958 break;
3959 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003960 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003961 break;
3962 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003963 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003964 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003965 }
3966 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003967 if (type->base != NULL) {
3968 fprintf(output, " base type: %s", type->base);
3969 if (type->baseNs != NULL)
3970 fprintf(output, " ns %s\n", type->baseNs);
3971 else
3972 fprintf(output, "\n");
3973 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003974 if (type->annot != NULL)
3975 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003976#ifdef DUMP_CONTENT_MODEL
3977 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3978 (type->subtypes != NULL)) {
3979 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3980 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003981 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003982#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003983}
3984
3985/**
3986 * xmlSchemaDump:
3987 * @output: the file output
3988 * @schema: a schema structure
3989 *
3990 * Dump a Schema structure.
3991 */
3992void
3993xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3994{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003995 if (output == NULL)
3996 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003997 if (schema == NULL) {
3998 fprintf(output, "Schemas: NULL\n");
3999 return;
4000 }
4001 fprintf(output, "Schemas: ");
4002 if (schema->name != NULL)
4003 fprintf(output, "%s, ", schema->name);
4004 else
4005 fprintf(output, "no name, ");
4006 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00004007 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004008 else
4009 fprintf(output, "no target namespace");
4010 fprintf(output, "\n");
4011 if (schema->annot != NULL)
4012 xmlSchemaAnnotDump(output, schema->annot);
4013
4014 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4015 output);
4016 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004017 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00004018}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004019
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00004020#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004021/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004022 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004023 * @vctxt: the WXS validation context
4024 *
4025 * Displays the current IDC table for debug purposes.
4026 */
4027static void
4028xmlSchemaDebugDumpIDCTable(FILE * output,
4029 const xmlChar *namespaceName,
4030 const xmlChar *localName,
4031 xmlSchemaPSVIIDCBindingPtr bind)
4032{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004033 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004034 xmlSchemaPSVIIDCNodePtr tab;
4035 xmlSchemaPSVIIDCKeyPtr key;
4036 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004037
4038 fprintf(output, "IDC: TABLES on %s\n",
4039 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004040 FREE_AND_NULL(str)
4041
4042 if (bind == NULL)
4043 return;
4044 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004045 fprintf(output, "IDC: BINDING %s\n",
4046 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004047 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004048 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004049 for (i = 0; i < bind->nbNodes; i++) {
4050 tab = bind->nodeTable[i];
4051 fprintf(output, " ( ");
4052 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004053 key = tab->keys[j];
4054 if ((key != NULL) && (key->val != NULL)) {
4055 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004056 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004057 fprintf(output, "\"%s\" ", value);
4058 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004059 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004060 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004061 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004062 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004063 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004064 else
4065 fprintf(output, "(key missing), ");
4066 }
4067 fprintf(output, ")\n");
4068 }
4069 bind = bind->next;
4070 } while (bind != NULL);
4071}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00004072#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004073#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00004074
4075/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004076 * *
4077 * Utilities *
4078 * *
4079 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004080
Daniel Veillardc0826a72004-08-10 14:17:33 +00004081/**
4082 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004083 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004084 * @name: the name of the attribute
4085 *
4086 * Seeks an attribute with a name of @name in
4087 * no namespace.
4088 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004089 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004090 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004091static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004092xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004093{
4094 xmlAttrPtr prop;
4095
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004096 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004097 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004098 prop = node->properties;
4099 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004100 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004101 return(prop);
4102 prop = prop->next;
4103 }
4104 return (NULL);
4105}
4106
4107/**
4108 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004109 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004110 * @uri: the uri
4111 * @name: the name of the attribute
4112 *
4113 * Seeks an attribute with a local name of @name and
4114 * a namespace URI of @uri.
4115 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004116 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004117 */
4118static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004119xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00004120{
4121 xmlAttrPtr prop;
4122
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004123 if ((node == NULL) || (name == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004124 return(NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004125 prop = node->properties;
4126 while (prop != NULL) {
4127 if ((prop->ns != NULL) &&
4128 xmlStrEqual(prop->name, BAD_CAST name) &&
4129 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00004130 return(prop);
4131 prop = prop->next;
4132 }
4133 return (NULL);
4134}
4135
4136static const xmlChar *
4137xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4138{
4139 xmlChar *val;
4140 const xmlChar *ret;
4141
4142 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004143 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00004144 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00004145 ret = xmlDictLookup(ctxt->dict, val, -1);
4146 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004147 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004148}
4149
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004150/**
4151 * xmlSchemaGetProp:
4152 * @ctxt: the parser context
4153 * @node: the node
4154 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004155 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004156 * Read a attribute value and internalize the string
4157 *
4158 * Returns the string or NULL if not present.
4159 */
4160static const xmlChar *
4161xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4162 const char *name)
4163{
4164 xmlChar *val;
4165 const xmlChar *ret;
4166
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004167 val = xmlGetNoNsProp(node, BAD_CAST name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004168 if (val == NULL)
4169 return(NULL);
4170 ret = xmlDictLookup(ctxt->dict, val, -1);
4171 xmlFree(val);
4172 return(ret);
4173}
4174
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004175/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00004176 * *
4177 * Parsing functions *
4178 * *
4179 ************************************************************************/
4180
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004181#define WXS_FIND_GLOBAL_ITEM(slot) \
4182 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4183 ret = xmlHashLookup(schema->slot, name); \
4184 if (ret != NULL) goto exit; \
4185 } \
4186 if (xmlHashSize(schema->schemasImports) > 1) { \
4187 xmlSchemaImportPtr import; \
4188 if (nsName == NULL) \
4189 import = xmlHashLookup(schema->schemasImports, \
4190 XML_SCHEMAS_NO_NAMESPACE); \
4191 else \
4192 import = xmlHashLookup(schema->schemasImports, nsName); \
4193 if (import == NULL) \
4194 goto exit; \
4195 ret = xmlHashLookup(import->schema->slot, name); \
4196 }
4197
Daniel Veillard4255d502002-04-16 15:50:10 +00004198/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004199 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004200 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004201 * @name: the element name
4202 * @ns: the element namespace
4203 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004204 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004205 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004206 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004207 */
4208static xmlSchemaElementPtr
4209xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004210 const xmlChar * nsName)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004211{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004212 xmlSchemaElementPtr ret = NULL;
4213
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004214 if ((name == NULL) || (schema == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004215 return(NULL);
4216 if (schema != NULL) {
4217 WXS_FIND_GLOBAL_ITEM(elemDecl)
4218 }
4219exit:
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004220#ifdef DEBUG
4221 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004222 if (nsName == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004223 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004224 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004225 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004226 nsName);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004227 }
4228#endif
4229 return (ret);
4230}
4231
4232/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004233 * xmlSchemaGetType:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004234 * @schema: the main schema
4235 * @name: the type's name
4236 * nsName: the type's namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004237 *
4238 * Lookup a type in the schemas or the predefined types
4239 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004240 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004241 */
4242static xmlSchemaTypePtr
4243xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004244 const xmlChar * nsName)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004245{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004246 xmlSchemaTypePtr ret = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004247
4248 if (name == NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004249 return (NULL);
4250 /* First try the built-in types. */
4251 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4252 ret = xmlSchemaGetPredefinedType(name, nsName);
4253 if (ret != NULL)
4254 goto exit;
4255 /*
4256 * Note that we try the parsed schemas as well here
4257 * since one might have parsed the S4S, which contain more
4258 * than the built-in types.
4259 * TODO: Can we optimize this?
4260 */
4261 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004262 if (schema != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004263 WXS_FIND_GLOBAL_ITEM(typeDecl)
4264 }
4265exit:
4266 if ((ret != NULL) && (ret->redef != NULL)) {
4267 /* Return the last redefinition. */
4268 ret = ret->redef;
Daniel Veillard4255d502002-04-16 15:50:10 +00004269 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004270#ifdef DEBUG
4271 if (ret == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004272 if (nsName == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004273 fprintf(stderr, "Unable to lookup type %s", name);
4274 else
4275 fprintf(stderr, "Unable to lookup type %s:%s", name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004276 nsName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004277 }
4278#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004279 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004280}
4281
Daniel Veillard3646d642004-06-02 19:19:14 +00004282/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004283 * xmlSchemaGetAttributeDecl:
4284 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004285 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004286 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004287 *
4288 * Lookup a an attribute in the schema or imported schemas
4289 *
4290 * Returns the attribute declaration or NULL if not found.
4291 */
4292static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004293xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004294 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004295{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004296 xmlSchemaAttributePtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004297
4298 if ((name == NULL) || (schema == NULL))
4299 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004300 if (schema != NULL) {
4301 WXS_FIND_GLOBAL_ITEM(attrDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004302 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004303exit:
Daniel Veillard3646d642004-06-02 19:19:14 +00004304#ifdef DEBUG
4305 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004306 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004307 fprintf(stderr, "Unable to lookup attribute %s", name);
4308 else
4309 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004310 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004311 }
4312#endif
4313 return (ret);
4314}
4315
4316/**
4317 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004318 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004319 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004320 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004321 *
4322 * Lookup a an attribute group in the schema or imported schemas
4323 *
4324 * Returns the attribute group definition or NULL if not found.
4325 */
4326static xmlSchemaAttributeGroupPtr
4327xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004328 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004329{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004330 xmlSchemaAttributeGroupPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004331
4332 if ((name == NULL) || (schema == NULL))
4333 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004334 if (schema != NULL) {
4335 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4336 }
4337exit:
4338 /* TODO:
4339 if ((ret != NULL) && (ret->redef != NULL)) {
4340 * Return the last redefinition. *
4341 ret = ret->redef;
Daniel Veillard3646d642004-06-02 19:19:14 +00004342 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004343 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004344#ifdef DEBUG
4345 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004346 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004347 fprintf(stderr, "Unable to lookup attribute group %s", name);
4348 else
4349 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004350 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004351 }
4352#endif
4353 return (ret);
4354}
4355
4356/**
4357 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004358 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004359 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004360 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004361 *
4362 * Lookup a group in the schema or imported schemas
4363 *
4364 * Returns the group definition or NULL if not found.
4365 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004366static xmlSchemaModelGroupDefPtr
Daniel Veillard3646d642004-06-02 19:19:14 +00004367xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004368 const xmlChar * nsName)
Daniel Veillard3646d642004-06-02 19:19:14 +00004369{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004370 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +00004371
4372 if ((name == NULL) || (schema == NULL))
4373 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004374 if (schema != NULL) {
4375 WXS_FIND_GLOBAL_ITEM(groupDecl)
Daniel Veillard3646d642004-06-02 19:19:14 +00004376 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004377exit:
4378 if ((ret != NULL) && (ret->redef != NULL)) {
4379 /* Return the last redefinition. */
4380 ret = ret->redef;
4381 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004382#ifdef DEBUG
4383 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004384 if (nsName == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +00004385 fprintf(stderr, "Unable to lookup group %s", name);
4386 else
4387 fprintf(stderr, "Unable to lookup group %s:%s", name,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004388 nsName);
Daniel Veillard3646d642004-06-02 19:19:14 +00004389 }
4390#endif
4391 return (ret);
4392}
4393
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004394static xmlSchemaNotationPtr
4395xmlSchemaGetNotation(xmlSchemaPtr schema,
4396 const xmlChar *name,
4397 const xmlChar *nsName)
4398{
4399 xmlSchemaNotationPtr ret = NULL;
4400
4401 if ((name == NULL) || (schema == NULL))
4402 return (NULL);
4403 if (schema != NULL) {
4404 WXS_FIND_GLOBAL_ITEM(notaDecl)
4405 }
4406exit:
4407 return (ret);
4408}
4409
4410static xmlSchemaIDCPtr
4411xmlSchemaGetIDC(xmlSchemaPtr schema,
4412 const xmlChar *name,
4413 const xmlChar *nsName)
4414{
4415 xmlSchemaIDCPtr ret = NULL;
4416
4417 if ((name == NULL) || (schema == NULL))
4418 return (NULL);
4419 if (schema != NULL) {
4420 WXS_FIND_GLOBAL_ITEM(idcDef)
4421 }
4422exit:
4423 return (ret);
4424}
4425
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004426/**
4427 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004428 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004429 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004430 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004431 *
4432 * Lookup a group in the schema or imported schemas
4433 *
4434 * Returns the group definition or NULL if not found.
4435 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004436static xmlSchemaBasicItemPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004437xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4438 xmlSchemaTypeType itemType,
4439 const xmlChar *name,
4440 const xmlChar *targetNs)
4441{
4442 switch (itemType) {
4443 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004444 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004445 name, targetNs));
4446 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004447 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004448 name, targetNs));
4449 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004450 TODO
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004451 return (NULL);
4452 }
4453}
4454
Daniel Veillard4255d502002-04-16 15:50:10 +00004455/************************************************************************
4456 * *
4457 * Parsing functions *
4458 * *
4459 ************************************************************************/
4460
4461#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004462 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004463
4464/**
4465 * xmlSchemaIsBlank:
4466 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004467 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004468 *
4469 * Check if a string is ignorable
4470 *
4471 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4472 */
4473static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004474xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004475{
Daniel Veillard4255d502002-04-16 15:50:10 +00004476 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004477 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004478 if (len < 0) {
4479 while (*str != 0) {
4480 if (!(IS_BLANK_CH(*str)))
4481 return (0);
4482 str++;
4483 }
4484 } else while ((*str != 0) && (len != 0)) {
4485 if (!(IS_BLANK_CH(*str)))
4486 return (0);
4487 str++;
4488 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004489 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004490
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004491 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004492}
4493
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004494#define WXS_GET_GLOBAL_HASH(c, s, slot) \
4495{ \
4496 if (WXS_IS_IMPMAIN((c)->type)) \
4497 table = &(IMPBUCKET_CAST((c))->schema->slot); \
4498 else \
4499 table = &(INCBUCKET_CAST((c))->ownerImport->schema->slot); \
4500} \
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004501
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004502#define WXS_INIT_GLOBAL_HASH(ctx, tbl) \
4503if (*(tbl) == NULL) *(tbl) = xmlHashCreateDict(10, (ctx)->dict); \
4504if (*(tbl) == NULL) { if (ret != NULL) xmlFree(ret); return (NULL); }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004505
4506/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004507 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004508 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004509 * @schema: the schema being built
4510 * @name: the item name
4511 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004512 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004513 * *WARNING* this interface is highly subject to change
4514 *
4515 * Returns the new struture or NULL in case of error
4516 */
4517static xmlSchemaNotationPtr
4518xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004519 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004520{
4521 xmlSchemaNotationPtr ret = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004522 xmlHashTablePtr *table = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004523 int val;
4524
4525 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4526 return (NULL);
4527
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004528 WXS_GET_GLOBAL_HASH(WXS_SCHEMA_BUCKET(ctxt), schema, notaDecl)
Daniel Veillard4255d502002-04-16 15:50:10 +00004529
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004530 WXS_INIT_GLOBAL_HASH(ctxt, table)
Daniel Veillard4255d502002-04-16 15:50:10 +00004531 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4532 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004533 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004534 return (NULL);
4535 }
4536 memset(ret, 0, sizeof(xmlSchemaNotation));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004537 ret->type = XML_SCHEMA_TYPE_NOTATION;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004538 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004539
4540 val = xmlHashAddEntry(*table, ret->name, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004541 if (val != 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004542 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004543 XML_SCHEMAP_REDEFINED_NOTATION,
4544 "A notation declaration with the name '%s' does already exist.\n",
4545 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004546 xmlFree(ret);
4547 return (NULL);
4548 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004549 ADD_GLOBAL_ITEM(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004550 return (ret);
4551}
4552
Daniel Veillard4255d502002-04-16 15:50:10 +00004553/**
4554 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004555 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004556 * @schema: the schema being built
4557 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004558 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004559 *
4560 * Add an XML schema Attrribute declaration
4561 * *WARNING* this interface is highly subject to change
4562 *
4563 * Returns the new struture or NULL in case of error
4564 */
4565static xmlSchemaAttributePtr
4566xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004567 const xmlChar * name, const xmlChar * nsName,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004568 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004569{
4570 xmlSchemaAttributePtr ret = NULL;
4571 int val;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004572 xmlHashTablePtr *table;
Daniel Veillard4255d502002-04-16 15:50:10 +00004573
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004574 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00004575 return (NULL);
4576
4577 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4578 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004579 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004580 return (NULL);
4581 }
4582 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004583 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004584 ret->targetNamespace = nsName;
4585
4586 if (topLevel) {
4587 WXS_GET_GLOBAL_HASH(WXS_SCHEMA_BUCKET(ctxt), schema, attrDecl)
4588 WXS_INIT_GLOBAL_HASH(ctxt, table)
4589 val = xmlHashAddEntry(*table, name, ret);
4590 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004591 xmlSchemaPCustomErr(ctxt,
4592 XML_SCHEMAP_REDEFINED_ATTR,
4593 NULL, NULL, node,
4594 "A global attribute declaration with the name '%s' does "
4595 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004596 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004597 return (NULL);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004598 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004599 ADD_GLOBAL_ITEM(ctxt, ret);
4600 } else
4601 ADD_LOCAL_ITEM(ctxt, ret);
4602 WXS_ADD_PENDING_ITEM(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004603 return (ret);
4604}
4605
4606/**
4607 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004608 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004609 * @schema: the schema being built
4610 * @name: the item name
4611 *
4612 * Add an XML schema Attrribute Group declaration
4613 *
4614 * Returns the new struture or NULL in case of error
4615 */
4616static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004617xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004618 xmlSchemaPtr schema,
4619 const xmlChar * name,
4620 xmlNodePtr node,
4621 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004622{
4623 xmlSchemaAttributeGroupPtr ret = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004624 xmlHashTablePtr *table = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004625 int val;
4626
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004627 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00004628 return (NULL);
4629
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004630 ret = (xmlSchemaAttributeGroupPtr)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004631 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004632 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004633 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
4634 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004635 }
4636 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004637 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
4638 ret->node = node;
4639
4640 if (topLevel) {
4641 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
4642 ret->name = xmlDictLookup(ctxt->dict, name, -1);
4643 ret->targetNamespace = ctxt->targetNamespace;
4644
4645 WXS_GET_GLOBAL_HASH(WXS_SCHEMA_BUCKET(ctxt), schema, attrgrpDecl)
4646 WXS_INIT_GLOBAL_HASH(ctxt, table)
4647
4648 val = xmlHashAddEntry(*table, name, ret);
4649 if (val != 0) {
4650 xmlSchemaPCustomErr(ctxt,
4651 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4652 NULL, NULL, node,
4653 "A global attribute group definition with the name '%s' "
4654 "does already exist", name);
4655 xmlFree(ret);
4656 return (NULL);
4657 }
4658 ADD_GLOBAL_ITEM(ctxt, ret);
4659 } else
4660 ADD_LOCAL_ITEM(ctxt, ret);
4661
4662 WXS_ADD_PENDING_ITEM(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004663 return (ret);
4664}
4665
4666/**
4667 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004668 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004669 * @schema: the schema being built
4670 * @name: the type name
4671 * @namespace: the type namespace
4672 *
4673 * Add an XML schema Element declaration
4674 * *WARNING* this interface is highly subject to change
4675 *
4676 * Returns the new struture or NULL in case of error
4677 */
4678static xmlSchemaElementPtr
4679xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004680 const xmlChar * name, const xmlChar * nsName,
William M. Brack2f2a6632004-08-20 23:09:47 +00004681 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004682{
4683 xmlSchemaElementPtr ret = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004684 xmlHashTablePtr *table = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004685 int val;
4686
4687 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4688 return (NULL);
4689
Daniel Veillard4255d502002-04-16 15:50:10 +00004690 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4691 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004692 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004693 return (NULL);
4694 }
4695 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004696 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004697 ret->targetNamespace = nsName;
4698
4699 if (topLevel) {
4700 WXS_GET_GLOBAL_HASH(WXS_SCHEMA_BUCKET(ctxt), schema, elemDecl)
4701 WXS_INIT_GLOBAL_HASH(ctxt, table)
4702 val = xmlHashAddEntry(*table, name, ret);
4703 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004704 xmlSchemaPCustomErr(ctxt,
4705 XML_SCHEMAP_REDEFINED_ELEMENT,
4706 NULL, NULL, node,
4707 "A global element declaration with the name '%s' does "
4708 "already exist", name);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004709 xmlFree(ret);
4710 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004711 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004712 ADD_GLOBAL_ITEM(ctxt, ret);
4713 } else
4714 ADD_LOCAL_ITEM(ctxt, ret);
4715 WXS_ADD_PENDING_ITEM(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004716 return (ret);
4717}
4718
4719/**
4720 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004721 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004722 * @schema: the schema being built
4723 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004724 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004725 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004726 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004727 * *WARNING* this interface is highly subject to change
4728 *
4729 * Returns the new struture or NULL in case of error
4730 */
4731static xmlSchemaTypePtr
4732xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004733 const xmlChar * name, const xmlChar * nsName,
4734 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004735{
4736 xmlSchemaTypePtr ret = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004737 xmlHashTablePtr *table = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00004738 int val;
4739
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004740 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard4255d502002-04-16 15:50:10 +00004741 return (NULL);
4742
4743 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4744 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004745 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004746 return (NULL);
4747 }
4748 memset(ret, 0, sizeof(xmlSchemaType));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004749 if (name != NULL)
4750 ret->name = xmlDictLookup(ctxt->dict, name, -1);
4751 ret->targetNamespace = nsName;
4752 ret->node = node;
4753 /* TODO: Get rid of occurences here. */
4754 ret->minOccurs = 1;
4755 ret->maxOccurs = 1;
4756
4757 if (topLevel) {
4758 WXS_GET_GLOBAL_HASH(WXS_SCHEMA_BUCKET(ctxt), schema, typeDecl)
4759 WXS_INIT_GLOBAL_HASH(ctxt, table)
4760 val = xmlHashAddEntry(*table, name, ret);
4761 if (val != 0) {
4762 if (! ctxt->isRedefine) {
4763 xmlChar *str = NULL;
4764
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004765 xmlSchemaPCustomErr(ctxt,
4766 XML_SCHEMAP_REDEFINED_TYPE,
4767 NULL, NULL, node,
4768 "A global type definition with the name '%s' does "
4769 "already exist",
4770 xmlSchemaFormatQName(&str, nsName, name));
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004771 FREE_AND_NULL(str);
4772 xmlFree(ret);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004773 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004774 } else {
4775 xmlSchemaTypePtr prev;
4776
4777 /* REDEFINE: Add a redefinition. */
4778 TODO
4779 prev = xmlHashLookup(*table, name);
4780 if (prev == NULL) {
4781 PERROR_INT2("xmlSchemaAddType", "hash list did not "
4782 "return a redefined type component, but should");
4783 xmlFree(ret);
4784 return (NULL);
4785 }
4786 ret->redef = prev->redef;
4787 prev->redef = ret;
4788 /* TODO: Add to locals; dunno if this will make trouble. */
4789 ADD_LOCAL_ITEM(ctxt, ret);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004790 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004791 } else
4792 ADD_GLOBAL_ITEM(ctxt, ret);
4793 } else
4794 ADD_LOCAL_ITEM(ctxt, ret);
4795 WXS_ADD_PENDING_ITEM(ctxt, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004796 return (ret);
4797}
4798
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004799static xmlSchemaQNameRefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004800xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004801 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004802 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004803 const xmlChar *refNs)
4804{
4805 xmlSchemaQNameRefPtr ret;
4806
4807 ret = (xmlSchemaQNameRefPtr)
4808 xmlMalloc(sizeof(xmlSchemaQNameRef));
4809 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004810 xmlSchemaPErrMemory(pctxt,
4811 "allocating QName reference item", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004812 return (NULL);
4813 }
4814 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4815 ret->name = refName;
4816 ret->targetNamespace = refNs;
4817 ret->item = NULL;
4818 ret->itemType = refType;
4819 /*
4820 * Store the reference item in the schema.
4821 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004822 ADD_LOCAL_ITEM(pctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004823 return (ret);
4824}
4825
4826/**
4827 * xmlSchemaAddModelGroup:
4828 * @ctxt: a schema parser context
4829 * @schema: the schema being built
4830 * @type: the "compositor" type of the model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004831 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004832 *
4833 * Adds a schema model group
4834 * *WARNING* this interface is highly subject to change
4835 *
4836 * Returns the new struture or NULL in case of error
4837 */
4838static xmlSchemaModelGroupPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004839xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
4840 xmlSchemaPtr schema,
4841 xmlSchemaTypeType type,
4842 xmlNodePtr node)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004843{
4844 xmlSchemaModelGroupPtr ret = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004845
4846 if ((ctxt == NULL) || (schema == NULL))
4847 return (NULL);
4848
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004849 ret = (xmlSchemaModelGroupPtr)
4850 xmlMalloc(sizeof(xmlSchemaModelGroup));
4851 if (ret == NULL) {
4852 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4853 NULL);
4854 return (NULL);
4855 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004856 memset(ret, 0, sizeof(xmlSchemaModelGroup));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004857 ret->type = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004858 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004859 ADD_LOCAL_ITEM(ctxt, ret);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004860 return (ret);
4861}
4862
4863
4864/**
4865 * xmlSchemaAddParticle:
4866 * @ctxt: a schema parser context
4867 * @schema: the schema being built
4868 * @node: the corresponding node in the schema doc
4869 * @min: the minOccurs
4870 * @max: the maxOccurs
4871 *
4872 * Adds an XML schema particle component.
4873 * *WARNING* this interface is highly subject to change
4874 *
4875 * Returns the new struture or NULL in case of error
4876 */
4877static xmlSchemaParticlePtr
4878xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4879 xmlNodePtr node, int min, int max)
4880{
4881 xmlSchemaParticlePtr ret = NULL;
4882 if ((ctxt == NULL) || (schema == NULL))
4883 return (NULL);
4884
4885#ifdef DEBUG
4886 fprintf(stderr, "Adding particle component\n");
4887#endif
4888 ret = (xmlSchemaParticlePtr)
4889 xmlMalloc(sizeof(xmlSchemaParticle));
4890 if (ret == NULL) {
4891 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4892 NULL);
4893 return (NULL);
4894 }
4895 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4896 ret->annot = NULL;
4897 ret->node = node;
4898 ret->minOccurs = min;
4899 ret->maxOccurs = max;
4900 ret->next = NULL;
4901 ret->children = NULL;
4902
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004903 ADD_LOCAL_ITEM(ctxt, ret);
4904 /*
4905 * Note that addition to pending components will be done locally
4906 * to the specific parsing function, since the most particles
4907 * need not to be fixed up (i.e. the reference to be resolved).
4908 * REMOVED: WXS_ADD_PENDING_ITEM(ctxt, ret);
4909 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004910 return (ret);
4911}
4912
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004913/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004914 * xmlSchemaAddModelGroupDefinition:
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004915 * @ctxt: a schema validation context
4916 * @schema: the schema being built
4917 * @name: the group name
4918 *
4919 * Add an XML schema Group definition
4920 *
4921 * Returns the new struture or NULL in case of error
4922 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004923static xmlSchemaModelGroupDefPtr
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004924xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
4925 xmlSchemaPtr schema,
4926 const xmlChar *name,
4927 const xmlChar *nsName,
4928 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004929{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004930 xmlSchemaModelGroupDefPtr ret = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004931 xmlHashTablePtr *table = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004932 int val;
4933
4934 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4935 return (NULL);
4936
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004937 WXS_GET_GLOBAL_HASH(WXS_SCHEMA_BUCKET(ctxt), schema, groupDecl)
4938 WXS_INIT_GLOBAL_HASH(ctxt, table)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004939
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004940 ret = (xmlSchemaModelGroupDefPtr)
4941 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004942 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004943 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004944 return (NULL);
4945 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004946 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004947 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004948 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004949 ret->node = node;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004950 ret->targetNamespace = nsName;
4951
4952 val = xmlHashAddEntry(*table, ret->name, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004953 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004954 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004955 XML_SCHEMAP_REDEFINED_GROUP,
4956 NULL, NULL, node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004957 "A global model group definition with the name '%s' does "
4958 "already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004959 xmlFree(ret);
4960 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004961 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004962 ADD_GLOBAL_ITEM(ctxt, ret);
4963 WXS_ADD_PENDING_ITEM(ctxt, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004964 return (ret);
4965}
4966
Daniel Veillard3646d642004-06-02 19:19:14 +00004967/**
4968 * xmlSchemaNewWildcardNs:
4969 * @ctxt: a schema validation context
4970 *
4971 * Creates a new wildcard namespace constraint.
4972 *
4973 * Returns the new struture or NULL in case of error
4974 */
4975static xmlSchemaWildcardNsPtr
4976xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4977{
4978 xmlSchemaWildcardNsPtr ret;
4979
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004980 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004981 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4982 if (ret == NULL) {
4983 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004984 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00004985 }
4986 ret->value = NULL;
4987 ret->next = NULL;
4988 return (ret);
4989}
4990
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00004991static xmlSchemaIDCPtr
4992xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4993 const xmlChar *name, const xmlChar *nsName,
4994 int category, xmlNodePtr node)
4995{
4996 xmlSchemaIDCPtr ret = NULL;
4997 xmlHashTablePtr *table = NULL;
4998 int val;
4999
5000 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5001 return (NULL);
5002
5003 WXS_GET_GLOBAL_HASH(WXS_SCHEMA_BUCKET(ctxt), schema, idcDef)
5004 WXS_INIT_GLOBAL_HASH(ctxt, table)
5005
5006 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5007 if (ret == NULL) {
5008 xmlSchemaPErrMemory(ctxt,
5009 "allocating an identity-constraint definition", NULL);
5010 return (NULL);
5011 }
5012 memset(ret, 0, sizeof(xmlSchemaIDC));
5013 /* The target namespace of the parent element declaration. */
5014 ret->targetNamespace = nsName;
5015 ret->name = name;
5016 ret->type = category;
5017 ret->node = node;
5018
5019 val = xmlHashAddEntry(*table, ret->name, ret);
5020 if (val != 0) {
5021 xmlSchemaPCustomErrExt(ctxt,
5022 /* TODO: Error code! */
5023 XML_SCHEMAP_REDEFINED_TYPE,
5024 NULL, NULL, node,
5025 "An identity-constraint definition with the name '%s' "
5026 "and targetNamespace '%s' does already exist",
5027 ret->name, ret->targetNamespace, NULL);
5028
5029 xmlFree(ret);
5030 return (NULL);
5031 }
5032 ADD_GLOBAL_ITEM(ctxt, ret);
5033 /*
5034 * Only keyrefs need to be fixup up.
5035 */
5036 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5037 WXS_ADD_PENDING_ITEM(ctxt, ret);
5038 return (ret);
5039}
5040
Daniel Veillard3646d642004-06-02 19:19:14 +00005041/**
5042 * xmlSchemaAddWildcard:
5043 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005044 * @schema: a schema
5045 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005046 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005047 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00005048 *
5049 * Returns the new struture or NULL in case of error
5050 */
5051static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005052xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5053 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00005054{
5055 xmlSchemaWildcardPtr ret = NULL;
5056
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005057 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00005058 return (NULL);
5059
5060 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5061 if (ret == NULL) {
5062 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5063 return (NULL);
5064 }
5065 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005066 ret->type = type;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005067 ret->node = node;
Daniel Veillard3646d642004-06-02 19:19:14 +00005068 ret->minOccurs = 1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005069 ret->maxOccurs = 1;
5070
5071 ADD_LOCAL_ITEM(ctxt, ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00005072 return (ret);
5073}
5074
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005075static void
5076xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5077{
5078 if (group == NULL)
5079 return;
5080 if (group->members != NULL)
5081 xmlSchemaItemListFree(group->members);
5082 xmlFree(group);
5083}
5084
5085static xmlSchemaSubstGroupPtr
5086xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5087 xmlSchemaElementPtr head)
5088{
5089 xmlSchemaSubstGroupPtr ret;
5090
5091 /* Init subst group hash. */
5092 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5093 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5094 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5095 return(NULL);
5096 }
5097 /* Create a new substitution group. */
5098 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5099 if (ret == NULL) {
5100 xmlSchemaPErrMemory(NULL,
5101 "allocating a substitution group container", NULL);
5102 return(NULL);
5103 }
5104 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5105 ret->head = head;
5106 /* Create list of members. */
5107 ret->members = xmlSchemaItemListCreate();
5108 if (ret->members == NULL) {
5109 xmlSchemaSubstGroupFree(ret);
5110 return(NULL);
5111 }
5112 /* Add subst group to hash. */
5113 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5114 head->name, head->targetNamespace, ret) != 0) {
5115 PERROR_INT("xmlSchemaSubstGroupAdd",
5116 "failed to add a new substitution container");
5117 xmlSchemaSubstGroupFree(ret);
5118 return(NULL);
5119 }
5120 return(ret);
5121}
5122
5123static xmlSchemaSubstGroupPtr
5124xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5125 xmlSchemaElementPtr head)
5126{
5127 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5128 return(NULL);
5129 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5130 head->name, head->targetNamespace));
5131
5132}
5133
5134/**
5135 * xmlSchemaAddElementSubstitutionMember:
5136 * @pctxt: a schema parser context
5137 * @head: the head of the substitution group
5138 * @member: the new member of the substitution group
5139 *
5140 * Allocate a new annotation structure.
5141 *
5142 * Returns the newly allocated structure or NULL in case or error
5143 */
5144static int
5145xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5146 xmlSchemaElementPtr head,
5147 xmlSchemaElementPtr member)
5148{
5149 xmlSchemaSubstGroupPtr substGroup = NULL;
5150
5151 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5152 return (-1);
5153
5154 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5155 if (substGroup == NULL)
5156 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5157 if (substGroup == NULL)
5158 return(-1);
5159 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5160 return(-1);
5161 return(0);
5162}
5163
Daniel Veillard4255d502002-04-16 15:50:10 +00005164/************************************************************************
5165 * *
5166 * Utilities for parsing *
5167 * *
5168 ************************************************************************/
5169
Daniel Veillard4255d502002-04-16 15:50:10 +00005170/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005171 * xmlSchemaPValAttrNodeQNameValue:
5172 * @ctxt: a schema parser context
5173 * @schema: the schema context
5174 * @ownerDes: the designation of the parent element
5175 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005176 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00005177 * @local: the resulting local part if found, the attribute value otherwise
5178 * @uri: the resulting namespace URI if found
5179 *
5180 * Extracts the local name and the URI of a QName value and validates it.
5181 * This one is intended to be used on attribute values that
5182 * should resolve to schema components.
5183 *
5184 * Returns 0, in case the QName is valid, a positive error code
5185 * if not valid and -1 if an internal error occurs.
5186 */
5187static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005188xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005189 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005190 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005191 xmlSchemaTypePtr ownerItem,
5192 xmlAttrPtr attr,
5193 const xmlChar *value,
5194 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005195 const xmlChar **local)
5196{
5197 const xmlChar *pref;
5198 xmlNsPtr ns;
5199 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005200
Daniel Veillardc0826a72004-08-10 14:17:33 +00005201 *uri = NULL;
5202 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005203 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005204 if (ret > 0) {
5205 xmlSchemaPSimpleTypeErr(ctxt,
5206 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5207 ownerItem, (xmlNodePtr) attr,
5208 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5209 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005210 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005211 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005212 } else if (ret < 0)
5213 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005214
5215 if (!strchr((char *) value, ':')) {
Daniel Veillard24505b02005-07-28 23:49:35 +00005216 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005217 if (ns)
5218 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5219 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005220 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5221 * parser context. */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005222 /*
5223 * This one takes care of included schemas with no
5224 * target namespace.
5225 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005226 *uri = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005227 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005228 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005229 return (0);
5230 }
5231 /*
5232 * At this point xmlSplitQName3 has to return a local name.
5233 */
5234 *local = xmlSplitQName3(value, &len);
5235 *local = xmlDictLookup(ctxt->dict, *local, -1);
5236 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005237 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5238 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005239 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005240 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005241 ownerItem, (xmlNodePtr) attr,
5242 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5243 "The value '%s' of simple type 'xs:QName' has no "
5244 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005245 return (ctxt->err);
5246 } else {
5247 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005248 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005249 return (0);
5250}
5251
5252/**
5253 * xmlSchemaPValAttrNodeQName:
5254 * @ctxt: a schema parser context
5255 * @schema: the schema context
5256 * @ownerDes: the designation of the owner element
5257 * @ownerItem: the owner as a schema object
5258 * @attr: the attribute node
5259 * @local: the resulting local part if found, the attribute value otherwise
5260 * @uri: the resulting namespace URI if found
5261 *
5262 * Extracts and validates the QName of an attribute value.
5263 * This one is intended to be used on attribute values that
5264 * should resolve to schema components.
5265 *
5266 * Returns 0, in case the QName is valid, a positive error code
5267 * if not valid and -1 if an internal error occurs.
5268 */
5269static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005270xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005271 xmlSchemaPtr schema,
5272 xmlChar **ownerDes,
5273 xmlSchemaTypePtr ownerItem,
5274 xmlAttrPtr attr,
5275 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005276 const xmlChar **local)
5277{
5278 const xmlChar *value;
5279
5280 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005281 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5282 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005283}
5284
5285/**
5286 * xmlSchemaPValAttrQName:
5287 * @ctxt: a schema parser context
5288 * @schema: the schema context
5289 * @ownerDes: the designation of the parent element
5290 * @ownerItem: the owner as a schema object
5291 * @ownerElem: the parent node of the attribute
5292 * @name: the name of the attribute
5293 * @local: the resulting local part if found, the attribute value otherwise
5294 * @uri: the resulting namespace URI if found
5295 *
5296 * Extracts and validates the QName of an attribute value.
5297 *
5298 * Returns 0, in case the QName is valid, a positive error code
5299 * if not valid and -1 if an internal error occurs.
5300 */
5301static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005302xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5303 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005304 xmlChar **ownerDes,
5305 xmlSchemaTypePtr ownerItem,
5306 xmlNodePtr ownerElem,
5307 const char *name,
5308 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005309 const xmlChar **local)
5310{
5311 xmlAttrPtr attr;
5312
5313 attr = xmlSchemaGetPropNode(ownerElem, name);
5314 if (attr == NULL) {
5315 *local = NULL;
5316 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005317 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005318 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005319 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5320 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005321}
5322
5323/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005324 * xmlSchemaPValAttrID:
5325 * @ctxt: a schema parser context
5326 * @schema: the schema context
5327 * @ownerDes: the designation of the parent element
5328 * @ownerItem: the owner as a schema object
5329 * @ownerElem: the parent node of the attribute
5330 * @name: the name of the attribute
5331 *
5332 * Extracts and validates the ID of an attribute value.
5333 *
5334 * Returns 0, in case the ID is valid, a positive error code
5335 * if not valid and -1 if an internal error occurs.
5336 */
5337static int
5338xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005339 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005340 xmlSchemaTypePtr ownerItem,
5341 xmlNodePtr ownerElem,
5342 const xmlChar *name)
5343{
5344 int ret;
5345 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005346 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005347
5348 value = xmlGetNoNsProp(ownerElem, name);
5349 if (value == NULL)
5350 return (0);
5351
5352 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5353 if (attr == NULL)
5354 return (-1);
5355
5356 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005357 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005358 /*
5359 * NOTE: the IDness might have already be declared in the DTD
5360 */
5361 if (attr->atype != XML_ATTRIBUTE_ID) {
5362 xmlIDPtr res;
5363 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005364
5365 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005366 * TODO: Use xmlSchemaStrip here; it's not exported at this
5367 * moment.
5368 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005369 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005370 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005371 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005372 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5373 if (res == NULL) {
5374 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005375 xmlSchemaPSimpleTypeErr(ctxt,
5376 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5377 ownerItem, (xmlNodePtr) attr,
5378 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5379 NULL, NULL, "Duplicate value '%s' of simple "
5380 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005381 } else
5382 attr->atype = XML_ATTRIBUTE_ID;
5383 if (strip != NULL)
5384 xmlFree(strip);
5385 }
5386 } else if (ret > 0) {
5387 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005388 xmlSchemaPSimpleTypeErr(ctxt,
5389 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5390 ownerItem, (xmlNodePtr) attr,
5391 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5392 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5393 "not a valid 'xs:NCName'",
5394 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005395 }
5396 xmlFree(value);
5397
5398 return (ret);
5399}
5400
5401/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005402 * xmlGetMaxOccurs:
5403 * @ctxt: a schema validation context
5404 * @node: a subtree containing XML Schema informations
5405 *
5406 * Get the maxOccurs property
5407 *
5408 * Returns the default if not found, or the value
5409 */
5410static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005411xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5412 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005413{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005414 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005415 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005416 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005417
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005418 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5419 if (attr == NULL)
5420 return (def);
5421 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005422
5423 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005424 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005425 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005426 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5427 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005428 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005429 val, NULL, NULL, NULL);
5430 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005431 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005432 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005433 }
5434
5435 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005436 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005437 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005438 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005439 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005440 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5441 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005442 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005443 val, NULL, NULL, NULL);
5444 return (def);
5445 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005446 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005447 ret = ret * 10 + (*cur - '0');
5448 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005449 }
William M. Brack76e95df2003-10-18 16:20:14 +00005450 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005451 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005452 /*
5453 * TODO: Restrict the maximal value to Integer.
5454 */
5455 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005456 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005457 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5458 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005459 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005460 val, NULL, NULL, NULL);
5461 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005462 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005463 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005464}
5465
5466/**
5467 * xmlGetMinOccurs:
5468 * @ctxt: a schema validation context
5469 * @node: a subtree containing XML Schema informations
5470 *
5471 * Get the minOccurs property
5472 *
5473 * Returns the default if not found, or the value
5474 */
5475static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005476xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005477 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005478{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005479 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005480 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005481 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005482
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005483 attr = xmlSchemaGetPropNode(node, "minOccurs");
5484 if (attr == NULL)
5485 return (def);
5486 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005487 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005488 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005489 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005490 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005491 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005492 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5493 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005494 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005495 val, NULL, NULL, NULL);
5496 return (def);
5497 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005498 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005499 ret = ret * 10 + (*cur - '0');
5500 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005501 }
William M. Brack76e95df2003-10-18 16:20:14 +00005502 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005503 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005504 /*
5505 * TODO: Restrict the maximal value to Integer.
5506 */
5507 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005508 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005509 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5510 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005511 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005512 val, NULL, NULL, NULL);
5513 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005514 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005515 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005516}
5517
5518/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005519 * xmlSchemaPGetBoolNodeValue:
5520 * @ctxt: a schema validation context
5521 * @ownerDes: owner designation
5522 * @ownerItem: the owner as a schema item
5523 * @node: the node holding the value
5524 *
5525 * Converts a boolean string value into 1 or 0.
5526 *
5527 * Returns 0 or 1.
5528 */
5529static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005530xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5531 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005532 xmlSchemaTypePtr ownerItem,
5533 xmlNodePtr node)
5534{
5535 xmlChar *value = NULL;
5536 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005537
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005538 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005539 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005540 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005541 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005542 * can have the following legal literals {true, false, 1, 0}.
5543 */
5544 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5545 res = 1;
5546 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5547 res = 0;
5548 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5549 res = 1;
5550 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005551 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005552 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005553 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005554 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005555 ownerItem, node,
5556 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5557 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005558 NULL, NULL, NULL);
5559 }
5560 if (value != NULL)
5561 xmlFree(value);
5562 return (res);
5563}
5564
5565/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005566 * xmlGetBooleanProp:
5567 * @ctxt: a schema validation context
5568 * @node: a subtree containing XML Schema informations
5569 * @name: the attribute name
5570 * @def: the default value
5571 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005572 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005573 *
5574 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005575 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005576 */
5577static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005578xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5579 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005580 xmlSchemaTypePtr ownerItem,
5581 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005582 const char *name, int def)
5583{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005584 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005585
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005586 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005587 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005588 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005589 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005590 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005591 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005592 * can have the following legal literals {true, false, 1, 0}.
5593 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005594 if (xmlStrEqual(val, BAD_CAST "true"))
5595 def = 1;
5596 else if (xmlStrEqual(val, BAD_CAST "false"))
5597 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005598 else if (xmlStrEqual(val, BAD_CAST "1"))
5599 def = 1;
5600 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005601 def = 0;
5602 else {
5603 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005604 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005605 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005606 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005607 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5608 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005609 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005610 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005611}
5612
5613/************************************************************************
5614 * *
5615 * Shema extraction from an Infoset *
5616 * *
5617 ************************************************************************/
5618static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5619 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005620 xmlNodePtr node,
5621 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005622static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5623 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005624 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005625 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005626 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005627static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5628 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005629 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005630 xmlNodePtr node,
5631 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005632static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5633 ctxt,
5634 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005635 xmlNodePtr node,
5636 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005637static xmlSchemaAttributeGroupPtr
5638xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005639 xmlSchemaPtr schema, xmlNodePtr node,
5640 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005641static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5642 xmlSchemaPtr schema,
5643 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005644static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005645xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5646 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005647
5648/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005649 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005650 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005651 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005652 * @ownerDes: the designation of the parent element
5653 * @ownerItem: the schema object owner if existent
5654 * @attr: the schema attribute node being validated
5655 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005656 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005657 *
5658 * Validates a value against the given built-in type.
5659 * This one is intended to be used internally for validation
5660 * of schema attribute values during parsing of the schema.
5661 *
5662 * Returns 0 if the value is valid, a positive error code
5663 * number otherwise and -1 in case of an internal or API error.
5664 */
5665static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005666xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5667 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5668 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005669 xmlAttrPtr attr,
5670 const xmlChar *value,
5671 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005672{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005673
5674 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005675
5676 /*
5677 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5678 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005679 */
5680 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005681 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005682 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5683 PERROR_INT("xmlSchemaPValAttrNodeValue",
5684 "the given type is not a built-in type");
5685 return (-1);
5686 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005687 switch (type->builtInType) {
5688 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005689 case XML_SCHEMAS_QNAME:
5690 case XML_SCHEMAS_ANYURI:
5691 case XML_SCHEMAS_TOKEN:
5692 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005693 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5694 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005695 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005696 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005697 PERROR_INT("xmlSchemaPValAttrNodeValue",
5698 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005699 return (-1);
5700 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005701 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005702 /*
5703 * TODO: Should we use the S4S error codes instead?
5704 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005705 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005706 PERROR_INT("xmlSchemaPValAttrNodeValue",
5707 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005708 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005709 } else if (ret > 0) {
5710 if (VARIETY_LIST(type))
5711 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5712 else
5713 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5714 xmlSchemaPSimpleTypeErr(pctxt,
5715 ret, ownerItem, (xmlNodePtr) attr,
5716 type, NULL, value, NULL, NULL, NULL);
5717 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005718 return (ret);
5719}
5720
5721/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005722 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005723 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005724 * @ctxt: a schema parser context
5725 * @ownerDes: the designation of the parent element
5726 * @ownerItem: the schema object owner if existent
5727 * @attr: the schema attribute node being validated
5728 * @type: the built-in type to be validated against
5729 * @value: the resulting value if any
5730 *
5731 * Extracts and validates a value against the given built-in type.
5732 * This one is intended to be used internally for validation
5733 * of schema attribute values during parsing of the schema.
5734 *
5735 * Returns 0 if the value is valid, a positive error code
5736 * number otherwise and -1 in case of an internal or API error.
5737 */
5738static int
5739xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5740 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005741 xmlSchemaTypePtr ownerItem,
5742 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005743 xmlSchemaTypePtr type,
5744 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005745{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005746 const xmlChar *val;
5747
5748 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005749 return (-1);
5750
Daniel Veillardc0826a72004-08-10 14:17:33 +00005751 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5752 if (value != NULL)
5753 *value = val;
5754
5755 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005756 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005757}
5758
5759/**
5760 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005761 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005762 * @ctxt: a schema parser context
5763 * @node: the element node of the attribute
5764 * @ownerDes: the designation of the parent element
5765 * @ownerItem: the schema object owner if existent
5766 * @ownerElem: the owner element node
5767 * @name: the name of the schema attribute node
5768 * @type: the built-in type to be validated against
5769 * @value: the resulting value if any
5770 *
5771 * Extracts and validates a value against the given built-in type.
5772 * This one is intended to be used internally for validation
5773 * of schema attribute values during parsing of the schema.
5774 *
5775 * Returns 0 if the value is valid, a positive error code
5776 * number otherwise and -1 in case of an internal or API error.
5777 */
5778static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005779xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005780 xmlChar **ownerDes,
5781 xmlSchemaTypePtr ownerItem,
5782 xmlNodePtr ownerElem,
5783 const char *name,
5784 xmlSchemaTypePtr type,
5785 const xmlChar **value)
5786{
5787 xmlAttrPtr attr;
5788
5789 if ((ctxt == NULL) || (type == NULL)) {
5790 if (value != NULL)
5791 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005792 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005793 }
5794 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5795 if (value != NULL)
5796 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005797 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005798 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005799 "Internal error: xmlSchemaPValAttr, the given "
5800 "type '%s' is not a built-in type.\n",
5801 type->name, NULL);
5802 return (-1);
5803 }
5804 attr = xmlSchemaGetPropNode(ownerElem, name);
5805 if (attr == NULL) {
5806 if (value != NULL)
5807 *value = NULL;
5808 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005809 }
5810 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005811 type, value));
5812}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005813
5814static int
5815xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005816 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005817 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005818 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005819 const xmlChar *namespaceName)
5820{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005821 /* TODO: Pointer comparison instead? */
5822 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005823 return (1);
5824 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5825 return (1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005826 /*
5827 * Check if the referenced namespace was <import>ed.
5828 */
5829 if (WXS_SCHEMA_BUCKET(pctxt)->relations != NULL) {
5830 xmlSchemaSchemaRelationPtr rel;
5831
5832 rel = WXS_SCHEMA_BUCKET(pctxt)->relations;
5833 do {
5834 if (WXS_IS_IMPMAIN(rel->type) &&
5835 xmlStrEqual(namespaceName, rel->importNamespace))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005836 return (1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005837 rel = rel->next;
5838 } while (rel != NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005839 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00005840 /*
5841 * No matching <import>ed namespace found.
5842 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005843 if (namespaceName == NULL)
5844 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005845 NULL, (xmlSchemaTypePtr) item, node,
5846 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005847 "namespace are not valid, since not indicated by an import "
5848 "statement", NULL);
5849 else
5850 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005851 NULL, (xmlSchemaTypePtr) item, node,
5852 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005853 "namespace '%s' are not valid, since not indicated by an import "
5854 "statement", namespaceName);
5855 return (0);
5856}
5857
Daniel Veillardc0826a72004-08-10 14:17:33 +00005858/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005859 * xmlSchemaParseAttrDecls:
5860 * @ctxt: a schema validation context
5861 * @schema: the schema being built
5862 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005863 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005864 *
5865 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005866 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005867 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5868 */
5869static xmlNodePtr
5870xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5871 xmlNodePtr child, xmlSchemaTypePtr type)
5872{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005873 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005874
Daniel Veillard4255d502002-04-16 15:50:10 +00005875 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005876 (IS_SCHEMA(child, "attributeGroup"))) {
5877 attr = NULL;
5878 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005879 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005880 } else if (IS_SCHEMA(child, "attributeGroup")) {
5881 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005882 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005883 }
5884 if (attr != NULL) {
5885 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005886 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5887 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5888 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005889 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005890 lastattr = attr;
5891 } else {
5892 lastattr->next = attr;
5893 lastattr = attr;
5894 }
5895 }
5896 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005897 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005898 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005899}
5900
5901/**
5902 * xmlSchemaParseAnnotation:
5903 * @ctxt: a schema validation context
5904 * @schema: the schema being built
5905 * @node: a subtree containing XML Schema informations
5906 *
5907 * parse a XML schema Attrribute declaration
5908 * *WARNING* this interface is highly subject to change
5909 *
William M. Bracke7091952004-05-11 15:09:58 +00005910 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005911 * 1 in case of success.
5912 */
5913static xmlSchemaAnnotPtr
5914xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5915 xmlNodePtr node)
5916{
5917 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005918 xmlNodePtr child = NULL;
5919 xmlAttrPtr attr;
5920 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005921
Daniel Veillardc0826a72004-08-10 14:17:33 +00005922 /*
5923 * INFO: S4S completed.
5924 */
5925 /*
5926 * id = ID
5927 * {any attributes with non-schema namespace . . .}>
5928 * Content: (appinfo | documentation)*
5929 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005930 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5931 return (NULL);
5932 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005933 attr = node->properties;
5934 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005935 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005936 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005937 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005938 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005939
5940 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005941 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5942 NULL, NULL, attr);
5943 }
5944 attr = attr->next;
5945 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005946 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005947 /*
5948 * And now for the children...
5949 */
5950 child = node->children;
5951 while (child != NULL) {
5952 if (IS_SCHEMA(child, "appinfo")) {
5953 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005954 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005955 * source = anyURI
5956 * {any attributes with non-schema namespace . . .}>
5957 * Content: ({any})*
5958 */
5959 attr = child->properties;
5960 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005961 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005962 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005963 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005964 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005965
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005966 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005967 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5968 NULL, NULL, attr);
5969 }
5970 attr = attr->next;
5971 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005972 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5973 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005974 child = child->next;
5975 } else if (IS_SCHEMA(child, "documentation")) {
5976 /* TODO: make available the content of "documentation". */
5977 /*
5978 * source = anyURI
5979 * {any attributes with non-schema namespace . . .}>
5980 * Content: ({any})*
5981 */
5982 attr = child->properties;
5983 while (attr != NULL) {
5984 if (attr->ns == NULL) {
5985 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005986 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005987 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5988 NULL, NULL, attr);
5989 }
5990 } else {
5991 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5992 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5993 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005994
5995 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005996 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5997 NULL, NULL, attr);
5998 }
5999 }
6000 attr = attr->next;
6001 }
6002 /*
6003 * Attribute "xml:lang".
6004 */
6005 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6006 if (attr != NULL)
6007 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006008 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006009 child = child->next;
6010 } else {
6011 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006012 xmlSchemaPContentErr(ctxt,
6013 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006014 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
6015 barked = 1;
6016 child = child->next;
6017 }
6018 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006019
Daniel Veillard4255d502002-04-16 15:50:10 +00006020 return (ret);
6021}
6022
6023/**
6024 * xmlSchemaParseFacet:
6025 * @ctxt: a schema validation context
6026 * @schema: the schema being built
6027 * @node: a subtree containing XML Schema informations
6028 *
6029 * parse a XML schema Facet declaration
6030 * *WARNING* this interface is highly subject to change
6031 *
6032 * Returns the new type structure or NULL in case of error
6033 */
6034static xmlSchemaFacetPtr
6035xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006036 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006037{
6038 xmlSchemaFacetPtr facet;
6039 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006040 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00006041
6042 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6043 return (NULL);
6044
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006045 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006046 if (facet == NULL) {
6047 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6048 return (NULL);
6049 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006050 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006051 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00006052 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006053 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6054 "Facet %s has no value\n", node->name, NULL);
6055 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00006056 return (NULL);
6057 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006058 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006059 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006060 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006061 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006062 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006063 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006064 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006065 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006066 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006067 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006068 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006069 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006070 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006071 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006072 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006073 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006074 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006075 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006076 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006077 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006078 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006079 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6080 } else if (IS_SCHEMA(node, "minLength")) {
6081 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6082 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006083 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6084 "Unknown facet type %s\n", node->name, NULL);
6085 xmlSchemaFreeFacet(facet);
6086 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006087 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006088 xmlSchemaPValAttrID(ctxt, NULL,
6089 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006090 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006091 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6092 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6093 const xmlChar *fixed;
6094
6095 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6096 if (fixed != NULL) {
6097 if (xmlStrEqual(fixed, BAD_CAST "true"))
6098 facet->fixed = 1;
6099 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006100 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006101 child = node->children;
6102
6103 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006104 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6105 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006106 }
6107 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006108 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6109 "Facet %s has unexpected child content\n",
6110 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006111 }
6112 return (facet);
6113}
6114
6115/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006116 * xmlSchemaParseWildcardNs:
6117 * @ctxt: a schema parser context
6118 * @wildc: the wildcard, already created
6119 * @node: a subtree containing XML Schema informations
6120 *
6121 * Parses the attribute "processContents" and "namespace"
6122 * of a xsd:anyAttribute and xsd:any.
6123 * *WARNING* this interface is highly subject to change
6124 *
6125 * Returns 0 if everything goes fine, a positive error code
6126 * if something is not valid and -1 if an internal error occurs.
6127 */
6128static int
6129xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006130 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006131 xmlSchemaWildcardPtr wildc,
6132 xmlNodePtr node)
6133{
6134 const xmlChar *pc, *ns, *dictnsItem;
6135 int ret = 0;
6136 xmlChar *nsItem;
6137 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6138 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006139
Daniel Veillardc0826a72004-08-10 14:17:33 +00006140 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6141 if ((pc == NULL)
6142 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6143 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6144 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6145 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6146 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6147 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6148 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006149 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006150 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006151 NULL, node,
6152 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006153 NULL, NULL, NULL);
6154 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006155 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006156 }
6157 /*
6158 * Build the namespace constraints.
6159 */
6160 attr = xmlSchemaGetPropNode(node, "namespace");
6161 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006162 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006163 wildc->any = 1;
6164 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6165 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006166 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006167 return (-1);
6168 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006169 wildc->negNsSet->value = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006170 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006171 const xmlChar *end, *cur;
6172
6173 cur = ns;
6174 do {
6175 while (IS_BLANK_CH(*cur))
6176 cur++;
6177 end = cur;
6178 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6179 end++;
6180 if (end == cur)
6181 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006182 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006183 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6184 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006185 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006186 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006187 NULL, (xmlNodePtr) attr,
6188 NULL,
6189 "((##any | ##other) | List of (xs:anyURI | "
6190 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006191 nsItem, NULL, NULL, NULL);
6192 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6193 } else {
6194 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006195 dictnsItem = ctxt->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006196 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6197 dictnsItem = NULL;
6198 } else {
6199 /*
6200 * Validate the item (anyURI).
6201 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006202 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006203 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6204 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6205 }
6206 /*
6207 * Avoid dublicate namespaces.
6208 */
6209 tmp = wildc->nsSet;
6210 while (tmp != NULL) {
6211 if (dictnsItem == tmp->value)
6212 break;
6213 tmp = tmp->next;
6214 }
6215 if (tmp == NULL) {
6216 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6217 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006218 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006219 return (-1);
6220 }
6221 tmp->value = dictnsItem;
6222 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006223 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006224 wildc->nsSet = tmp;
6225 else
6226 lastNs->next = tmp;
6227 lastNs = tmp;
6228 }
6229
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006230 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006231 xmlFree(nsItem);
6232 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006233 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006234 }
6235 return (ret);
6236}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006237
6238static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006239xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6240 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006241 xmlNodePtr node,
6242 int minOccurs,
6243 int maxOccurs) {
6244
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006245 if ((maxOccurs == 0) && ( minOccurs == 0))
6246 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006247 if (maxOccurs != UNBOUNDED) {
6248 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006249 * TODO: Maybe we should better not create the particle,
6250 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006251 * content model.
6252 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006253 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006254 * 3.9.6 Schema Component Constraint: Particle Correct
6255 *
6256 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006257 if (maxOccurs < 1) {
6258 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006259 * 2.2 {max occurs} must be greater than or equal to 1.
6260 */
6261 xmlSchemaPCustomAttrErr(ctxt,
6262 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006263 NULL, NULL,
6264 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006265 "The value must be greater than or equal to 1");
6266 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6267 } else if (minOccurs > maxOccurs) {
6268 /*
6269 * 2.1 {min occurs} must not be greater than {max occurs}.
6270 */
6271 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006272 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006273 NULL, NULL,
6274 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006275 "The value must not be greater than the value of 'maxOccurs'");
6276 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6277 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006278 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006279 return (0);
6280}
6281
Daniel Veillardc0826a72004-08-10 14:17:33 +00006282/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006283 * xmlSchemaParseAny:
6284 * @ctxt: a schema validation context
6285 * @schema: the schema being built
6286 * @node: a subtree containing XML Schema informations
6287 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006288 * Parsea a XML schema <any> element. A particle and wildcard
6289 * will be created (except if minOccurs==maxOccurs==0, in this case
6290 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006291 * *WARNING* this interface is highly subject to change
6292 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006293 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006294 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006295static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006296xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6297 xmlNodePtr node)
6298{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006299 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006300 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006301 xmlSchemaWildcardPtr wild;
6302 int min, max;
6303 xmlAttrPtr attr;
6304 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006305
6306 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6307 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006308 /*
6309 * Check for illegal attributes.
6310 */
6311 attr = node->properties;
6312 while (attr != NULL) {
6313 if (attr->ns == NULL) {
6314 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6315 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6316 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6317 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6318 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006319 xmlSchemaPIllegalAttrErr(ctxt,
6320 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6321 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006322 }
6323 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006324 xmlSchemaPIllegalAttrErr(ctxt,
6325 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6326 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006327 }
6328 attr = attr->next;
6329 }
6330 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6331 /*
6332 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006333 */
6334 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6335 "(xs:nonNegativeInteger | unbounded)");
6336 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6337 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006338 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6339 /*
6340 * Create & parse the wildcard.
6341 */
6342 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6343 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006344 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006345 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006346 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006347 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006348 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006349 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006350 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006351 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006352 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006353 }
6354 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006355 xmlSchemaPContentErr(ctxt,
6356 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006357 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006358 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006359 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006360 /*
6361 * No component if minOccurs==maxOccurs==0.
6362 */
6363 if ((min == 0) && (max == 0)) {
6364 /* Don't free the wildcard, since it's already on the list. */
6365 return (NULL);
6366 }
6367 /*
6368 * Create the particle.
6369 */
6370 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6371 if (particle == NULL)
6372 return (NULL);
6373 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006374 wild->minOccurs = min;
6375 wild->maxOccurs = max;
6376 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006377
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006378 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006379}
6380
6381/**
6382 * xmlSchemaParseNotation:
6383 * @ctxt: a schema validation context
6384 * @schema: the schema being built
6385 * @node: a subtree containing XML Schema informations
6386 *
6387 * parse a XML schema Notation declaration
6388 *
6389 * Returns the new structure or NULL in case of error
6390 */
6391static xmlSchemaNotationPtr
6392xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006393 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006394{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006395 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006396 xmlSchemaNotationPtr ret;
6397 xmlNodePtr child = NULL;
6398
6399 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6400 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006401 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006402 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006403 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6404 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006405 return (NULL);
6406 }
6407 ret = xmlSchemaAddNotation(ctxt, schema, name);
6408 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006409 return (NULL);
6410 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006411 ret->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006412
6413 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6414 node, BAD_CAST "id");
6415
6416 if (IS_SCHEMA(child, "annotation")) {
6417 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6418 child = child->next;
6419 }
6420
Daniel Veillard4255d502002-04-16 15:50:10 +00006421 child = node->children;
6422 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006423 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6424 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006425 }
6426 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006427 xmlSchemaPContentErr(ctxt,
6428 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006429 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006430 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006431 }
6432
6433 return (ret);
6434}
6435
6436/**
6437 * xmlSchemaParseAnyAttribute:
6438 * @ctxt: a schema validation context
6439 * @schema: the schema being built
6440 * @node: a subtree containing XML Schema informations
6441 *
6442 * parse a XML schema AnyAttrribute declaration
6443 * *WARNING* this interface is highly subject to change
6444 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006445 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006446 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006447static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006448xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6449 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006450{
Daniel Veillard3646d642004-06-02 19:19:14 +00006451 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006452 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006453 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006454
6455 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6456 return (NULL);
6457
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006458 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6459 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006460 if (ret == NULL) {
6461 return (NULL);
6462 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006463 /*
6464 * Check for illegal attributes.
6465 */
6466 attr = node->properties;
6467 while (attr != NULL) {
6468 if (attr->ns == NULL) {
6469 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6470 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6471 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006472 xmlSchemaPIllegalAttrErr(ctxt,
6473 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6474 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006475 }
6476 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006477 xmlSchemaPIllegalAttrErr(ctxt,
6478 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6479 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006480 }
6481 attr = attr->next;
6482 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006483 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6484 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006485 /*
6486 * Parse the namespace list.
6487 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006488 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006489 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006490 /*
6491 * And now for the children...
6492 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006493 child = node->children;
6494 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006495 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6496 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006497 }
6498 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006499 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006500 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006501 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006502 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006503 }
6504
6505 return (ret);
6506}
6507
6508
6509/**
6510 * xmlSchemaParseAttribute:
6511 * @ctxt: a schema validation context
6512 * @schema: the schema being built
6513 * @node: a subtree containing XML Schema informations
6514 *
6515 * parse a XML schema Attrribute declaration
6516 * *WARNING* this interface is highly subject to change
6517 *
William M. Bracke7091952004-05-11 15:09:58 +00006518 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006519 */
6520static xmlSchemaAttributePtr
6521xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006522 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006523{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006524 const xmlChar *name, *attrValue;
6525 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006526 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006527 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006528 xmlAttrPtr attr, nameAttr;
6529 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006530
6531 /*
6532 * Note that the w3c spec assumes the schema to be validated with schema
6533 * for schemas beforehand.
6534 *
6535 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006536 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006537
6538 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6539 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006540 attr = xmlSchemaGetPropNode(node, "ref");
6541 nameAttr = xmlSchemaGetPropNode(node, "name");
6542
6543 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006544 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006545 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006546 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006547 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006548 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6549 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006550 "One of the attributes 'ref' or 'name' must be present");
6551 return (NULL);
6552 }
6553 if ((topLevel) || (attr == NULL)) {
6554 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006555 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6556 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006557 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006558 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006559 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006560 isRef = 1;
6561
Daniel Veillardc0826a72004-08-10 14:17:33 +00006562 if (isRef) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006563#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006564 char buf[50];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006565#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006566 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006567
6568 /*
6569 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006570 */
6571 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6572 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6573 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006574 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006575 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006576#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006577 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006578 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006579 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006580#else
6581 ret = xmlSchemaAddAttribute(ctxt, schema, NULL, NULL, node, 0);
6582#endif
6583
Daniel Veillardc0826a72004-08-10 14:17:33 +00006584 if (ret == NULL) {
6585 if (repName != NULL)
6586 xmlFree(repName);
6587 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006588 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006589 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6590 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006591 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006592 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006593 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6594 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006595 /*
6596 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6597 */
6598 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006599 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6600 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006601 "ref", "name");
6602 /*
6603 * Check for illegal attributes.
6604 */
6605 attr = node->properties;
6606 while (attr != NULL) {
6607 if (attr->ns == NULL) {
6608 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6609 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006610 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006611 * 3.2.3 : 3.2
6612 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006613 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006614 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006615 xmlSchemaPIllegalAttrErr(ctxt,
6616 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006617 (xmlSchemaTypePtr) ret, attr);
6618 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6619 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6620 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006621 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6622 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006623 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006624 xmlSchemaPIllegalAttrErr(ctxt,
6625 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6626 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006627 }
6628 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006629 xmlSchemaPIllegalAttrErr(ctxt,
6630 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6631 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006632 }
6633 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006634 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006635 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006636 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006637
Daniel Veillardc0826a72004-08-10 14:17:33 +00006638 /*
6639 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006640 */
6641 if (xmlSchemaPValAttrNode(ctxt,
6642 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006643 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6644 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006645 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006646 /*
6647 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6648 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006649 /*
6650 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6651 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006652 */
6653 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006654 xmlSchemaPSimpleTypeErr(ctxt,
6655 XML_SCHEMAP_NO_XMLNS,
6656 NULL, (xmlNodePtr) nameAttr,
6657 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6658 "The value of type 'xs:NCName' must not match 'xmlns'",
6659 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006660 if (repName != NULL)
6661 xmlFree(repName);
6662 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006663 }
6664 /*
6665 * Evaluate the target namespace
6666 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006667 if (topLevel) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006668 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006669 } else {
6670 attr = xmlSchemaGetPropNode(node, "form");
6671 if (attr != NULL) {
6672 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6673 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006674 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006675 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006676 xmlSchemaPSimpleTypeErr(ctxt,
6677 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6678 NULL, (xmlNodePtr) attr,
6679 NULL, "(qualified | unqualified)",
6680 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006681 }
6682 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006683 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
6684 ns = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006685 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006686 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006687 if (ret == NULL) {
6688 if (repName != NULL)
6689 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006690 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006691 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006692 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006693 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006694 if (topLevel)
6695 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006696 /*
6697 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6698 * TODO: Move this to the component layer.
6699 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006700 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006701 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006702 XML_SCHEMAP_NO_XSI,
6703 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006704 "The target namespace must not match '%s'",
6705 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006706 }
6707 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006708 * Check for illegal attributes.
6709 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006710 attr = node->properties;
6711 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006712 if (attr->ns == NULL) {
6713 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6714 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6715 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006716 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6717 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006718 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006719 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6720 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006721 xmlSchemaPIllegalAttrErr(ctxt,
6722 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6723 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006724 }
6725 }
6726 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006727 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6728 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006729 }
6730 attr = attr->next;
6731 }
6732 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006733 node, "type", &ret->typeNs, &ret->typeName);
6734 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006735 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6736 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006737 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006738 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006739 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006740 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6741 if (ret->defValue != NULL)
6742 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006743 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006744 * Attribute "default".
6745 */
6746 attr = xmlSchemaGetPropNode(node, "default");
6747 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006748 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006749 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006750 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006751 */
6752 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6753 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6754 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6755 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006756 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6757 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006758 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006759 /*
6760 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006761 */
6762 attr = xmlSchemaGetPropNode(node, "use");
6763 if (attr != NULL) {
6764 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6765 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6766 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6767 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6768 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6769 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6770 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6771 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006772 xmlSchemaPSimpleTypeErr(ctxt,
6773 XML_SCHEMAP_INVALID_ATTR_USE,
6774 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6775 NULL, "(optional | prohibited | required)",
6776 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006777 } else
6778 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006779 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006780 * 3.2.3 : 2
6781 * If default and use are both present, use must have
6782 * the actual value optional.
6783 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006784 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6785 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006786 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006787 xmlSchemaPSimpleTypeErr(ctxt,
6788 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6789 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6790 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006791 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006792 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006793 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006794 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006795 /*
6796 * And now for the children...
6797 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006798 child = node->children;
6799 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006800 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6801 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006802 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006803 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006804 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006805 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006806 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006807 * 3.2.3 : 3.2
6808 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006809 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006810 */
6811 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6812 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6813 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006814 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006815 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6816 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006817 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006818 }
6819 } else {
6820 if (IS_SCHEMA(child, "simpleType")) {
6821 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006822 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006823 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006824 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006825 */
6826 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6827 &repName, (xmlSchemaTypePtr) ret, node, child,
6828 "The attribute 'type' and the <simpleType> child "
6829 "are mutually exclusive", NULL);
6830 } else
6831 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6832 child = child->next;
6833 }
6834 if (child != NULL)
6835 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6836 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6837 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006838 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006839 /*
6840 * Cleanup.
6841 */
6842 if (repName != NULL)
6843 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006844 return (ret);
6845}
6846
6847/**
6848 * xmlSchemaParseAttributeGroup:
6849 * @ctxt: a schema validation context
6850 * @schema: the schema being built
6851 * @node: a subtree containing XML Schema informations
6852 *
6853 * parse a XML schema Attribute Group declaration
6854 * *WARNING* this interface is highly subject to change
6855 *
6856 * Returns the attribute group or NULL in case of error.
6857 */
6858static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006859xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006860 xmlSchemaPtr schema, xmlNodePtr node,
6861 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006862{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006863 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006864 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006865 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006866 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006867
6868 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6869 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006870
6871 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006872 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006873 if ((topLevel) || (attr == NULL)) {
6874 /*
6875 * Parse as an attribute group definition.
6876 * Note that those are allowed at top level only.
6877 */
6878 if (nameAttr == NULL) {
6879 xmlSchemaPMissingAttrErr(ctxt,
6880 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006881 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006882 return (NULL);
6883 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006884 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006885 * (xmlNodePtr) nameAttr);
6886 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006887 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006888 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006889 */
6890 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006891 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006892 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6893 return (NULL);
6894 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006895 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node, 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006896 if (ret == NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006897 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006898 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006899#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006900 char buf[50];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006901#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006902 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006903
6904 /*
6905 * Parse as an attribute group definition reference.
6906 */
6907 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006908 xmlSchemaPMissingAttrErr(ctxt,
6909 XML_SCHEMAP_S4S_ATTR_MISSING,
6910 NULL, node, "ref", NULL);
6911 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006912 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006913 NULL, NULL, attr, &refNs,&ref);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006914#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006915 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006916 name = (const xmlChar *) buf;
6917 if (name == NULL) {
6918 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6919 "attribute group definition reference", node);
6920 return (NULL);
6921 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006922 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node, 0);
6923#else
6924 ret = xmlSchemaAddAttributeGroup(ctxt, schema, NULL, node, 0);
6925#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006926 if (ret == NULL)
6927 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006928 ret->ref = ref;
6929 ret->refNs = refNs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006930 xmlSchemaCheckReference(ctxt, schema, node,
6931 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006932 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006933 /*
6934 * Check for illegal attributes.
6935 */
6936 attr = node->properties;
6937 while (attr != NULL) {
6938 if (attr->ns == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006939 if ((((topLevel == 0) &&
6940 (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006941 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006942 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006943 {
6944 xmlSchemaPIllegalAttrErr(ctxt,
6945 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6946 NULL, NULL, attr);
6947 }
6948 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6949 xmlSchemaPIllegalAttrErr(ctxt,
6950 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6951 NULL, NULL, attr);
6952 }
6953 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006954 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006955 /* Attribute ID */
6956 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6957 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006958 /*
6959 * And now for the children...
6960 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006961 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006962 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006963 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6964 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006965 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006966 if (topLevel) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006967 child = xmlSchemaParseAttrDecls(ctxt, schema, child,
6968 (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006969 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00006970 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt,
6971 schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006972 child = child->next;
6973 }
6974 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006975 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006976 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006977 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6978 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006979 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006980 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006981 return (ret);
6982}
6983
6984/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006985 * xmlSchemaPValAttrFormDefault:
6986 * @value: the value
6987 * @flags: the flags to be modified
6988 * @flagQualified: the specific flag for "qualified"
6989 *
6990 * Returns 0 if the value is valid, 1 otherwise.
6991 */
6992static int
6993xmlSchemaPValAttrFormDefault(const xmlChar *value,
6994 int *flags,
6995 int flagQualified)
6996{
6997 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6998 if ((*flags & flagQualified) == 0)
6999 *flags |= flagQualified;
7000 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007001 return (1);
7002
William M. Brack2f2a6632004-08-20 23:09:47 +00007003 return (0);
7004}
7005
7006/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00007007 * xmlSchemaPValAttrBlockFinal:
7008 * @value: the value
7009 * @flags: the flags to be modified
7010 * @flagAll: the specific flag for "#all"
7011 * @flagExtension: the specific flag for "extension"
7012 * @flagRestriction: the specific flag for "restriction"
7013 * @flagSubstitution: the specific flag for "substitution"
7014 * @flagList: the specific flag for "list"
7015 * @flagUnion: the specific flag for "union"
7016 *
7017 * Validates the value of the attribute "final" and "block". The value
7018 * is converted into the specified flag values and returned in @flags.
7019 *
7020 * Returns 0 if the value is valid, 1 otherwise.
7021 */
7022
7023static int
7024xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007025 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007026 int flagAll,
7027 int flagExtension,
7028 int flagRestriction,
7029 int flagSubstitution,
7030 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007031 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007032{
7033 int ret = 0;
7034
7035 /*
7036 * TODO: This does not check for dublicate entries.
7037 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007038 if ((flags == NULL) || (value == NULL))
7039 return (-1);
7040 if (value[0] == 0)
7041 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007042 if (xmlStrEqual(value, BAD_CAST "#all")) {
7043 if (flagAll != -1)
7044 *flags |= flagAll;
7045 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007046 if (flagExtension != -1)
7047 *flags |= flagExtension;
7048 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007049 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007050 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007051 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007052 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007053 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007054 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007055 *flags |= flagUnion;
7056 }
7057 } else {
7058 const xmlChar *end, *cur = value;
7059 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007060
Daniel Veillardc0826a72004-08-10 14:17:33 +00007061 do {
7062 while (IS_BLANK_CH(*cur))
7063 cur++;
7064 end = cur;
7065 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7066 end++;
7067 if (end == cur)
7068 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007069 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007070 if (xmlStrEqual(item, BAD_CAST "extension")) {
7071 if (flagExtension != -1) {
7072 if ((*flags & flagExtension) == 0)
7073 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007074 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007075 ret = 1;
7076 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7077 if (flagRestriction != -1) {
7078 if ((*flags & flagRestriction) == 0)
7079 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007080 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007081 ret = 1;
7082 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7083 if (flagSubstitution != -1) {
7084 if ((*flags & flagSubstitution) == 0)
7085 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007086 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007087 ret = 1;
7088 } else if (xmlStrEqual(item, BAD_CAST "list")) {
7089 if (flagList != -1) {
7090 if ((*flags & flagList) == 0)
7091 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007092 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007093 ret = 1;
7094 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7095 if (flagUnion != -1) {
7096 if ((*flags & flagUnion) == 0)
7097 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007098 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007099 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007100 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007101 ret = 1;
7102 if (item != NULL)
7103 xmlFree(item);
7104 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007105 } while ((ret == 0) && (*cur != 0));
7106 }
7107
Daniel Veillardc0826a72004-08-10 14:17:33 +00007108 return (ret);
7109}
7110
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007111static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007112xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007113 xmlSchemaIDCPtr idc,
7114 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007115 xmlAttrPtr attr,
7116 int isField)
7117{
7118 xmlNodePtr node;
7119
7120 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007121 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007122 * Schema Component Constraint: Selector Value OK
7123 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007124 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007125 * in [XPath].
7126 */
7127 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007128 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007129 XML_SCHEMAP_INTERNAL,
7130 "Internal error: xmlSchemaCheckCSelectorXPath, "
7131 "the selector is not specified.\n", NULL, NULL);
7132 return (-1);
7133 }
7134 if (attr == NULL)
7135 node = idc->node;
7136 else
7137 node = (xmlNodePtr) attr;
7138 if (selector->xpath == NULL) {
7139 xmlSchemaPCustomErr(ctxt,
7140 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007141 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7142 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007143 "The XPath expression of the selector is not valid", NULL);
7144 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7145 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007146 const xmlChar **nsArray = NULL;
7147 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007148 /*
7149 * Compile the XPath expression.
7150 */
7151 /*
7152 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007153 * TODO: Call xmlPatterncompile with different options for selector/
7154 * field.
7155 */
7156 nsList = xmlGetNsList(attr->doc, attr->parent);
7157 /*
7158 * Build an array of prefixes and namespaces.
7159 */
7160 if (nsList != NULL) {
7161 int i, count = 0;
7162 xmlNsPtr ns;
7163
7164 for (i = 0; nsList[i] != NULL; i++)
7165 count++;
7166
7167 nsArray = (const xmlChar **) xmlMalloc(
7168 (count * 2 + 1) * sizeof(const xmlChar *));
7169 if (nsArray == NULL) {
7170 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
7171 NULL);
7172 return (-1);
7173 }
7174 for (i = 0; i < count; i++) {
7175 ns = nsList[i];
7176 nsArray[2 * i] = nsList[i]->href;
7177 nsArray[2 * i + 1] = nsList[i]->prefix;
7178 }
7179 nsArray[count * 2] = NULL;
7180 xmlFree(nsList);
7181 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007182 /*
7183 * TODO: Differentiate between "selector" and "field".
7184 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007185 if (isField)
7186 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00007187 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007188 else
7189 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00007190 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007191 if (nsArray != NULL)
7192 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007193
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00007194 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007195 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00007196 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007197 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7198 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007199 "The XPath expression '%s' could not be "
7200 "compiled", selector->xpath);
7201 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007202 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007203 }
7204 return (0);
7205}
7206
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007207#define ADD_ANNOTATION(annot) \
7208 xmlSchemaAnnotPtr cur = item->annot; \
7209 if (item->annot == NULL) { \
7210 item->annot = annot; \
7211 return (annot); \
7212 } \
7213 cur = item->annot; \
7214 if (cur->next != NULL) { \
7215 cur = cur->next; \
7216 } \
7217 cur->next = annot;
7218
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007219/**
7220 * xmlSchemaAssignAnnotation:
7221 * @item: the schema component
7222 * @annot: the annotation
7223 *
7224 * Adds the annotation to the given schema component.
7225 *
7226 * Returns the given annotaion.
7227 */
7228static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007229xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
7230 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007231{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007232 if ((annItem == NULL) || (annot == NULL))
7233 return (NULL);
7234 switch (annItem->type) {
7235 case XML_SCHEMA_TYPE_ELEMENT: {
7236 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
7237 ADD_ANNOTATION(annot)
7238 }
7239 break;
7240 case XML_SCHEMA_TYPE_ATTRIBUTE: {
7241 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
7242 ADD_ANNOTATION(annot)
7243 }
7244 break;
7245 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
7246 case XML_SCHEMA_TYPE_ANY: {
7247 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
7248 ADD_ANNOTATION(annot)
7249 }
7250 break;
7251 case XML_SCHEMA_TYPE_PARTICLE:
7252 case XML_SCHEMA_TYPE_IDC_KEY:
7253 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007254 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007255 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
7256 ADD_ANNOTATION(annot)
7257 }
7258 break;
7259 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
7260 xmlSchemaAttributeGroupPtr item =
7261 (xmlSchemaAttributeGroupPtr) annItem;
7262 ADD_ANNOTATION(annot)
7263 }
7264 break;
7265 case XML_SCHEMA_TYPE_NOTATION: {
7266 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7267 ADD_ANNOTATION(annot)
7268 }
7269 break;
7270 case XML_SCHEMA_FACET_MININCLUSIVE:
7271 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7272 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7273 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7274 case XML_SCHEMA_FACET_TOTALDIGITS:
7275 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7276 case XML_SCHEMA_FACET_PATTERN:
7277 case XML_SCHEMA_FACET_ENUMERATION:
7278 case XML_SCHEMA_FACET_WHITESPACE:
7279 case XML_SCHEMA_FACET_LENGTH:
7280 case XML_SCHEMA_FACET_MAXLENGTH:
7281 case XML_SCHEMA_FACET_MINLENGTH: {
7282 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7283 ADD_ANNOTATION(annot)
7284 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007285 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007286 case XML_SCHEMA_TYPE_SIMPLE:
7287 case XML_SCHEMA_TYPE_COMPLEX: {
7288 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7289 ADD_ANNOTATION(annot)
7290 }
7291 break;
7292 case XML_SCHEMA_TYPE_GROUP: {
7293 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7294 ADD_ANNOTATION(annot)
7295 }
7296 break;
7297 case XML_SCHEMA_TYPE_SEQUENCE:
7298 case XML_SCHEMA_TYPE_CHOICE:
7299 case XML_SCHEMA_TYPE_ALL: {
7300 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7301 ADD_ANNOTATION(annot)
7302 }
7303 break;
7304 default:
7305 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007306 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007307 NULL, NULL, NULL,
7308 "Internal error: xmlSchemaAddAnnotation, "
7309 "The item is not a annotated schema component", NULL);
7310 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007311 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007312 return (annot);
7313}
7314
7315/**
7316 * xmlSchemaParseIDCSelectorAndField:
7317 * @ctxt: a schema validation context
7318 * @schema: the schema being built
7319 * @node: a subtree containing XML Schema informations
7320 *
7321 * Parses a XML Schema identity-contraint definition's
7322 * <selector> and <field> elements.
7323 *
7324 * Returns the parsed identity-constraint definition.
7325 */
7326static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007327xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007328 xmlSchemaPtr schema,
7329 xmlSchemaIDCPtr idc,
7330 xmlNodePtr node,
7331 int isField)
7332{
7333 xmlSchemaIDCSelectPtr item;
7334 xmlNodePtr child = NULL;
7335 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007336
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007337 /*
7338 * Check for illegal attributes.
7339 */
7340 attr = node->properties;
7341 while (attr != NULL) {
7342 if (attr->ns == NULL) {
7343 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7344 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007345 xmlSchemaPIllegalAttrErr(ctxt,
7346 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7347 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007348 }
7349 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007350 xmlSchemaPIllegalAttrErr(ctxt,
7351 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7352 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007353 }
7354 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007355 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007356 /*
7357 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007358 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007359 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7360 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007361 xmlSchemaPErrMemory(ctxt,
7362 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007363 NULL);
7364 return (NULL);
7365 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007366 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007367 /*
7368 * Attribute "xpath" (mandatory).
7369 */
7370 attr = xmlSchemaGetPropNode(node, "xpath");
7371 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007372 xmlSchemaPMissingAttrErr(ctxt,
7373 XML_SCHEMAP_S4S_ATTR_MISSING,
7374 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007375 "name", NULL);
7376 } else {
7377 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7378 /*
7379 * URGENT TODO: "field"s have an other syntax than "selector"s.
7380 */
7381
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007382 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7383 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007384 xmlSchemaPErr(ctxt,
7385 (xmlNodePtr) attr,
7386 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007387 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007388 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007389 NULL, NULL);
7390 }
7391
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007392 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007393 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007394 /*
7395 * And now for the children...
7396 */
7397 child = node->children;
7398 if (IS_SCHEMA(child, "annotation")) {
7399 /*
7400 * Add the annotation to the parent IDC.
7401 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007402 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007403 xmlSchemaParseAnnotation(ctxt, schema, child));
7404 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007405 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007406 if (child != NULL) {
7407 xmlSchemaPContentErr(ctxt,
7408 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007409 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007410 NULL, "(annotation?)");
7411 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007412
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007413 return (item);
7414}
7415
7416/**
7417 * xmlSchemaParseIDC:
7418 * @ctxt: a schema validation context
7419 * @schema: the schema being built
7420 * @node: a subtree containing XML Schema informations
7421 *
7422 * Parses a XML Schema identity-contraint definition.
7423 *
7424 * Returns the parsed identity-constraint definition.
7425 */
7426static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007427xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007428 xmlSchemaPtr schema,
7429 xmlNodePtr node,
7430 xmlSchemaTypeType idcCategory,
7431 const xmlChar *targetNamespace)
7432{
7433 xmlSchemaIDCPtr item = NULL;
7434 xmlNodePtr child = NULL;
7435 xmlAttrPtr attr;
7436 const xmlChar *name = NULL;
7437 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007438
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007439 /*
7440 * Check for illegal attributes.
7441 */
7442 attr = node->properties;
7443 while (attr != NULL) {
7444 if (attr->ns == NULL) {
7445 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7446 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7447 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7448 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007449 xmlSchemaPIllegalAttrErr(ctxt,
7450 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7451 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007452 }
7453 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007454 xmlSchemaPIllegalAttrErr(ctxt,
7455 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7456 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007457 }
7458 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007459 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007460 /*
7461 * Attribute "name" (mandatory).
7462 */
7463 attr = xmlSchemaGetPropNode(node, "name");
7464 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007465 xmlSchemaPMissingAttrErr(ctxt,
7466 XML_SCHEMAP_S4S_ATTR_MISSING,
7467 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007468 "name", NULL);
7469 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007470 } else if (xmlSchemaPValAttrNode(ctxt,
7471 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007472 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7473 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007474 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007475 /* Create the component. */
7476 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
7477 idcCategory, node);
7478 if (item == NULL)
7479 return(NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007480
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007481 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7482 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007483 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7484 /*
7485 * Attribute "refer" (mandatory).
7486 */
7487 attr = xmlSchemaGetPropNode(node, "refer");
7488 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007489 xmlSchemaPMissingAttrErr(ctxt,
7490 XML_SCHEMAP_S4S_ATTR_MISSING,
7491 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007492 "refer", NULL);
7493 } else {
7494 /*
7495 * Create a reference item.
7496 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007497 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007498 NULL, NULL);
7499 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007500 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007501 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007502 NULL, NULL, attr,
7503 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007504 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007505 xmlSchemaCheckReference(ctxt, schema, node,
7506 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007507 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007508 }
7509 }
7510 /*
7511 * And now for the children...
7512 */
7513 child = node->children;
7514 if (IS_SCHEMA(child, "annotation")) {
7515 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7516 child = child->next;
7517 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007518 if (child == NULL) {
7519 xmlSchemaPContentErr(ctxt,
7520 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007521 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007522 "A child element is missing",
7523 "(annotation?, (selector, field+))");
7524 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007525 /*
7526 * Child element <selector>.
7527 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007528 if (IS_SCHEMA(child, "selector")) {
7529 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007530 item, child, 0);
7531 child = child->next;
7532 /*
7533 * Child elements <field>.
7534 */
7535 if (IS_SCHEMA(child, "field")) {
7536 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007537 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007538 item, child, 1);
7539 if (field != NULL) {
7540 field->index = item->nbFields;
7541 item->nbFields++;
7542 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007543 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007544 else
7545 item->fields = field;
7546 lastField = field;
7547 }
7548 child = child->next;
7549 } while (IS_SCHEMA(child, "field"));
7550 } else {
7551 xmlSchemaPContentErr(ctxt,
7552 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007553 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007554 NULL, "(annotation?, (selector, field+))");
7555 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007556 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007557 if (child != NULL) {
7558 xmlSchemaPContentErr(ctxt,
7559 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007560 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007561 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007562 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007563
7564 return (item);
7565}
7566
Daniel Veillardc0826a72004-08-10 14:17:33 +00007567/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007568 * xmlSchemaParseElement:
7569 * @ctxt: a schema validation context
7570 * @schema: the schema being built
7571 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007572 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007573 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007574 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007575 * *WARNING* this interface is highly subject to change
7576 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007577 * Returns the element declaration or a particle; NULL in case
7578 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007579 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007580static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007581xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007582 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007583{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007584 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007585 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007586 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007587 xmlNodePtr child = NULL;
7588 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007589 int min, max, isRef = 0;
7590 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007591
7592 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7593 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007594
Daniel Veillard4255d502002-04-16 15:50:10 +00007595 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007596 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007597 /*
7598 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007599 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007600 * robust.
7601 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007602 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007603 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007604 if ((topLevel) || (attr == NULL)) {
7605 if (nameAttr == NULL) {
7606 xmlSchemaPMissingAttrErr(ctxt,
7607 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007608 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007609 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007610 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007611 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007612 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007613
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007614 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007615 child = node->children;
7616 if (IS_SCHEMA(child, "annotation")) {
7617 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7618 child = child->next;
7619 }
7620 /*
7621 * Skip particle part if a global declaration.
7622 */
7623 if (topLevel)
7624 goto declaration_part;
7625 /*
7626 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007627 */
7628 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7629 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7630 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007631 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7632 if (particle == NULL)
7633 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007634
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007635 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7636
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007637 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007638 const xmlChar *refNs = NULL, *ref = NULL;
7639 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007640 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007641 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007642 */
7643 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007644 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007645 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007646 /*
7647 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007648 */
7649 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007650 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007651 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007652 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007653 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007654 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007655 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007656 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007657 attr = node->properties;
7658 while (attr != NULL) {
7659 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007660 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7661 xmlStrEqual(attr->name, BAD_CAST "name") ||
7662 xmlStrEqual(attr->name, BAD_CAST "id") ||
7663 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7664 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7665 {
7666 attr = attr->next;
7667 continue;
7668 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007669 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007670 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007671 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007672 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007673 "Only the attributes 'minOccurs', 'maxOccurs' and "
7674 "'id' are allowed in addition to 'ref'");
7675 break;
7676 }
7677 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7678 xmlSchemaPIllegalAttrErr(ctxt,
7679 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007680 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007681 }
7682 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007683 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007684 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007685 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007686 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007687 if (child != NULL) {
7688 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7689 NULL, NULL, node, child, NULL, "(annotation?)");
7690 }
7691 if ((min == 0) && (max == 0))
7692 goto return_null;
7693 /*
7694 * Create the reference item.
7695 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007696 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007697 ref, refNs);
7698 if (refer == NULL)
7699 goto return_null;
7700 particle->children = (xmlSchemaTreeItemPtr) refer;
7701 particle->annot = annot;
7702 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007703 * Add the particle to pending components, since the reference
7704 * need to be resolved.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007705 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007706 WXS_ADD_PENDING_ITEM(ctxt, particle);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007707 return ((xmlSchemaBasicItemPtr) particle);
7708 }
7709 /*
7710 * The declaration part ===============================================
7711 */
7712declaration_part:
7713 {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007714 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007715 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7716
7717 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007718 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007719 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007720 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007721 * Evaluate the target namespace.
7722 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007723 if (topLevel) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007724 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007725 } else {
7726 attr = xmlSchemaGetPropNode(node, "form");
7727 if (attr != NULL) {
7728 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7729 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007730 ns = ctxt->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007731 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007732 xmlSchemaPSimpleTypeErr(ctxt,
7733 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7734 NULL, (xmlNodePtr) attr,
7735 NULL, "(qualified | unqualified)",
7736 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007737 }
7738 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00007739 ns = ctxt->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007740 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007741 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007742 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007743 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007744 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007745 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7746 decl->node = node;
7747 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007748 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007749 * Check for illegal attributes.
7750 */
William M. Bracke7091952004-05-11 15:09:58 +00007751 attr = node->properties;
7752 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007753 if (attr->ns == NULL) {
7754 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7755 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007756 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007757 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007758 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007759 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007760 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7761 {
7762 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007763 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007764 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007765 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007766 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007767 xmlSchemaPIllegalAttrErr(ctxt,
7768 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7769 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007770 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007771 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7772 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007773 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7774
7775 xmlSchemaPIllegalAttrErr(ctxt,
7776 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007777 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007778 }
7779 }
7780 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007781
Daniel Veillardc0826a72004-08-10 14:17:33 +00007782 xmlSchemaPIllegalAttrErr(ctxt,
7783 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007784 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007785 }
7786 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007787 }
William M. Bracke7091952004-05-11 15:09:58 +00007788 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007789 * Extract/validate attributes.
7790 */
7791 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007792 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007793 * Process top attributes of global element declarations here.
7794 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007795 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7796 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007797 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7798 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7799 &(decl->substGroupNs), &(decl->substGroup));
7800 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007801 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007802 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007803 /*
7804 * Attribute "final".
7805 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007806 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007807 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007808 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7809 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7810 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7811 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007812 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007813 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7814 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007815 -1,
7816 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7817 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007818 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007819 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007820 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7821 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007822 attrValue, NULL, NULL, NULL);
7823 }
7824 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007825 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007826 /*
7827 * Attribute "block".
7828 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007829 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007830 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007831 /*
7832 * Apply default "block" values.
7833 */
7834 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7835 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7836 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7837 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7838 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7839 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007840 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007841 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7842 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007843 -1,
7844 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007845 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007846 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7847 xmlSchemaPSimpleTypeErr(ctxt,
7848 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007849 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007850 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007851 "restriction | substitution))", attrValue,
7852 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007853 }
7854 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007855 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007856 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007857 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007858
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007859 attr = xmlSchemaGetPropNode(node, "type");
7860 if (attr != NULL) {
7861 xmlSchemaPValAttrNodeQName(ctxt, schema,
7862 NULL, (xmlSchemaTypePtr) decl, attr,
7863 &(decl->namedTypeNs), &(decl->namedType));
7864 xmlSchemaCheckReference(ctxt, schema, node,
7865 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7866 }
7867 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7868 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007869 if (attr != NULL) {
7870 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007871 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007872 /*
7873 * 3.3.3 : 1
7874 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007875 */
7876 xmlSchemaPMutualExclAttrErr(ctxt,
7877 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007878 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007879 "default", "fixed");
7880 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007881 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7882 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007883 }
William M. Bracke7091952004-05-11 15:09:58 +00007884 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007885 /*
7886 * And now for the children...
7887 */
William M. Bracke7091952004-05-11 15:09:58 +00007888 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007889 /*
7890 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007891 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007892 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007893 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007894 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007895 xmlSchemaPContentErr(ctxt,
7896 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007897 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007898 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007899 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007900 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007901 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007902 child = child->next;
7903 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007904 /*
7905 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007906 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007907 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007908 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007909 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007910 xmlSchemaPContentErr(ctxt,
7911 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007912 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007913 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007914 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007915 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007916 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007917 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007918 }
William M. Bracke7091952004-05-11 15:09:58 +00007919 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007920 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007921 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007922 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007923 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007924 } else if (IS_SCHEMA(child, "key")) {
7925 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007926 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007927 } else if (IS_SCHEMA(child, "keyref")) {
7928 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007929 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007930 }
7931 if (lastIDC != NULL)
7932 lastIDC->next = curIDC;
7933 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007934 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007935 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007936 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007937 }
7938 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007939 xmlSchemaPContentErr(ctxt,
7940 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007941 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007942 NULL, "(annotation?, ((simpleType | complexType)?, "
7943 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007944 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007945 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007946 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007947 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007948 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007949 * different layer.
7950 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007951 FREE_AND_NULL(des)
7952 if (topLevel)
7953 return ((xmlSchemaBasicItemPtr) decl);
7954 else {
7955 particle->children = (xmlSchemaTreeItemPtr) decl;
7956 return ((xmlSchemaBasicItemPtr) particle);
7957 }
7958
7959return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007960 FREE_AND_NULL(des);
7961 if (annot != NULL) {
7962 if (particle != NULL)
7963 particle->annot = NULL;
7964 if (decl != NULL)
7965 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007966 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007967 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007968 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007969}
7970
7971/**
7972 * xmlSchemaParseUnion:
7973 * @ctxt: a schema validation context
7974 * @schema: the schema being built
7975 * @node: a subtree containing XML Schema informations
7976 *
7977 * parse a XML schema Union definition
7978 * *WARNING* this interface is highly subject to change
7979 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007980 * Returns -1 in case of internal error, 0 in case of success and a positive
7981 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007982 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007983static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007984xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007985 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007986{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007987 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007988 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007989 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007990 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007991
7992 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007993 return (-1);
7994 /* Not a component, don't create it. */
7995 type = ctxt->ctxtType;
7996 /*
7997 * Mark the simple type as being of variety "union".
7998 */
7999 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008000 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008001 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8002 * then the ·simple ur-type definition·."
8003 */
8004 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008005 /*
8006 * Check for illegal attributes.
8007 */
8008 attr = node->properties;
8009 while (attr != NULL) {
8010 if (attr->ns == NULL) {
8011 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8012 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008013 xmlSchemaPIllegalAttrErr(ctxt,
8014 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8015 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008016 }
8017 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008018 xmlSchemaPIllegalAttrErr(ctxt,
8019 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8020 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008021 }
8022 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008023 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008024 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008025 /*
8026 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008027 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00008028 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008029 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008030 if (attr != NULL) {
8031 const xmlChar *end;
8032 xmlChar *tmp;
8033 const xmlChar *localName, *nsName;
8034 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8035 xmlSchemaQNameRefPtr ref;
8036
8037 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008038 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008039 do {
8040 while (IS_BLANK_CH(*cur))
8041 cur++;
8042 end = cur;
8043 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8044 end++;
8045 if (end == cur)
8046 break;
8047 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008048 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
8049 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008050 /*
8051 * Create the member type link.
8052 */
8053 link = (xmlSchemaTypeLinkPtr)
8054 xmlMalloc(sizeof(xmlSchemaTypeLink));
8055 if (link == NULL) {
8056 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8057 "allocating a type link", NULL);
8058 return (-1);
8059 }
8060 link->type = NULL;
8061 link->next = NULL;
8062 if (lastLink == NULL)
8063 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008064 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008065 lastLink->next = link;
8066 lastLink = link;
8067 /*
8068 * Create a reference item.
8069 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008070 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008071 localName, nsName);
8072 if (ref == NULL) {
8073 FREE_AND_NULL(tmp)
8074 return (-1);
8075 }
8076 /*
8077 * Assign the reference to the link, it will be resolved
8078 * later during fixup of the union simple type.
8079 */
8080 link->type = (xmlSchemaTypePtr) ref;
8081 }
8082 FREE_AND_NULL(tmp)
8083 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008084 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008085
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008086 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008087 /*
8088 * And now for the children...
8089 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008090 child = node->children;
8091 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008092 /*
8093 * Add the annotation to the simple type ancestor.
8094 */
8095 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8096 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008097 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008098 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008099 if (IS_SCHEMA(child, "simpleType")) {
8100 xmlSchemaTypePtr subtype, last = NULL;
8101
8102 /*
8103 * Anchor the member types in the "subtypes" field of the
8104 * simple type.
8105 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008106 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008107 subtype = (xmlSchemaTypePtr)
8108 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8109 if (subtype != NULL) {
8110 if (last == NULL) {
8111 type->subtypes = subtype;
8112 last = subtype;
8113 } else {
8114 last->next = subtype;
8115 last = subtype;
8116 }
8117 last->next = NULL;
8118 }
8119 child = child->next;
8120 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008121 }
8122 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008123 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008124 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008125 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008126 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008127 if ((attr == NULL) && (type->subtypes == NULL)) {
8128 /*
8129 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008130 * Either the memberTypes [attribute] of the <union> element must
8131 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008132 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008133 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008134 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
8135 NULL, NULL, node,
8136 "Either the attribute 'memberTypes' or "
8137 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008138 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008139 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00008140}
8141
8142/**
8143 * xmlSchemaParseList:
8144 * @ctxt: a schema validation context
8145 * @schema: the schema being built
8146 * @node: a subtree containing XML Schema informations
8147 *
8148 * parse a XML schema List definition
8149 * *WARNING* this interface is highly subject to change
8150 *
William M. Bracke7091952004-05-11 15:09:58 +00008151 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008152 * 1 in case of success.
8153 */
8154static xmlSchemaTypePtr
8155xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008156 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008157{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008158 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008159 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008160 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008161
8162 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8163 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008164 /* Not a component, don't create it. */
8165 type = ctxt->ctxtType;
8166 /*
8167 * Mark the type as being of variety "list".
8168 */
8169 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008170 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008171 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8172 * then the ·simple ur-type definition·."
8173 */
8174 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008175 /*
8176 * Check for illegal attributes.
8177 */
8178 attr = node->properties;
8179 while (attr != NULL) {
8180 if (attr->ns == NULL) {
8181 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8182 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008183 xmlSchemaPIllegalAttrErr(ctxt,
8184 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8185 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008186 }
8187 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008188 xmlSchemaPIllegalAttrErr(ctxt,
8189 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8190 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008191 }
8192 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008193 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008194
8195 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8196
William M. Brack2f2a6632004-08-20 23:09:47 +00008197 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008198 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
8199 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00008200 */
8201 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008202 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00008203 /*
8204 * And now for the children...
8205 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008206 child = node->children;
8207 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008208 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8209 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008210 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008211 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008212 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008213 /*
8214 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008215 * Either the itemType [attribute] or the <simpleType> [child] of
8216 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008217 */
8218 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008219 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008220 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008221 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00008222 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008223 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008224 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008225 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008226 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008227 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008228 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008229 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008230 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008231 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008232 "Either the attribute 'itemType' or the <simpleType> child "
8233 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008234 }
8235 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008236 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008237 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008238 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008239 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008240 if ((type->ref == NULL) &&
8241 (type->subtypes == NULL) &&
8242 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008243 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008244 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008245 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008246 "Either the attribute 'itemType' or the <simpleType> child "
8247 "must be present", NULL);
8248 }
8249 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008250}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008251
Daniel Veillard4255d502002-04-16 15:50:10 +00008252/**
8253 * xmlSchemaParseSimpleType:
8254 * @ctxt: a schema validation context
8255 * @schema: the schema being built
8256 * @node: a subtree containing XML Schema informations
8257 *
8258 * parse a XML schema Simple Type definition
8259 * *WARNING* this interface is highly subject to change
8260 *
William M. Bracke7091952004-05-11 15:09:58 +00008261 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008262 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008263 */
8264static xmlSchemaTypePtr
8265xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008266 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008267{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008268 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008269 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008270 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008271 xmlAttrPtr attr;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008272 int hasRestriction = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008273
8274 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8275 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008276
Daniel Veillardc0826a72004-08-10 14:17:33 +00008277 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008278 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008279 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008280 xmlSchemaPMissingAttrErr(ctxt,
8281 XML_SCHEMAP_S4S_ATTR_MISSING,
8282 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008283 "name", NULL);
8284 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008285 } else {
8286 if (xmlSchemaPValAttrNode(ctxt,
8287 NULL, NULL, attr,
8288 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
8289 return (NULL);
8290 /*
8291 * Skip built-in types.
8292 */
8293 if (ctxt->isS4S) {
8294 xmlSchemaTypePtr biType;
8295
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008296 if (ctxt->isRedefine) {
8297 /*
8298 * REDEFINE: Disallow redefinition of built-in-types.
8299 * TODO: It seems that the spec does not say anything
8300 * about this case.
8301 */
8302 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
8303 NULL, NULL, node,
8304 "Redefinition of built-in simple types is not "
8305 "supported", NULL);
8306 return(NULL);
8307 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008308 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
8309 if (biType != NULL)
8310 return (biType);
8311 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008312 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008313 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008314 /*
8315 * TargetNamespace:
8316 * SPEC "The ·actual value· of the targetNamespace [attribute]
8317 * of the <schema> ancestor element information item if present,
8318 * otherwise ·absent·.
8319 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008320 if (topLevel == 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008321#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008322 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008323#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +00008324 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008325 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008326 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008327#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008328 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008329 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf,
8330 ctxt->targetNamespace, node, 0);
8331#else
8332 type = xmlSchemaAddType(ctxt, schema, NULL,
8333 ctxt->targetNamespace, node, 0);
8334#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +00008335 if (type == NULL)
8336 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008337 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008338 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008339 /*
8340 * Check for illegal attributes.
8341 */
8342 attr = node->properties;
8343 while (attr != NULL) {
8344 if (attr->ns == NULL) {
8345 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008346 xmlSchemaPIllegalAttrErr(ctxt,
8347 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8348 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008349 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008350 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008351 xmlSchemaPIllegalAttrErr(ctxt,
8352 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8353 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008354 }
8355 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008356 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008357 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008358 /*
8359 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008360 *
8361 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008362 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008363 type = xmlSchemaAddType(ctxt, schema, attrValue,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008364 ctxt->targetNamespace, node, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008365 if (type == NULL)
8366 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008367 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008368 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008369 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8370 /*
8371 * Check for illegal attributes.
8372 */
8373 attr = node->properties;
8374 while (attr != NULL) {
8375 if (attr->ns == NULL) {
8376 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8377 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008378 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008379 xmlSchemaPIllegalAttrErr(ctxt,
8380 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8381 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008382 }
8383 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008384 xmlSchemaPIllegalAttrErr(ctxt,
8385 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8386 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008387 }
8388 attr = attr->next;
8389 }
8390 /*
8391 * Attribute "final".
8392 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008393 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008394 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008395 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8396 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8397 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8398 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8399 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8400 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008401 } else {
8402 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008403 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8404 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008405 XML_SCHEMAS_TYPE_FINAL_LIST,
8406 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8407
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008408 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008409 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008410 type, (xmlNodePtr) attr,
8411 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008412 attrValue, NULL, NULL, NULL);
8413 }
8414 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008415 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008416 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008417 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008418 /*
8419 * And now for the children...
8420 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008421 oldCtxtType = ctxt->ctxtType;
8422 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008423 ctxt->ctxtType = type;
8424 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008425 child = node->children;
8426 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008427 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8428 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008429 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008430 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008431 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8432 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008433 "(annotation?, (restriction | list | union))");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008434 } else if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008435 xmlSchemaParseRestriction(ctxt, schema, child,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008436 XML_SCHEMA_TYPE_SIMPLE);
8437 hasRestriction = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008438 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008439 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008440 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008441 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008442 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008443 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008444 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008445 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008446 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008447 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8448 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008449 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008450 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008451 /*
8452 * REDEFINE: SPEC src-redefine (5)
8453 * "Within the [children], each <simpleType> must have a
8454 * <restriction> among its [children] ... the ·actual value· of whose
8455 * base [attribute] must be the same as the ·actual value· of its own
8456 * name attribute plus target namespace;"
8457 */
8458 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
8459 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
8460 NULL, NULL, node, "This is a redefinition, thus the "
8461 "<simpleType> must have a <restriction> child", NULL);
8462 }
8463
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008464 ctxt->parentItem = oldParentItem;
8465 ctxt->ctxtType = oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008466 return (type);
8467}
8468
Daniel Veillard4255d502002-04-16 15:50:10 +00008469/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008470 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008471 * @ctxt: a schema validation context
8472 * @schema: the schema being built
8473 * @node: a subtree containing XML Schema informations
8474 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008475 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008476 * *WARNING* this interface is highly subject to change
8477 *
William M. Bracke7091952004-05-11 15:09:58 +00008478 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008479 * 1 in case of success.
8480 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008481static xmlSchemaTreeItemPtr
8482xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8483 xmlSchemaPtr schema,
8484 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008485{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008486 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008487 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008488 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008489 const xmlChar *ref = NULL, *refNs = NULL;
8490 int min, max;
8491
8492 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008493 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008494
8495 attr = xmlSchemaGetPropNode(node, "ref");
8496 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008497 xmlSchemaPMissingAttrErr(ctxt,
8498 XML_SCHEMAP_S4S_ATTR_MISSING,
8499 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008500 "ref", NULL);
8501 return (NULL);
8502 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008503 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008504 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008505 }
8506 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008507 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008508 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008509 /*
8510 * Check for illegal attributes.
8511 */
8512 attr = node->properties;
8513 while (attr != NULL) {
8514 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008515 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008516 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8517 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8518 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008519 xmlSchemaPIllegalAttrErr(ctxt,
8520 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8521 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008522 }
8523 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008524 xmlSchemaPIllegalAttrErr(ctxt,
8525 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8526 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008527 }
8528 attr = attr->next;
8529 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008530 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008531 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8532 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008533 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008534 /* Add to pending components; the reference needs to be resolved. */
8535 WXS_ADD_PENDING_ITEM(ctxt, item);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008536 /*
8537 * Create a reference item as the term; it will be substituted for
8538 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008539 */
8540 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008541 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008542 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8543 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8544 /*
8545 * And now for the children...
8546 */
8547 child = node->children;
8548 /* TODO: Is annotation even allowed for a model group reference? */
8549 if (IS_SCHEMA(child, "annotation")) {
8550 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008551 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008552 */
8553 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8554 child = child->next;
8555 }
8556 if (child != NULL) {
8557 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008558 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008559 NULL, NULL, node, child, NULL,
8560 "(annotation?)");
8561 }
8562 /*
8563 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8564 */
8565 if ((min == 0) && (max == 0))
8566 return (NULL);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008567
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008568 return ((xmlSchemaTreeItemPtr) item);
8569}
8570
8571/**
8572 * xmlSchemaParseModelGroupDefinition:
8573 * @ctxt: a schema validation context
8574 * @schema: the schema being built
8575 * @node: a subtree containing XML Schema informations
8576 *
8577 * Parses a XML schema model group definition.
8578 * *WARNING* this interface is highly subject to change
8579 *
8580 * Returns -1 in case of error, 0 if the declaration is improper and
8581 * 1 in case of success.
8582 */
8583static xmlSchemaModelGroupDefPtr
8584xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8585 xmlSchemaPtr schema,
8586 xmlNodePtr node)
8587{
8588 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008589 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008590 xmlAttrPtr attr;
8591 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008592
8593 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008594 return (NULL);
8595
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008596 attr = xmlSchemaGetPropNode(node, "name");
8597 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008598 xmlSchemaPMissingAttrErr(ctxt,
8599 XML_SCHEMAP_S4S_ATTR_MISSING,
8600 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008601 "name", NULL);
8602 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008603 } else if (xmlSchemaPValAttrNode(ctxt,
8604 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008605 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8606 return (NULL);
8607 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008608 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
8609 ctxt->targetNamespace, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008610 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008611 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008612 /*
8613 * Check for illegal attributes.
8614 */
8615 attr = node->properties;
8616 while (attr != NULL) {
8617 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008618 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008619 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008620 xmlSchemaPIllegalAttrErr(ctxt,
8621 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8622 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008623 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008624 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008625 xmlSchemaPIllegalAttrErr(ctxt,
8626 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8627 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008628 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008629 attr = attr->next;
8630 }
8631 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8632 /*
8633 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008634 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008635 child = node->children;
8636 if (IS_SCHEMA(child, "annotation")) {
8637 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8638 child = child->next;
8639 }
8640 if (IS_SCHEMA(child, "all")) {
8641 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8642 XML_SCHEMA_TYPE_ALL, 0);
8643 child = child->next;
8644 } else if (IS_SCHEMA(child, "choice")) {
8645 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8646 XML_SCHEMA_TYPE_CHOICE, 0);
8647 child = child->next;
8648 } else if (IS_SCHEMA(child, "sequence")) {
8649 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8650 XML_SCHEMA_TYPE_SEQUENCE, 0);
8651 child = child->next;
8652 }
8653 if (child != NULL) {
8654 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008655 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8656 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008657 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008658 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008659
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008660 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008661}
8662
8663/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008664 * xmlSchemaCleanupDoc:
8665 * @ctxt: a schema validation context
8666 * @node: the root of the document.
8667 *
8668 * removes unwanted nodes in a schemas document tree
8669 */
8670static void
8671xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8672{
8673 xmlNodePtr delete, cur;
8674
8675 if ((ctxt == NULL) || (root == NULL)) return;
8676
8677 /*
8678 * Remove all the blank text nodes
8679 */
8680 delete = NULL;
8681 cur = root;
8682 while (cur != NULL) {
8683 if (delete != NULL) {
8684 xmlUnlinkNode(delete);
8685 xmlFreeNode(delete);
8686 delete = NULL;
8687 }
8688 if (cur->type == XML_TEXT_NODE) {
8689 if (IS_BLANK_NODE(cur)) {
8690 if (xmlNodeGetSpacePreserve(cur) != 1) {
8691 delete = cur;
8692 }
8693 }
8694 } else if ((cur->type != XML_ELEMENT_NODE) &&
8695 (cur->type != XML_CDATA_SECTION_NODE)) {
8696 delete = cur;
8697 goto skip_children;
8698 }
8699
8700 /*
8701 * Skip to next node
8702 */
8703 if (cur->children != NULL) {
8704 if ((cur->children->type != XML_ENTITY_DECL) &&
8705 (cur->children->type != XML_ENTITY_REF_NODE) &&
8706 (cur->children->type != XML_ENTITY_NODE)) {
8707 cur = cur->children;
8708 continue;
8709 }
8710 }
8711 skip_children:
8712 if (cur->next != NULL) {
8713 cur = cur->next;
8714 continue;
8715 }
8716
8717 do {
8718 cur = cur->parent;
8719 if (cur == NULL)
8720 break;
8721 if (cur == root) {
8722 cur = NULL;
8723 break;
8724 }
8725 if (cur->next != NULL) {
8726 cur = cur->next;
8727 break;
8728 }
8729 } while (cur != NULL);
8730 }
8731 if (delete != NULL) {
8732 xmlUnlinkNode(delete);
8733 xmlFreeNode(delete);
8734 delete = NULL;
8735 }
8736}
8737
William M. Brack2f2a6632004-08-20 23:09:47 +00008738
William M. Brack2f2a6632004-08-20 23:09:47 +00008739static void
8740xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8741{
8742 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8743 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8744
8745 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8746 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8747
8748 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8749 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8750 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8751 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8752 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8753 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8754 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8755 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8756
8757 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8758 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8759 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8760 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8761 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8762 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8763}
8764
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008765static int
8766xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008767 xmlSchemaPtr schema,
8768 xmlNodePtr node)
8769{
8770 xmlAttrPtr attr;
8771 const xmlChar *val;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008772 int res = 0, oldErrs = ctxt->nberrors;
William M. Brack2f2a6632004-08-20 23:09:47 +00008773
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008774 /*
8775 * Those flags should be moved to the parser context flags,
8776 * since they are not visible at the component level. I.e.
8777 * they are used if processing schema *documents* only.
8778 */
8779 res = xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8780 HFAILURE;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008781
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008782 /*
8783 * Since the version is of type xs:token, we won't bother to
8784 * check it.
8785 */
8786 /* REMOVED:
8787 attr = xmlSchemaGetPropNode(node, "version");
8788 if (attr != NULL) {
8789 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8790 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
8791 HFAILURE;
8792 }
8793 */
8794 attr = xmlSchemaGetPropNode(node, "targetNamespace");
8795 if (attr != NULL) {
8796 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8797 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
8798 HFAILURE;
8799 if (res != 0) {
8800 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
8801 goto exit;
8802 }
8803 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008804 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008805 if (attr != NULL) {
8806 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008807 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
8808 XML_SCHEMAS_QUALIF_ELEM);
8809 HFAILURE;
8810 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008811 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008812 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008813 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008814 "(qualified | unqualified)", val, NULL, NULL, NULL);
8815 }
8816 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008817 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008818 if (attr != NULL) {
8819 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008820 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
8821 XML_SCHEMAS_QUALIF_ATTR);
8822 HFAILURE;
8823 if (res != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008824 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008825 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008826 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008827 "(qualified | unqualified)", val, NULL, NULL, NULL);
8828 }
8829 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008830 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008831 if (attr != NULL) {
8832 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008833 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00008834 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8835 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8836 -1,
8837 XML_SCHEMAS_FINAL_DEFAULT_LIST,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008838 XML_SCHEMAS_FINAL_DEFAULT_UNION);
8839 HFAILURE;
8840 if (res != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008841 xmlSchemaPSimpleTypeErr(ctxt,
8842 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008843 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008844 "(#all | List of (extension | restriction | list | union))",
8845 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008846 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008847 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008848 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008849 if (attr != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008850 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8851 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
William M. Brack2f2a6632004-08-20 23:09:47 +00008852 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8853 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008854 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
8855 HFAILURE;
8856 if (res != 0) {
8857 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008858 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008859 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008860 "(#all | List of (extension | restriction | substitution))",
8861 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008862 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008863 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008864
8865exit:
8866 if (oldErrs != ctxt->nberrors)
8867 res = ctxt->err;
8868 return(res);
8869exit_failure:
8870 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008871}
8872
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008873/**
8874 * xmlSchemaParseSchemaTopLevel:
8875 * @ctxt: a schema validation context
8876 * @schema: the schemas
8877 * @nodes: the list of top level nodes
8878 *
8879 * Returns the internal XML Schema structure built from the resource or
8880 * NULL in case of error
8881 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008882static int
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008883xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8884 xmlSchemaPtr schema, xmlNodePtr nodes)
8885{
8886 xmlNodePtr child;
8887 xmlSchemaAnnotPtr annot;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008888 int res = 0, oldErrs, tmpOldErrs;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008889
8890 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008891 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008892
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008893 oldErrs = ctxt->nberrors;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008894 child = nodes;
8895 while ((IS_SCHEMA(child, "include")) ||
8896 (IS_SCHEMA(child, "import")) ||
8897 (IS_SCHEMA(child, "redefine")) ||
8898 (IS_SCHEMA(child, "annotation"))) {
8899 if (IS_SCHEMA(child, "annotation")) {
8900 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8901 if (schema->annot == NULL)
8902 schema->annot = annot;
8903 else
8904 xmlSchemaFreeAnnot(annot);
8905 } else if (IS_SCHEMA(child, "import")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008906 tmpOldErrs = ctxt->nberrors;
8907 res = xmlSchemaParseImport(ctxt, schema, child);
8908 HFAILURE;
8909 HSTOP(ctxt);
8910 if (tmpOldErrs != ctxt->nberrors)
8911 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008912 } else if (IS_SCHEMA(child, "include")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008913 tmpOldErrs = ctxt->nberrors;
8914 res = xmlSchemaParseInclude(ctxt, schema, child);
8915 HFAILURE;
8916 HSTOP(ctxt);
8917 if (tmpOldErrs != ctxt->nberrors)
8918 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008919 } else if (IS_SCHEMA(child, "redefine")) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008920 tmpOldErrs = ctxt->nberrors;
8921 res = xmlSchemaParseRedefine(ctxt, schema, child);
8922 HFAILURE;
8923 HSTOP(ctxt);
8924 if (tmpOldErrs != ctxt->nberrors)
8925 goto exit;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008926 }
8927 child = child->next;
8928 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008929 /*
8930 * URGENT TODO: Change the functions to return int results.
8931 * We need especially to catch internal errors.
8932 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008933 while (child != NULL) {
8934 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008935 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008936 child = child->next;
8937 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008938 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008939 child = child->next;
8940 } else if (IS_SCHEMA(child, "element")) {
8941 xmlSchemaParseElement(ctxt, schema, child, 1);
8942 child = child->next;
8943 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008944 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008945 child = child->next;
8946 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008947 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008948 child = child->next;
8949 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008950 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008951 child = child->next;
8952 } else if (IS_SCHEMA(child, "notation")) {
8953 xmlSchemaParseNotation(ctxt, schema, child);
8954 child = child->next;
8955 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008956 xmlSchemaPContentErr(ctxt,
8957 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8958 NULL, NULL, child->parent, child,
8959 NULL, "((include | import | redefine | annotation)*, "
8960 "(((simpleType | complexType | group | attributeGroup) "
8961 "| element | attribute | notation), annotation*)*)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008962 child = child->next;
8963 }
8964 while (IS_SCHEMA(child, "annotation")) {
8965 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8966 if (schema->annot == NULL)
8967 schema->annot = annot;
8968 else
8969 xmlSchemaFreeAnnot(annot);
8970 child = child->next;
8971 }
8972 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008973exit:
Daniel Veillard01fa6152004-06-29 17:04:39 +00008974 ctxt->parentItem = NULL;
8975 ctxt->ctxtType = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008976 if (oldErrs != ctxt->nberrors)
8977 res = ctxt->err;
8978 return(res);
8979exit_failure:
8980 return(-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008981}
8982
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008983static xmlSchemaSchemaRelationPtr
8984xmlSchemaSchemaRelationCreate(void)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008985{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008986 xmlSchemaSchemaRelationPtr ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008987
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008988 ret = (xmlSchemaSchemaRelationPtr)
8989 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008990 if (ret == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008991 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008992 return(NULL);
8993 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008994 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008995 return(ret);
8996}
8997
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00008998#if 0
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008999static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009000xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009001{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009002 xmlFree(rel);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009003}
9004#endif
9005
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009006static void
9007xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9008{
9009 /*
9010 * After the construction context has been freed, there will be
9011 * no schema graph available any more. Only the schema buckets
9012 * will stay alive, which are put into the "schemasImports" and
9013 * "includes" slots of the xmlSchema.
9014 */
9015 if (con->buckets != NULL)
9016 xmlSchemaItemListFree(con->buckets);
9017 if (con->pending != NULL)
9018 xmlSchemaItemListFree(con->pending);
9019 if (con->substGroups != NULL)
9020 xmlHashFree(con->substGroups,
9021 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
9022 if (con->dict != NULL)
9023 xmlDictFree(con->dict);
9024 xmlFree(con);
9025}
9026
9027static xmlSchemaConstructionCtxtPtr
9028xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9029{
9030 xmlSchemaConstructionCtxtPtr ret;
9031
9032 ret = (xmlSchemaConstructionCtxtPtr)
9033 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9034 if (ret == NULL) {
9035 xmlSchemaPErrMemory(NULL,
9036 "allocating schema construction context", NULL);
9037 return (NULL);
9038 }
9039 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9040
9041 ret->buckets = xmlSchemaItemListCreate();
9042 if (ret->buckets == NULL) {
9043 xmlSchemaPErrMemory(NULL,
9044 "allocating list of schema buckets", NULL);
9045 xmlFree(ret);
9046 return (NULL);
9047 }
9048 ret->pending = xmlSchemaItemListCreate();
9049 if (ret->pending == NULL) {
9050 xmlSchemaPErrMemory(NULL,
9051 "allocating list of pending global components", NULL);
9052 xmlSchemaConstructionCtxtFree(ret);
9053 return (NULL);
9054 }
9055 ret->dict = dict;
9056 xmlDictReference(dict);
9057 return(ret);
9058}
9059
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009060static xmlSchemaParserCtxtPtr
9061xmlSchemaParserCtxtCreate(void)
9062{
9063 xmlSchemaParserCtxtPtr ret;
9064
9065 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9066 if (ret == NULL) {
9067 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9068 NULL);
9069 return (NULL);
9070 }
9071 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9072 ret->type = XML_SCHEMA_CTXT_PARSER;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009073 return(ret);
9074}
9075
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009076/**
9077 * xmlSchemaNewParserCtxtUseDict:
9078 * @URL: the location of the schema
9079 * @dict: the dictionary to be used
9080 *
9081 * Create an XML Schemas parse context for that file/resource expected
9082 * to contain an XML Schemas file.
9083 *
9084 * Returns the parser context or NULL in case of error
9085 */
9086static xmlSchemaParserCtxtPtr
9087xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9088{
9089 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009090
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009091 ret = xmlSchemaParserCtxtCreate();
9092 if (ret == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009093 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009094 ret->dict = dict;
9095 xmlDictReference(dict);
9096 if (URL != NULL)
9097 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009098 return (ret);
9099}
9100
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009101static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009102xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9103{
9104 if (vctxt->pctxt == NULL) {
9105 if (vctxt->schema != NULL)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009106 vctxt->pctxt =
9107 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009108 else
9109 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9110 if (vctxt->pctxt == NULL) {
9111 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9112 "failed to create a temp. parser context");
9113 return (-1);
9114 }
9115 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009116 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
9117 vctxt->warning, vctxt->userData);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009118 }
9119 return (0);
9120}
9121
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009122/**
9123 * xmlSchemaGetSchemaBucket:
9124 * @pctxt: the schema parser context
9125 * @schemaLocation: the URI of the schema document
9126 *
9127 * Returns a schema bucket if it was already parsed.
9128 *
9129 * Returns a schema bucket if it was already parsed from
9130 * @schemaLocation, NULL otherwise.
9131 */
9132static xmlSchemaBucketPtr
9133xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9134 const xmlChar *schemaLocation)
9135{
9136 xmlSchemaBucketPtr cur;
9137 xmlSchemaItemListPtr list;
9138
9139 list = pctxt->constructor->buckets;
9140 if (list->nbItems == 0)
9141 return(NULL);
9142 else {
9143 int i;
9144 for (i = 0; i < list->nbItems; i++) {
9145 cur = (xmlSchemaBucketPtr) list->items[i];
9146 /* Pointer comparison! */
9147 if (cur->schemaLocation == schemaLocation)
9148 return(cur);
9149 }
9150 }
9151 return(NULL);
9152}
9153
9154static xmlSchemaBucketPtr
9155xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9156 const xmlChar *schemaLocation,
9157 const xmlChar *targetNamespace)
9158{
9159 xmlSchemaBucketPtr cur;
9160 xmlSchemaItemListPtr list;
9161
9162 list = pctxt->constructor->buckets;
9163 if (list->nbItems == 0)
9164 return(NULL);
9165 else {
9166 int i;
9167 for (i = 0; i < list->nbItems; i++) {
9168 cur = (xmlSchemaBucketPtr) list->items[i];
9169 /* Pointer comparison! */
9170 if ((cur->origTargetNamespace == NULL) &&
9171 (cur->schemaLocation == schemaLocation) &&
9172 (cur->targetNamespace == targetNamespace))
9173 return(cur);
9174 }
9175 }
9176 return(NULL);
9177}
9178
9179
9180#define IS_BAD_SCHEMA_DOC(b) \
9181 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
9182
9183static xmlSchemaBucketPtr
9184xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
9185 const xmlChar *targetNamespace,
9186 int imported)
9187{
9188 xmlSchemaBucketPtr cur;
9189 xmlSchemaItemListPtr list;
9190
9191 list = pctxt->constructor->buckets;
9192 if (list->nbItems == 0)
9193 return(NULL);
9194 else {
9195 int i;
9196 for (i = 0; i < list->nbItems; i++) {
9197 cur = (xmlSchemaBucketPtr) list->items[i];
9198 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
9199 (cur->origTargetNamespace == targetNamespace) &&
9200 ((imported && cur->imported) ||
9201 ((!imported) && (!cur->imported))))
9202 return(cur);
9203 }
9204 }
9205 return(NULL);
9206}
9207
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009208static int
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009209xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
9210 xmlSchemaPtr schema,
9211 xmlSchemaBucketPtr bucket)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009212{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009213 int oldFlags;
9214 xmlDocPtr oldDoc;
9215 xmlNodePtr node;
9216 int ret, oldErrs;
9217 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
9218
9219 /*
9220 * Save old values; reset the *main* schema.
9221 * URGENT TODO: This is not good; move the per-document information
9222 * to the parser.
9223 */
9224 oldFlags = schema->flags;
9225 oldDoc = schema->doc;
9226 if (schema->flags != 0)
9227 xmlSchemaClearSchemaDefaults(schema);
9228 schema->doc = bucket->doc;
9229 /* !! REMOVED: schema->targetNamespace = bucket->targetNamespace; */
9230 pctxt->schema = schema;
9231 /*
9232 * Keep the current target namespace on the parser *not* on the
9233 * main schema.
9234 */
9235 pctxt->targetNamespace = bucket->targetNamespace;
9236 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009237
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009238 if ((bucket->targetNamespace != NULL) &&
9239 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009240 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009241 * We are parsing the schema for schemas!
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009242 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009243 pctxt->isS4S = 1;
9244 }
9245 /* Mark it as parsed, even if parsing fails. */
9246 bucket->parsed++;
9247 /* Compile the schema doc. */
9248 node = xmlDocGetRootElement(bucket->doc);
9249 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
9250 if (ret != 0)
9251 goto exit;
9252 /* An empty schema; just get out. */
9253 if (node->children == NULL)
9254 goto exit;
9255 oldErrs = pctxt->nberrors;
9256 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9257 if (ret != 0)
9258 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009259 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009260 * TODO: Not nice, but I'm not 100% sure we will get always an error
9261 * as a result of the obove functions; so better rely on pctxt->err
9262 * as well.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009263 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009264 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
9265 ret = pctxt->err;
9266 goto exit;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009267 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009268
9269exit:
9270 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
9271 /* Restore schema values. */
9272 schema->doc = oldDoc;
9273 schema->flags = oldFlags;
9274 return(ret);
9275}
9276
9277static int
9278xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
9279 xmlSchemaPtr schema,
9280 xmlSchemaBucketPtr bucket)
9281{
9282 xmlSchemaParserCtxtPtr newpctxt;
9283 int res = 0;
9284
9285 if (bucket == NULL)
9286 return(0);
9287 if (bucket->parsed) {
9288 PERROR_INT("xmlSchemaParseNewDoc",
9289 "reparsing a schema doc");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009290 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009291 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009292 if (bucket->doc == NULL) {
9293 PERROR_INT("xmlSchemaParseNewDoc",
9294 "parsing a schema doc, but there's no doc");
9295 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009296 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009297 if (pctxt->constructor == NULL) {
9298 PERROR_INT("xmlSchemaParseNewDoc",
9299 "no constructor");
9300 return(-1);
9301 }
9302 /* Create and init the temporary parser context. */
9303 newpctxt = xmlSchemaNewParserCtxtUseDict(
9304 (const char *) bucket->schemaLocation, pctxt->dict);
9305 if (newpctxt == NULL)
9306 return(-1);
9307 newpctxt->constructor = pctxt->constructor;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009308 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009309 * TODO: Can we avoid that the parser knows about the main schema?
9310 * It would be better if he knows about the current schema bucket
9311 * only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009312 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009313 newpctxt->schema = schema;
9314 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
9315 pctxt->userData);
9316 newpctxt->counter = pctxt->counter;
9317
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009318
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009319 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
9320
9321 /* Channel back errors and cleanup the temporary parser context. */
9322 if (res != 0)
9323 pctxt->err = res;
9324 pctxt->nberrors += newpctxt->nberrors;
9325 pctxt->counter = newpctxt->counter;
9326 newpctxt->constructor = NULL;
9327 /* Free the parser context. */
9328 xmlSchemaFreeParserCtxt(newpctxt);
9329 return(res);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009330}
William M. Brack2f2a6632004-08-20 23:09:47 +00009331
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009332static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009333xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
9334 xmlSchemaSchemaRelationPtr rel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009335{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009336 xmlSchemaSchemaRelationPtr cur = bucket->relations;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009337
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009338 if (cur == NULL) {
9339 bucket->relations = rel;
9340 return;
9341 }
9342 while (cur->next != NULL)
9343 cur = cur->next;
9344 cur->next = rel;
9345}
9346
9347
9348static const xmlChar *
9349xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
9350 xmlNodePtr ctxtNode)
9351{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009352 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009353 * Build an absolue location URI.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009354 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009355 if (location != NULL) {
9356 if (ctxtNode == NULL)
9357 return(location);
9358 else {
9359 xmlChar *base, *URI;
9360 const xmlChar *ret = NULL;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009361
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009362 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
9363 if (base == NULL) {
9364 URI = xmlBuildURI(location, ctxtNode->doc->URL);
9365 } else {
9366 URI = xmlBuildURI(location, base);
9367 xmlFree(base);
9368 }
9369 if (URI != NULL) {
9370 ret = xmlDictLookup(dict, URI, -1);
9371 xmlFree(URI);
9372 return(ret);
9373 }
9374 }
9375 }
9376 return(NULL);
9377}
9378
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009379
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009380
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009381/**
9382 * xmlSchemaAddSchemaDoc:
9383 * @pctxt: a schema validation context
9384 * @schema: the schema being built
9385 * @node: a subtree containing XML Schema informations
9386 *
9387 * Parse an included (and to-be-redefined) XML schema document.
9388 *
9389 * Returns 0 on success, a positive error code on errors and
9390 * -1 in case of an internal or API error.
9391 */
9392
9393static int
9394xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
9395 int type, /* import or include or redefine */
9396 const xmlChar *schemaLocation,
9397 xmlDocPtr schemaDoc,
9398 const char *schemaBuffer,
9399 int schemaBufferLen,
9400 xmlNodePtr invokingNode,
9401 const xmlChar *sourceTargetNamespace,
9402 const xmlChar *importNamespace,
9403 xmlSchemaBucketPtr *bucket)
9404{
9405 const xmlChar *targetNamespace = NULL;
9406 xmlSchemaSchemaRelationPtr relation = NULL;
9407 xmlDocPtr doc = NULL;
9408 int res = 0, err = 0, located = 0, preserveDoc = 0;
9409 xmlSchemaBucketPtr bkt = NULL;
9410
9411 if (bucket != NULL)
9412 *bucket = NULL;
9413
9414 switch (type) {
9415 case XML_SCHEMA_SCHEMA_IMPORT:
9416 case XML_SCHEMA_SCHEMA_MAIN:
9417 err = XML_SCHEMAP_SRC_IMPORT;
9418 break;
9419 case XML_SCHEMA_SCHEMA_INCLUDE:
9420 err = XML_SCHEMAP_SRC_INCLUDE;
9421 break;
9422 case XML_SCHEMA_SCHEMA_REDEFINE:
9423 err = XML_SCHEMAP_SRC_REDEFINE;
9424 break;
9425 }
9426
9427
9428 /* Special handling for the main schema:
9429 * skip the location and relation logic and just parse the doc.
9430 * We need just a bucket to be returned in this case.
9431 */
9432 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
9433 goto doc_load;
9434
9435 /* Note that we expect the location to be an absulute URI. */
9436 if (schemaLocation != NULL) {
9437 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
9438 if ((bkt != NULL) &&
9439 (pctxt->constructor->bucket == bkt)) {
9440 /* Report self-imports/inclusions/redefinitions. */
9441
9442 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
9443 invokingNode, NULL,
9444 "The schema must not import/include/redefine itself",
9445 NULL, NULL);
9446 goto exit;
9447 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009448 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009449 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009450 * Create a relation for the graph of schemas.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009451 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009452 relation = xmlSchemaSchemaRelationCreate();
9453 if (relation == NULL)
9454 return(-1);
9455 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
9456 relation);
9457 relation->type = type;
9458
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009459 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009460 * Save the namespace import information.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009461 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009462 if (WXS_IS_IMPMAIN(type)) {
9463 relation->importNamespace = importNamespace;
9464 if (schemaLocation == NULL) {
9465 /*
9466 * No location; this is just an import of the namespace.
9467 * Note that we don't assign a bucket to the relation
9468 * in this case.
9469 */
9470 goto exit;
9471 }
9472 targetNamespace = importNamespace;
9473 }
9474
9475 /* Did we already fetch the doc? */
9476 if (bkt != NULL) {
9477 /* TODO: The following nasty cases will produce an error. */
9478 if ((WXS_IS_IMPMAIN(type)) && (! bkt->imported)) {
9479 /* We included/redefined and then try to import a schema. */
9480 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
9481 invokingNode, NULL,
9482 "The schema document '%s' cannot be imported, since "
9483 "it was already included or redefined",
9484 schemaLocation, NULL);
9485 goto exit;
9486 } else if ((! WXS_IS_IMPMAIN(type)) && (bkt->imported)) {
9487 /* We imported and then try to include/redefine a schema. */
9488 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
9489 invokingNode, NULL,
9490 "The schema document '%s' cannot be included or "
9491 "redefined, since it was already imported",
9492 schemaLocation, NULL);
9493 goto exit;
9494 }
9495 }
9496
9497 if (WXS_IS_IMPMAIN(type)) {
9498 /*
9499 * Given that the schemaLocation [attribute] is only a hint, it is open
9500 * to applications to ignore all but the first <import> for a given
9501 * namespace, regardless of the ·actual value· of schemaLocation, but
9502 * such a strategy risks missing useful information when new
9503 * schemaLocations are offered.
9504 *
9505 * We will use the first <import> that comes with a location.
9506 * Further <import>s *with* a location, will result in an error.
9507 * TODO: Better would be to just report a warning here, but
9508 * we'll try it this way until someone complains.
9509 *
9510 * Schema Document Location Strategy:
9511 * 3 Based on the namespace name, identify an existing schema document,
9512 * either as a resource which is an XML document or a <schema> element
9513 * information item, in some local schema repository;
9514 * 5 Attempt to resolve the namespace name to locate such a resource.
9515 *
9516 * NOTE: (3) and (5) are not supported.
9517 */
9518 if (bkt != NULL) {
9519 relation->bucket = bkt;
9520 goto exit;
9521 }
9522 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
9523 importNamespace, 1);
9524
9525 if (bkt != NULL) {
9526 relation->bucket = bkt;
9527 if (bkt->schemaLocation == NULL) {
9528 /* First given location of the schema; load the doc. */
9529 bkt->schemaLocation = schemaLocation;
9530 } else {
9531 if (!xmlStrEqual(schemaLocation,
9532 bkt->schemaLocation)) {
9533 /*
9534 * Additional location given; just skip it.
9535 * URGENT TODO: We should report a warning here.
9536 * res = XML_SCHEMAP_SRC_IMPORT;
9537 */
9538 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
9539 XML_SCHEMAP_WARN_SKIP_SCHEMA,
9540 invokingNode, NULL,
9541 "Skipping import of schema located at '%s' for the "
9542 "namespace '%s', since this namespace was already "
9543 "imported with the schema located at '%s'",
9544 schemaLocation, importNamespace, bkt->schemaLocation);
9545 }
9546 goto exit;
9547 }
9548 }
9549 /*
9550 * No bucket + first location: load the doc and create a
9551 * bucket.
9552 */
9553 } else {
9554 /* <include> and <redefine> */
9555 if (bkt != NULL) {
9556
9557 if ((bkt->origTargetNamespace == NULL) &&
9558 (bkt->targetNamespace != sourceTargetNamespace)) {
9559 xmlSchemaBucketPtr chamel;
9560
9561 /*
9562 * Chameleon include/redefine: skip loading only if it was
9563 * aleady build for the targetNamespace of the including
9564 * schema.
9565 */
9566 /*
9567 * URGENT TODO: If the schema is a chameleon-include then copy
9568 * the components into the including schema and modify the
9569 * targetNamespace of those components, do nothing otherwise.
9570 * NOTE: This is currently worked-around by compiling the
9571 * chameleon for every destinct including targetNamespace; thus
9572 * not performant at the moment.
9573 * TODO: Check when the namespace in wildcards for chameleons
9574 * needs to be converted: before we built wildcard intersections
9575 * or after.
9576 * Answer: after!
9577 */
9578 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
9579 schemaLocation, sourceTargetNamespace);
9580 if (chamel != NULL) {
9581 /* A fitting chameleon was already parsed; NOP. */
9582 relation->bucket = chamel;
9583 goto exit;
9584 }
9585 /*
9586 * We need to parse the chameleon again for a different
9587 * targetNamespace.
9588 * CHAMELEON TODO: Optimize this by only parsing the
9589 * chameleon once, and then copying the components to
9590 * the new targetNamespace.
9591 */
9592 bkt = NULL;
9593 } else {
9594 relation->bucket = bkt;
9595 goto exit;
9596 }
9597 }
9598 }
9599 if ((bkt != NULL) && (bkt->doc != NULL)) {
9600 PERROR_INT("xmlSchemaAddSchemaDoc",
9601 "trying to load a schema doc, but a doc is already "
9602 "assigned to the schema bucket");
9603 goto exit_failure;
9604 }
9605
9606doc_load:
9607 /*
9608 * Load the document.
9609 */
9610 if (schemaDoc != NULL) {
9611 doc = schemaDoc;
9612 /* Don' free this one, since it was provided by the caller. */
9613 preserveDoc = 1;
9614 /* TODO: Does the context or the doc hold the location? */
9615 if (schemaDoc->URL != NULL)
9616 schemaLocation = xmlDictLookup(pctxt->dict,
9617 schemaDoc->URL, -1);
9618
9619 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
9620 xmlParserCtxtPtr parserCtxt;
9621
9622 parserCtxt = xmlNewParserCtxt();
9623 if (parserCtxt == NULL) {
9624 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
9625 "allocating a parser context", NULL);
9626 goto exit_failure;
9627 }
9628 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9629 /*
9630 * TODO: Do we have to burden the schema parser dict with all
9631 * the content of the schema doc?
9632 */
9633 xmlDictFree(parserCtxt->dict);
9634 parserCtxt->dict = pctxt->dict;
9635 xmlDictReference(parserCtxt->dict);
9636 }
9637 if (schemaLocation != NULL) {
9638 /* Parse from file. */
9639 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
9640 NULL, SCHEMAS_PARSE_OPTIONS);
9641 } else if (schemaBuffer != NULL) {
9642 /* Parse from memory buffer. */
9643 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
9644 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
9645 schemaLocation = xmlStrdup(BAD_CAST "in_memory_buffer");
9646 if (doc != NULL)
9647 doc->URL = schemaLocation;
9648 }
9649 /*
9650 * For <import>:
9651 * 2.1 The referent is (a fragment of) a resource which is an
9652 * XML document (see clause 1.1), which in turn corresponds to
9653 * a <schema> element information item in a well-formed information
9654 * set, which in turn corresponds to a valid schema.
9655 * TODO: (2.1) fragments of XML documents are not supported.
9656 *
9657 * 2.2 The referent is a <schema> element information item in
9658 * a well-formed information set, which in turn corresponds
9659 * to a valid schema.
9660 * TODO: (2.2) is not supported.
9661 */
9662 if (doc == NULL) {
9663 xmlErrorPtr lerr;
9664 lerr = xmlGetLastError();
9665 /*
9666 * Check if this a parser error, or if the document could
9667 * just not be located.
9668 * TODO: Try to find specific error codes to react only on
9669 * localisation failures.
9670 */
9671 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
9672 /*
9673 * We assume a parser error here.
9674 */
9675 located = 1;
9676 /* TODO: Error code ?? */
9677 res = XML_SCHEMAP_SRC_IMPORT_2_1;
9678 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
9679 invokingNode, NULL,
9680 "Failed to parse the XML resource '%s'",
9681 schemaLocation, NULL);
9682 }
9683 }
9684 xmlFreeParserCtxt(parserCtxt);
9685 if ((doc == NULL) && located)
9686 goto exit_error;
9687 } else {
9688 xmlSchemaPErr(pctxt, NULL,
9689 XML_SCHEMAP_NOTHING_TO_PARSE,
9690 "No information for parsing was provided with the "
9691 "given schema parser context.\n",
9692 NULL, NULL);
9693 goto exit_failure;
9694 }
9695 /*
9696 * Preprocess the document.
9697 */
9698 if (doc != NULL) {
9699 xmlNodePtr docElem = NULL;
9700
9701 located = 1;
9702 docElem = xmlDocGetRootElement(doc);
9703 if (docElem == NULL) {
9704 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
9705 invokingNode, NULL,
9706 "The document '%s' has no document element",
9707 schemaLocation, NULL);
9708 xmlFreeDoc(doc);
9709 doc = NULL;
9710 goto exit_error;
9711 }
9712 /*
9713 * Remove all the blank text nodes.
9714 */
9715 xmlSchemaCleanupDoc(pctxt, docElem);
9716 /*
9717 * Check the schema's top level element.
9718 */
9719 if (!IS_SCHEMA(docElem, "schema")) {
9720 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
9721 invokingNode, NULL,
9722 "The XML document '%s' is not a schema document",
9723 schemaLocation, NULL);
9724 xmlFreeDoc(doc);
9725 doc = NULL;
9726 goto exit_error;
9727 }
9728 /*
9729 * Note that we don't apply a type check for the
9730 * targetNamespace value here.
9731 */
9732 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
9733 "targetNamespace");
9734 }
9735
9736/* after_doc_loading: */
9737 if ((bkt == NULL) && located) {
9738 /* Only create a bucket if the schema was located. */
9739 bkt = xmlSchemaBucketCreate(pctxt, type,
9740 targetNamespace);
9741 if (bkt == NULL)
9742 goto exit_failure;
9743 }
9744 if (bkt != NULL) {
9745 bkt->schemaLocation = schemaLocation;
9746 bkt->located = located;
9747 if (doc != NULL) {
9748 bkt->doc = doc;
9749 bkt->targetNamespace = targetNamespace;
9750 bkt->origTargetNamespace = targetNamespace;
9751 if (preserveDoc)
9752 bkt->preserveDoc = 1;
9753 }
9754 if (WXS_IS_IMPMAIN(type))
9755 bkt->imported++;
9756 /*
9757 * Add it to the graph of schemas.
9758 */
9759 if (relation != NULL)
9760 relation->bucket = bkt;
9761 }
9762
9763exit:
9764 /*
9765 * Return the bucket explicitely; this is needed for the
9766 * main schema.
9767 */
9768 if (bucket != NULL)
9769 *bucket = bkt;
9770 return (0);
9771
9772exit_error:
9773 if ((doc != NULL) && (! preserveDoc)) {
9774 xmlFreeDoc(doc);
9775 if (bkt != NULL)
9776 bkt->doc = NULL;
9777 }
9778 return(pctxt->err);
9779
9780exit_failure:
9781 if ((doc != NULL) && (! preserveDoc)) {
9782 xmlFreeDoc(doc);
9783 if (bkt != NULL)
9784 bkt->doc = NULL;
9785 }
9786 return (-1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009787}
9788
William M. Brack2f2a6632004-08-20 23:09:47 +00009789/**
9790 * xmlSchemaParseImport:
9791 * @ctxt: a schema validation context
9792 * @schema: the schema being built
9793 * @node: a subtree containing XML Schema informations
9794 *
9795 * parse a XML schema Import definition
9796 * *WARNING* this interface is highly subject to change
9797 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009798 * Returns 0 in case of success, a positive error code if
9799 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009800 */
9801static int
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009802xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00009803 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009804{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009805 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009806 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009807 const xmlChar *schemaLocation = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009808 xmlAttrPtr attr;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009809 int ret = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009810 xmlSchemaBucketPtr bucket = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009811
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009812 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
William M. Brack2f2a6632004-08-20 23:09:47 +00009813 return (-1);
9814
9815 /*
9816 * Check for illegal attributes.
9817 */
9818 attr = node->properties;
9819 while (attr != NULL) {
9820 if (attr->ns == NULL) {
9821 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9822 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9823 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009824 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009825 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9826 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009827 }
9828 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009829 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009830 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9831 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009832 }
9833 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009834 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009835 /*
9836 * Extract and validate attributes.
9837 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009838 if (xmlSchemaPValAttr(pctxt, NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009839 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009840 &namespaceName) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009841 xmlSchemaPSimpleTypeErr(pctxt,
9842 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009843 NULL, node,
9844 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009845 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009846 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +00009847 }
9848
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009849 if (xmlSchemaPValAttr(pctxt, NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009850 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009851 &schemaLocation) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009852 xmlSchemaPSimpleTypeErr(pctxt,
9853 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009854 NULL, node,
9855 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009856 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009857 return (pctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009858 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009859 /*
9860 * And now for the children...
9861 */
9862 child = node->children;
9863 if (IS_SCHEMA(child, "annotation")) {
9864 /*
9865 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009866 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009867 */
9868 child = child->next;
9869 }
9870 if (child != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009871 xmlSchemaPContentErr(pctxt,
9872 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
William M. Brack2f2a6632004-08-20 23:09:47 +00009873 NULL, NULL, node, child, NULL,
9874 "(annotation?)");
9875 }
9876 /*
9877 * Apply additional constraints.
9878 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009879 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009880 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009881 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9882 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009883 * targetNamespace [attribute].
9884 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009885 if (xmlStrEqual(pctxt->targetNamespace, namespaceName)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009886 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009887 XML_SCHEMAP_SRC_IMPORT_1_1,
9888 NULL, NULL, node,
9889 "The value of the attribute 'namespace' must not match "
9890 "the target namespace '%s' of the importing schema",
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009891 pctxt->targetNamespace);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009892 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +00009893 }
9894 } else {
9895 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009896 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009897 * <schema> must have a targetNamespace [attribute].
9898 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009899 if (pctxt->targetNamespace == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009900 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009901 XML_SCHEMAP_SRC_IMPORT_1_2,
9902 NULL, NULL, node,
9903 "The attribute 'namespace' must be existent if "
9904 "the importing schema has no target namespace",
9905 NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009906 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +00009907 }
9908 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009909 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009910 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009911 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009912 if (schemaLocation != NULL)
9913 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
9914 schemaLocation, node);
9915 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
9916 schemaLocation, NULL, NULL, 0, node, pctxt->targetNamespace,
9917 namespaceName, &bucket);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009918
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009919 if (ret != 0)
9920 return(ret);
9921
9922 /*
9923 * For <import>: "It is *not* an error for the application
9924 * schema reference strategy to fail."
9925 * So just don't parse if no schema document was found.
9926 * Note that we will get no bucket if the schema could not be
9927 * located or if there was no schemaLocation.
9928 */
9929 if ((bucket == NULL) && (schemaLocation != NULL)) {
9930 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
9931 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
9932 node, NULL,
9933 "Failed to locate a schema at location '%s'. "
9934 "Skipping the import", schemaLocation, NULL, NULL);
9935 }
9936
9937 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
9938 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
9939 }
9940
9941 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00009942}
9943
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009944static int
9945xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
9946 xmlSchemaPtr schema,
9947 xmlNodePtr node,
9948 xmlChar **schemaLocation,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +00009949 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009950{
9951 xmlAttrPtr attr;
9952
9953 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
9954 (schemaLocation == NULL))
9955 return (-1);
9956
9957 *schemaLocation = NULL;
9958 /*
9959 * Check for illegal attributes.
9960 * Applies for both <include> and <redefine>.
9961 */
9962 attr = node->properties;
9963 while (attr != NULL) {
9964 if (attr->ns == NULL) {
9965 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9966 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
9967 xmlSchemaPIllegalAttrErr(pctxt,
9968 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9969 NULL, NULL, attr);
9970 }
9971 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9972 xmlSchemaPIllegalAttrErr(pctxt,
9973 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9974 NULL, NULL, attr);
9975 }
9976 attr = attr->next;
9977 }
9978 xmlSchemaPValAttrID(pctxt, NULL, NULL, node, BAD_CAST "id");
9979 /*
9980 * Preliminary step, extract the URI-Reference and make an URI
9981 * from the base.
9982 */
9983 /*
9984 * Attribute "schemaLocation" is mandatory.
9985 */
9986 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9987 if (attr != NULL) {
9988 xmlChar *base = NULL;
9989 xmlChar *uri = NULL;
9990
9991 if (xmlSchemaPValAttrNode(pctxt, NULL, NULL, attr,
9992 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
9993 (const xmlChar **) schemaLocation) != 0)
9994 goto exit_error;
9995 base = xmlNodeGetBase(node->doc, node);
9996 if (base == NULL) {
9997 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
9998 } else {
9999 uri = xmlBuildURI(*schemaLocation, base);
10000 xmlFree(base);
10001 }
10002 if (uri == NULL) {
10003 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10004 "could not build an URI from the schemaLocation")
10005 goto exit_failure;
10006 }
10007 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10008 xmlFree(uri);
10009 } else {
10010 xmlSchemaPMissingAttrErr(pctxt,
10011 XML_SCHEMAP_S4S_ATTR_MISSING,
10012 NULL, node, "schemaLocation", NULL);
10013 goto exit_error;
10014 }
10015 /*
10016 * Report self-inclusion and self-redefinition.
10017 */
10018 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010019 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010020 xmlSchemaPCustomErr(pctxt,
10021 XML_SCHEMAP_SRC_REDEFINE,
10022 NULL, NULL, node,
10023 "The schema document '%s' cannot redefine itself.",
10024 *schemaLocation);
10025 } else {
10026 xmlSchemaPCustomErr(pctxt,
10027 XML_SCHEMAP_SRC_INCLUDE,
10028 NULL, NULL, node,
10029 "The schema document '%s' cannot include itself.",
10030 *schemaLocation);
10031 }
10032 goto exit_error;
10033 }
10034
10035 return(0);
10036exit_error:
10037 return(pctxt->err);
10038exit_failure:
10039 return(-1);
10040}
10041
10042static int
10043xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10044 xmlSchemaPtr schema,
10045 xmlNodePtr node,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010046 int type)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010047{
10048 xmlNodePtr child = NULL;
10049 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010050 int res = 0, /* docRes = 0, located = 0, */ hasRedefinitions = 0;
10051 int isChameleon = 0, wasChameleon = 0;
10052 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010053
10054 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10055 return (-1);
10056
10057 /*
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010058 * Parse attributes. Note that the returned schemaLocation will
10059 * be already converted to an absolute URI.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010060 */
10061 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010062 node, (xmlChar **) (&schemaLocation), type);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010063 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010064 return(res);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010065 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010066 * Load and add the schema document.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010067 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010068 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10069 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010070 if (res != 0)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010071 return(res);
10072 /*
10073 if (bucket == NULL) {
10074 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10075 "no schema bucket aquired");
10076 return(-1);
10077 }
10078 */
10079 if ((bucket == NULL) || (bucket->doc == NULL)) {
10080 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10081 /*
10082 * WARNING for <include>:
10083 * We will raise an error if the schema cannot be located
10084 * for inclusions, since the that was the feedback from the
10085 * schema people. I.e. the following spec piece will *not* be
10086 * satisfied:
10087 * SPEC src-include: "It is not an error for the ·actual value· of the
10088 * schemaLocation [attribute] to fail to resolve it all, in which
10089 * case no corresponding inclusion is performed.
10090 * So do we need a warning report here?"
10091 */
10092 res = XML_SCHEMAP_SRC_INCLUDE;
10093 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10094 node, NULL,
10095 "Failed to load the document '%s' for inclusion",
10096 schemaLocation, NULL);
10097 } else {
10098 /*
10099 * NOTE: This was changed to raise an error even if no redefinitions
10100 * are specified.
10101 *
10102 * SPEC src-redefine (1)
10103 * "If there are any element information items among the [children]
10104 * other than <annotation> then the ·actual value· of the
10105 * schemaLocation [attribute] must successfully resolve."
10106 * TODO: Ask the WG if a the location has always to resolve
10107 * here as well!
10108 */
10109 res = XML_SCHEMAP_SRC_REDEFINE;
10110 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10111 node, NULL,
10112 "Failed to load the document '%s' for redefinition",
10113 schemaLocation, NULL);
10114 }
10115 } else {
10116 /*
10117 * Check targetNamespace sanity before parsing the new schema.
10118 * TODO: Note that we won't check further content if the
10119 * targetNamespace was bad.
10120 */
10121 if (bucket->origTargetNamespace != NULL) {
10122 /*
10123 * SPEC src-include (2.1)
10124 * "SII has a targetNamespace [attribute], and its ·actual
10125 * value· is identical to the ·actual value· of the targetNamespace
10126 * [attribute] of SIIÂ’ (which must have such an [attribute])."
10127 */
10128 if (pctxt->targetNamespace == NULL) {
10129 xmlSchemaCustomErr(ACTXT_CAST pctxt,
10130 XML_SCHEMAP_SRC_INCLUDE,
10131 node, NULL,
10132 "The target namespace of the included/redefined schema "
10133 "'%s' has to be absent, since the including/redefining "
10134 "schema has no target namespace",
10135 schemaLocation, NULL);
10136 goto exit_error;
10137 } else if (!xmlStrEqual(bucket->origTargetNamespace,
10138 pctxt->targetNamespace)) {
10139 /* TODO: Change error function. */
10140 xmlSchemaPCustomErrExt(pctxt,
10141 XML_SCHEMAP_SRC_INCLUDE,
10142 NULL, NULL, node,
10143 "The target namespace '%s' of the included/redefined "
10144 "schema '%s' differs from '%s' of the "
10145 "including/redefining schema",
10146 bucket->origTargetNamespace, schemaLocation,
10147 pctxt->targetNamespace);
10148 goto exit_error;
10149 }
10150 } else if (pctxt->targetNamespace != NULL) {
10151 /*
10152 * Chameleons: the original target namespace will
10153 * differ from the resulting namespace.
10154 */
10155 isChameleon = 1;
10156 if (bucket->parsed &&
10157 (bucket->targetNamespace != pctxt->targetNamespace)) {
10158 /*
10159 * This is a sanity check, I dunno yet if this can happen.
10160 */
10161 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10162 "trying to use an already parsed schema for a "
10163 "different targetNamespace");
10164 return(-1);
10165 }
10166 bucket->targetNamespace = pctxt->targetNamespace;
10167 }
10168 }
10169 /*
10170 * Parse the schema.
10171 */
10172 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
10173 if (isChameleon) {
10174 /* TODO: Get rid of this flag on the schema itself. */
10175 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
10176 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
10177 } else
10178 wasChameleon = 1;
10179 }
10180 xmlSchemaParseNewDoc(pctxt, schema, bucket);
10181 /* Restore chameleon flag. */
10182 if (isChameleon && (!wasChameleon))
10183 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
10184 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010185 /*
10186 * And now for the children...
10187 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010188 child = node->children;
10189 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10190
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010191 /*
10192 * Parse (simpleType | complexType | group | attributeGroup))*
10193 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010194 /*
10195 * How to proceed if the redefined schema was not located?
10196 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010197 pctxt->isRedefine = 1;
10198 while (IS_SCHEMA(child, "annotation") ||
10199 IS_SCHEMA(child, "simpleType") ||
10200 IS_SCHEMA(child, "complexType") ||
10201 IS_SCHEMA(child, "group") ||
10202 IS_SCHEMA(child, "attributeGroup")) {
10203 if (IS_SCHEMA(child, "annotation")) {
10204 /*
10205 * TODO: discard or not?
10206 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010207 } else if (bucket && bucket->parsed) {
10208 /*
10209 * TODO: Not nice: we won't parse the stuff if the redefined
10210 * document was not parsed or not located.
10211 */
10212 if (IS_SCHEMA(child, "simpleType")) {
10213 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
10214 } else if (IS_SCHEMA(child, "complexType")) {
10215 xmlSchemaParseComplexType(pctxt, schema, child, 1);
10216 hasRedefinitions = 1;
10217 } else if (IS_SCHEMA(child, "group")) {
10218 TODO
10219 hasRedefinitions = 1;
10220 /* xmlSchemaParseModelGroupDefinition(pctxt,
10221 schema, child); */
10222 } else if (IS_SCHEMA(child, "attributeGroup")) {
10223 TODO
10224 hasRedefinitions = 1;
10225 /* xmlSchemaParseAttributeGroup(pctxt, schema,
10226 child, 1); */
10227 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010228 }
10229 child = child->next;
10230 }
10231 pctxt->isRedefine = 0;
10232 } else {
10233 if (IS_SCHEMA(child, "annotation")) {
10234 /*
10235 * TODO: discard or not?
10236 */
10237 child = child->next;
10238 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010239 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010240 if (child != NULL) {
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010241 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010242 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10243 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010244 NULL, NULL, node, child, NULL,
10245 "(annotation | (simpleType | complexType | group | attributeGroup))*");
10246 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010247 xmlSchemaPContentErr(pctxt, res,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010248 NULL, NULL, node, child, NULL,
10249 "(annotation?)");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010250 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010251 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010252 return(res);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010253
10254exit_error:
10255 return(pctxt->err);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010256}
10257
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010258static int
10259xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10260 xmlNodePtr node)
10261{
10262 int res;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010263#ifndef ENABLE_REDEFINE
10264 TODO
10265 return(0);
10266#endif
10267 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
10268 XML_SCHEMA_SCHEMA_REDEFINE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010269 if (res != 0)
10270 return(res);
10271 return(0);
10272}
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010273
10274static int
10275xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10276 xmlNodePtr node)
10277{
10278 int res;
10279
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010280 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
10281 XML_SCHEMA_SCHEMA_INCLUDE);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010282 if (res != 0)
10283 return(res);
10284 return(0);
10285}
10286
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010287/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010288 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +000010289 * @ctxt: a schema validation context
10290 * @schema: the schema being built
10291 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010292 * @type: the "compositor" type
10293 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +000010294 *
10295 * parse a XML schema Sequence definition
10296 * *WARNING* this interface is highly subject to change
10297 *
William M. Bracke7091952004-05-11 15:09:58 +000010298 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +000010299 * 1 in case of success.
10300 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010301static xmlSchemaTreeItemPtr
10302xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
10303 xmlNodePtr node, xmlSchemaTypeType type,
10304 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +000010305{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010306 xmlSchemaModelGroupPtr item;
10307 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000010308 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000010309 xmlAttrPtr attr;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010310 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010311
10312 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010313 return (NULL);
10314 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010315 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +000010316 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000010317 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010318 if (item == NULL)
10319 return (NULL);
10320
10321 if (withParticle) {
10322 if (type == XML_SCHEMA_TYPE_ALL) {
10323 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010324 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010325 } else {
10326 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010327 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
10328 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
10329 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010330 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010331 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
10332 /*
10333 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010334 */
10335 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
10336 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010337 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010338 particle->children = (xmlSchemaTreeItemPtr) item;
10339 /*
10340 * Check for illegal attributes.
10341 */
10342 attr = node->properties;
10343 while (attr != NULL) {
10344 if (attr->ns == NULL) {
10345 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10346 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
10347 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010348 xmlSchemaPIllegalAttrErr(ctxt,
10349 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10350 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010351 }
10352 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010353 xmlSchemaPIllegalAttrErr(ctxt,
10354 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10355 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010356 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010357 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000010358 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010359 } else {
10360 /*
10361 * Check for illegal attributes.
10362 */
10363 attr = node->properties;
10364 while (attr != NULL) {
10365 if (attr->ns == NULL) {
10366 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010367 xmlSchemaPIllegalAttrErr(ctxt,
10368 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10369 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010370 }
10371 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010372 xmlSchemaPIllegalAttrErr(ctxt,
10373 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10374 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010375 }
10376 attr = attr->next;
10377 }
10378
William M. Brack2f2a6632004-08-20 23:09:47 +000010379 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010380
William M. Brack2f2a6632004-08-20 23:09:47 +000010381 /*
10382 * Extract and validate attributes.
10383 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010384 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000010385 /*
10386 * And now for the children...
10387 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010388 child = node->children;
10389 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010390 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010391 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010392 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010393 if (type == XML_SCHEMA_TYPE_ALL) {
10394 xmlSchemaParticlePtr part, last = NULL;
10395
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010396 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010397 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
10398 schema, child, 0);
10399 if (part != NULL) {
10400 if (part->minOccurs > 1)
10401 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010402 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010403 "Invalid value for minOccurs (must be 0 or 1)", NULL);
10404 if (part->maxOccurs > 1)
10405 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010406 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010407 "Invalid value for maxOccurs (must be 0 or 1)",
10408 NULL);
10409 if (last == NULL)
10410 item->children = (xmlSchemaTreeItemPtr) part;
10411 else
10412 last->next = (xmlSchemaTreeItemPtr) part;
10413 last = part;
10414 }
10415 child = child->next;
10416 }
10417 if (child != NULL) {
10418 xmlSchemaPContentErr(ctxt,
10419 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10420 NULL, NULL, node, child, NULL,
10421 "(annotation?, (annotation?, element*)");
10422 }
10423 } else {
10424 /* choice + sequence */
10425 xmlSchemaTreeItemPtr part = NULL, last = NULL;
10426
10427 while ((IS_SCHEMA(child, "element")) ||
10428 (IS_SCHEMA(child, "group")) ||
10429 (IS_SCHEMA(child, "any")) ||
10430 (IS_SCHEMA(child, "choice")) ||
10431 (IS_SCHEMA(child, "sequence"))) {
10432
10433 if (IS_SCHEMA(child, "element")) {
10434 part = (xmlSchemaTreeItemPtr)
10435 xmlSchemaParseElement(ctxt, schema, child, 0);
10436 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010437 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010438 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10439 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010440 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010441 xmlSchemaParseAny(ctxt, schema, child);
10442 } else if (IS_SCHEMA(child, "choice")) {
10443 part = xmlSchemaParseModelGroup(ctxt, schema, child,
10444 XML_SCHEMA_TYPE_CHOICE, 1);
10445 } else if (IS_SCHEMA(child, "sequence")) {
10446 part = xmlSchemaParseModelGroup(ctxt, schema, child,
10447 XML_SCHEMA_TYPE_SEQUENCE, 1);
10448 }
10449 if (part != NULL) {
10450 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010451 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010452 else
10453 last->next = part;
10454 last = part;
10455 }
10456 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010457 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010458 if (child != NULL) {
10459 xmlSchemaPContentErr(ctxt,
10460 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10461 NULL, NULL, node, child, NULL,
10462 "(annotation?, (element | group | choice | sequence | any)*)");
10463 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010464 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010465 if (withParticle) {
10466 if ((min == 0) && (max == 0))
10467 return (NULL);
10468 else
10469 return ((xmlSchemaTreeItemPtr) particle);
10470 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010471 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +000010472}
10473
10474/**
10475 * xmlSchemaParseRestriction:
10476 * @ctxt: a schema validation context
10477 * @schema: the schema being built
10478 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +000010479 *
10480 * parse a XML schema Restriction definition
10481 * *WARNING* this interface is highly subject to change
10482 *
10483 * Returns the type definition or NULL in case of error
10484 */
10485static xmlSchemaTypePtr
10486xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010487 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010488{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010489 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010490 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000010491 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010492
10493 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10494 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010495 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010496 type = ctxt->ctxtType;
10497 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010498
10499 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000010500 * Check for illegal attributes.
10501 */
10502 attr = node->properties;
10503 while (attr != NULL) {
10504 if (attr->ns == NULL) {
10505 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10506 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010507 xmlSchemaPIllegalAttrErr(ctxt,
10508 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10509 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010510 }
10511 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010512 xmlSchemaPIllegalAttrErr(ctxt,
10513 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10514 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010515 }
10516 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010517 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010518 /*
10519 * Extract and validate attributes.
10520 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010521 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000010522 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010523 * Attribute
William M. Brack2f2a6632004-08-20 23:09:47 +000010524 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010525 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010526 * Extract the base type. The "base" attribute is mandatory if inside
10527 * a complex type or if redefining.
10528 *
10529 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010530 * among its [children]), the simple type definition which is
10531 * the {content type} of the type definition ·resolved· to by
10532 * the ·actual value· of the base [attribute]"
10533 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010534 if (xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010535 NULL, NULL, node, "base",
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010536 &(type->baseNs), &(type->base)) == 0)
10537 {
10538 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
10539 xmlSchemaPMissingAttrErr(ctxt,
10540 XML_SCHEMAP_S4S_ATTR_MISSING,
10541 type, node, "base", NULL);
10542 } else if ((ctxt->isRedefine) &&
10543 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
10544 {
10545 if (type->base == NULL) {
10546 xmlSchemaPMissingAttrErr(ctxt,
10547 XML_SCHEMAP_S4S_ATTR_MISSING,
10548 type, node, "base", NULL);
10549 } else if ((! xmlStrEqual(type->base, type->name)) ||
10550 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
10551 {
10552 xmlChar *str1 = NULL, *str2 = NULL;
10553 /*
10554 * REDEFINE: SPEC src-redefine (5)
10555 * "Within the [children], each <simpleType> must have a
10556 * <restriction> among its [children] ... the ·actual value· of
10557 * whose base [attribute] must be the same as the ·actual value·
10558 * of its own name attribute plus target namespace;"
10559 */
10560 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
10561 NULL, NULL, node, "This is a redefinition, but the QName "
10562 "value '%s' of the 'base' attribute does not match the "
10563 "type's designation '%s'",
10564 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
10565 xmlSchemaFormatQName(&str1, type->targetNamespace,
10566 type->name), NULL);
10567 FREE_AND_NULL(str1);
10568 FREE_AND_NULL(str2);
10569 }
10570 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010571 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010572 /*
10573 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010574 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010575 child = node->children;
10576 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010577 /*
10578 * Add the annotation to the simple type ancestor.
10579 */
10580 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10581 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010582 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010583 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010584 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
10585 /*
10586 * Corresponds to <simpleType><restriction><simpleType>.
10587 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010588 if (IS_SCHEMA(child, "simpleType")) {
10589 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010590 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000010591 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010592 * Either the base [attribute] or the simpleType [child] of the
10593 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +000010594 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010595 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010596 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010597 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +000010598 "The attribute 'base' and the <simpleType> child are "
10599 "mutually exclusive", NULL);
10600 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010601 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +000010602 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010603 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010604 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010605 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010606 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010607 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
10608 NULL, NULL, node, child,
10609 "Either the attribute 'base' or a <simpleType> child "
10610 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000010611 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010612 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10613 /*
10614 * Corresponds to <complexType><complexContent><restriction>...
10615 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010616 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010617 * Model groups <all>, <choice> and <sequence>.
10618 */
10619 if (IS_SCHEMA(child, "all")) {
10620 type->subtypes = (xmlSchemaTypePtr)
10621 xmlSchemaParseModelGroup(ctxt, schema, child,
10622 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010623 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010624 } else if (IS_SCHEMA(child, "choice")) {
10625 type->subtypes = (xmlSchemaTypePtr)
10626 xmlSchemaParseModelGroup(ctxt,
10627 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
10628 child = child->next;
10629 } else if (IS_SCHEMA(child, "sequence")) {
10630 type->subtypes = (xmlSchemaTypePtr)
10631 xmlSchemaParseModelGroup(ctxt, schema, child,
10632 XML_SCHEMA_TYPE_SEQUENCE, 1);
10633 child = child->next;
10634 /*
10635 * Model group reference <group>.
10636 */
10637 } else if (IS_SCHEMA(child, "group")) {
10638 type->subtypes = (xmlSchemaTypePtr)
10639 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10640 child = child->next;
10641 }
10642 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010643 /*
10644 * Corresponds to <complexType><simpleContent><restriction>...
10645 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010646 * "1.1 the simple type definition corresponding to the <simpleType>
10647 * among the [children] of <restriction> if there is one;"
10648 */
10649 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010650 /*
10651 * We will store the to-be-restricted simple type in
10652 * type->contentTypeDef *temporarily*.
10653 */
10654 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010655 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010656 if ( type->contentTypeDef == NULL)
10657 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010658 child = child->next;
10659 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010660 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010661
10662 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010663 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010664 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010665 /*
10666 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010667 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010668 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010669
Daniel Veillard01fa6152004-06-29 17:04:39 +000010670 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010671 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010672 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010673 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010674 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
10675 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +000010676 * *Single Facet Value*
10677 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010678 while ((IS_SCHEMA(child, "minInclusive")) ||
10679 (IS_SCHEMA(child, "minExclusive")) ||
10680 (IS_SCHEMA(child, "maxInclusive")) ||
10681 (IS_SCHEMA(child, "maxExclusive")) ||
10682 (IS_SCHEMA(child, "totalDigits")) ||
10683 (IS_SCHEMA(child, "fractionDigits")) ||
10684 (IS_SCHEMA(child, "pattern")) ||
10685 (IS_SCHEMA(child, "enumeration")) ||
10686 (IS_SCHEMA(child, "whiteSpace")) ||
10687 (IS_SCHEMA(child, "length")) ||
10688 (IS_SCHEMA(child, "maxLength")) ||
10689 (IS_SCHEMA(child, "minLength"))) {
10690 facet = xmlSchemaParseFacet(ctxt, schema, child);
10691 if (facet != NULL) {
10692 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010693 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010694 else
10695 lastfacet->next = facet;
10696 lastfacet = facet;
10697 lastfacet->next = NULL;
10698 }
10699 child = child->next;
10700 }
10701 /*
10702 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010703 */
10704 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010705 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
10706
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010707 facet = type->facets;
10708 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010709 facetLink = (xmlSchemaFacetLinkPtr)
10710 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000010711 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010712 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010713 xmlFree(facetLink);
10714 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010715 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010716 facetLink->facet = facet;
10717 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010718 if (lastFacetLink == NULL)
10719 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010720 else
10721 lastFacetLink->next = facetLink;
10722 lastFacetLink = facetLink;
10723 facet = facet->next;
10724 } while (facet != NULL);
10725 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010726 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010727 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
10728 /*
10729 * Attribute uses/declarations.
10730 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010731 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010732 /*
10733 * Attribute wildcard.
10734 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010735 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010736 type->attributeWildcard =
10737 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010738 child = child->next;
10739 }
10740 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010741 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010742 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10743 xmlSchemaPContentErr(ctxt,
10744 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010745 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010746 "annotation?, (group | all | choice | sequence)?, "
10747 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010748 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010749 xmlSchemaPContentErr(ctxt,
10750 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010751 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010752 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10753 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10754 "length | minLength | maxLength | enumeration | whiteSpace | "
10755 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10756 } else {
10757 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010758 xmlSchemaPContentErr(ctxt,
10759 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010760 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010761 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10762 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10763 "length | minLength | maxLength | enumeration | whiteSpace | "
10764 "pattern)*))");
10765 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010766 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010767 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010768}
10769
10770/**
10771 * xmlSchemaParseExtension:
10772 * @ctxt: a schema validation context
10773 * @schema: the schema being built
10774 * @node: a subtree containing XML Schema informations
10775 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010776 * Parses an <extension>, which is found inside a
10777 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010778 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010779 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010780 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010781 */
10782static xmlSchemaTypePtr
10783xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010784 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010785{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010786 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010787 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010788 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010789
10790 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10791 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010792 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010793 type = ctxt->ctxtType;
10794 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010795
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010796 /*
10797 * Check for illegal attributes.
10798 */
10799 attr = node->properties;
10800 while (attr != NULL) {
10801 if (attr->ns == NULL) {
10802 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10803 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010804 xmlSchemaPIllegalAttrErr(ctxt,
10805 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10806 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010807 }
10808 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010809 xmlSchemaPIllegalAttrErr(ctxt,
10810 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10811 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010812 }
10813 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010814 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010815
10816 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010817
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010818 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010819 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010820 */
10821 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010822 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10823 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010824 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010825 XML_SCHEMAP_S4S_ATTR_MISSING,
10826 NULL, node, "base", NULL);
10827 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010828 /*
10829 * And now for the children...
10830 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010831 child = node->children;
10832 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010833 /*
10834 * Add the annotation to the type ancestor.
10835 */
10836 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10837 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010838 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010839 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010840 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10841 /*
10842 * Corresponds to <complexType><complexContent><extension>... and:
10843 *
10844 * Model groups <all>, <choice>, <sequence> and <group>.
10845 */
10846 if (IS_SCHEMA(child, "all")) {
10847 type->subtypes = (xmlSchemaTypePtr)
10848 xmlSchemaParseModelGroup(ctxt, schema,
10849 child, XML_SCHEMA_TYPE_ALL, 1);
10850 child = child->next;
10851 } else if (IS_SCHEMA(child, "choice")) {
10852 type->subtypes = (xmlSchemaTypePtr)
10853 xmlSchemaParseModelGroup(ctxt, schema,
10854 child, XML_SCHEMA_TYPE_CHOICE, 1);
10855 child = child->next;
10856 } else if (IS_SCHEMA(child, "sequence")) {
10857 type->subtypes = (xmlSchemaTypePtr)
10858 xmlSchemaParseModelGroup(ctxt, schema,
10859 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10860 child = child->next;
10861 } else if (IS_SCHEMA(child, "group")) {
10862 type->subtypes = (xmlSchemaTypePtr)
10863 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10864 child = child->next;
10865 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010866 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010867 if (child != NULL) {
10868 /*
10869 * Attribute uses/declarations.
10870 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010871 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010872 /*
10873 * Attribute wildcard.
10874 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010875 if (IS_SCHEMA(child, "anyAttribute")) {
10876 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010877 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10878 child = child->next;
10879 }
10880 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010881 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010882 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10883 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010884 xmlSchemaPContentErr(ctxt,
10885 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010886 NULL, NULL, node, child, NULL,
10887 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010888 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010889 } else {
10890 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010891 xmlSchemaPContentErr(ctxt,
10892 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010893 NULL, NULL, node, child, NULL,
10894 "(annotation?, ((attribute | attributeGroup)*, "
10895 "anyAttribute?))");
10896 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010897 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010898 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010899}
10900
10901/**
10902 * xmlSchemaParseSimpleContent:
10903 * @ctxt: a schema validation context
10904 * @schema: the schema being built
10905 * @node: a subtree containing XML Schema informations
10906 *
10907 * parse a XML schema SimpleContent definition
10908 * *WARNING* this interface is highly subject to change
10909 *
10910 * Returns the type definition or NULL in case of error
10911 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010912static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010913xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010914 xmlSchemaPtr schema, xmlNodePtr node,
10915 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000010916{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010917 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010918 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010919 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010920
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010921 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
10922 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010923 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010924 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010925 /* Not a component, don't create it. */
10926 type = ctxt->ctxtType;
10927 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10928 /*
10929 * Check for illegal attributes.
10930 */
10931 attr = node->properties;
10932 while (attr != NULL) {
10933 if (attr->ns == NULL) {
10934 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010935 xmlSchemaPIllegalAttrErr(ctxt,
10936 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10937 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010938 }
10939 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010940 xmlSchemaPIllegalAttrErr(ctxt,
10941 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10942 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010943 }
10944 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010945 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010946
10947 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010948
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010949 /*
10950 * And now for the children...
10951 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010952 child = node->children;
10953 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010954 /*
10955 * Add the annotation to the complex type ancestor.
10956 */
10957 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10958 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010959 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010960 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010961 if (child == NULL) {
10962 xmlSchemaPContentErr(ctxt,
10963 XML_SCHEMAP_S4S_ELEM_MISSING,
10964 NULL, NULL, node, NULL, NULL,
10965 "(annotation?, (restriction | extension))");
10966 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010967 if (child == NULL) {
10968 xmlSchemaPContentErr(ctxt,
10969 XML_SCHEMAP_S4S_ELEM_MISSING,
10970 NULL, NULL, node, NULL, NULL,
10971 "(annotation?, (restriction | extension))");
10972 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010973 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010974 xmlSchemaParseRestriction(ctxt, schema, child,
10975 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010976 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010977 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010978 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010979 xmlSchemaParseExtension(ctxt, schema, child,
10980 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010981 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010982 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010983 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010984 if (child != NULL) {
10985 xmlSchemaPContentErr(ctxt,
10986 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010987 NULL, NULL, node, child, NULL,
10988 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010989 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010990 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010991}
10992
10993/**
10994 * xmlSchemaParseComplexContent:
10995 * @ctxt: a schema validation context
10996 * @schema: the schema being built
10997 * @node: a subtree containing XML Schema informations
10998 *
10999 * parse a XML schema ComplexContent definition
11000 * *WARNING* this interface is highly subject to change
11001 *
11002 * Returns the type definition or NULL in case of error
11003 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011004static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011005xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011006 xmlSchemaPtr schema, xmlNodePtr node,
11007 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000011008{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011009 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011010 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011011 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011012
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011013 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11014 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011015 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011016 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011017 /* Not a component, don't create it. */
11018 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011019 /*
11020 * Check for illegal attributes.
11021 */
11022 attr = node->properties;
11023 while (attr != NULL) {
11024 if (attr->ns == NULL) {
11025 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011026 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011027 {
11028 xmlSchemaPIllegalAttrErr(ctxt,
11029 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
11030 NULL, NULL, attr);
11031 }
11032 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11033 xmlSchemaPIllegalAttrErr(ctxt,
11034 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
11035 NULL, NULL, attr);
11036 }
11037 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011038 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011039
11040 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
11041
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011042 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011043 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011044 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011045 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
11046 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
11047 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011048 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011049 child = node->children;
11050 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011051 /*
11052 * Add the annotation to the complex type ancestor.
11053 */
11054 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11055 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011056 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011057 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011058 if (child == NULL) {
11059 xmlSchemaPContentErr(ctxt,
11060 XML_SCHEMAP_S4S_ELEM_MISSING,
11061 NULL, NULL, node, NULL,
11062 NULL, "(annotation?, (restriction | extension))");
11063 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011064 if (child == NULL) {
11065 xmlSchemaPContentErr(ctxt,
11066 XML_SCHEMAP_S4S_ELEM_MISSING,
11067 NULL, NULL, node, NULL,
11068 NULL, "(annotation?, (restriction | extension))");
11069 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011070 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011071 xmlSchemaParseRestriction(ctxt, schema, child,
11072 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011073 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011074 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011075 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011076 xmlSchemaParseExtension(ctxt, schema, child,
11077 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011078 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011079 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011080 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011081 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011082 xmlSchemaPContentErr(ctxt,
11083 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11084 NULL, NULL, node, child,
11085 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000011086 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011087 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000011088}
11089
11090/**
11091 * xmlSchemaParseComplexType:
11092 * @ctxt: a schema validation context
11093 * @schema: the schema being built
11094 * @node: a subtree containing XML Schema informations
11095 *
11096 * parse a XML schema Complex Type definition
11097 * *WARNING* this interface is highly subject to change
11098 *
11099 * Returns the type definition or NULL in case of error
11100 */
11101static xmlSchemaTypePtr
11102xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000011103 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000011104{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011105 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000011106 xmlNodePtr child = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011107 const xmlChar *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011108 xmlAttrPtr attr;
11109 const xmlChar *attrValue;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011110#ifdef ENABLE_NAMED_LOCALS
Daniel Veillard1a380b82004-10-21 16:00:06 +000011111 char buf[40];
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011112#endif
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011113 int final = 0, block = 0, hasRestrictionOrExtension = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000011114
Daniel Veillard4255d502002-04-16 15:50:10 +000011115
11116 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11117 return (NULL);
11118
Daniel Veillard01fa6152004-06-29 17:04:39 +000011119 ctxtType = ctxt->ctxtType;
11120
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011121 if (topLevel) {
11122 attr = xmlSchemaGetPropNode(node, "name");
11123 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011124 xmlSchemaPMissingAttrErr(ctxt,
11125 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011126 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011127 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011128 NULL, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011129 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
11130 return (NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011131 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011132 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011133
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011134 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011135 /*
11136 * Parse as local complex type definition.
11137 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011138#ifdef ENABLE_NAMED_LOCALS
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000011139 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011140 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf,
11141 ctxt->targetNamespace, node, 0);
11142#else
11143 type = xmlSchemaAddType(ctxt, schema, NULL,
11144 ctxt->targetNamespace, node, 0);
11145#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011146 if (type == NULL)
11147 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011148 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011149 type->node = node;
11150 type->type = XML_SCHEMA_TYPE_COMPLEX;
11151 /*
11152 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011153 */
11154 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011155 /*
11156 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011157 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011158 type = xmlSchemaAddType(ctxt, schema, name, ctxt->targetNamespace,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011159 node, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011160 if (type == NULL)
11161 return (NULL);
11162 type->node = node;
11163 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011164 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000011165 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011166 type->targetNamespace = ctxt->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011167 /*
11168 * Handle attributes.
11169 */
11170 attr = node->properties;
11171 while (attr != NULL) {
11172 if (attr->ns == NULL) {
11173 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
11174 /*
11175 * Attribute "id".
11176 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000011177 xmlSchemaPValAttrID(ctxt, NULL, type, node,
11178 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011179 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
11180 /*
11181 * Attribute "mixed".
11182 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011183 if (xmlSchemaPGetBoolNodeValue(ctxt, NULL, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011184 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011185 type->flags |= XML_SCHEMAS_TYPE_MIXED;
11186 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011187 /*
11188 * Attributes of global complex type definitions.
11189 */
11190 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
11191 /* Pass. */
11192 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
11193 /*
11194 * Attribute "abstract".
11195 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011196 if (xmlSchemaPGetBoolNodeValue(ctxt, NULL, type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011197 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011198 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
11199 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
11200 /*
11201 * Attribute "final".
11202 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011203 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011204 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011205 if (xmlSchemaPValAttrBlockFinal(attrValue,
11206 &(type->flags),
11207 -1,
11208 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
11209 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
11210 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011211 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011212 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011213 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011214 type, (xmlNodePtr) attr, NULL,
11215 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011216 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011217 } else
11218 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011219 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
11220 /*
11221 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011222 */
11223 attrValue = xmlSchemaGetNodeContent(ctxt,
11224 (xmlNodePtr) attr);
11225 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011226 -1,
11227 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011228 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011229 -1, -1, -1) != 0) {
11230 xmlSchemaPSimpleTypeErr(ctxt,
11231 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011232 type, (xmlNodePtr) attr, NULL,
11233 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011234 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011235 } else
11236 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011237 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011238 xmlSchemaPIllegalAttrErr(ctxt,
11239 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011240 NULL, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011241 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011242 } else {
11243 xmlSchemaPIllegalAttrErr(ctxt,
11244 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011245 NULL, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011246 }
11247 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011248 xmlSchemaPIllegalAttrErr(ctxt,
11249 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011250 NULL, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011251 }
11252 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011253 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011254 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000011255 /*
11256 * Apply default "block" values.
11257 */
11258 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
11259 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
11260 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
11261 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
11262 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011263 if (! final) {
11264 /*
11265 * Apply default "block" values.
11266 */
11267 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
11268 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
11269 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
11270 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
11271 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011272 /*
11273 * And now for the children...
11274 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011275 child = node->children;
11276 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011277 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
11278 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011279 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011280 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000011281 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011282 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011283 * <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011284 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011285 * Specifying mixed='true' when the <simpleContent>
11286 * alternative is chosen has no effect
11287 */
William M. Bracke7091952004-05-11 15:09:58 +000011288 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
11289 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011290 xmlSchemaParseSimpleContent(ctxt, schema, child,
11291 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011292 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011293 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011294 /*
11295 * <complexType><complexContent>...
11296 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011297 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011298 xmlSchemaParseComplexContent(ctxt, schema, child,
11299 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011300 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000011301 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011302 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011303 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
11304 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011305 * SPEC
11306 * "...the third alternative (neither <simpleContent> nor
11307 * <complexContent>) is chosen. This case is understood as shorthand
11308 * for complex content restricting the ·ur-type definition·, and the
11309 * details of the mappings should be modified as necessary.
11310 */
11311 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11312 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011313 /*
11314 * Parse model groups.
11315 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011316 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011317 type->subtypes = (xmlSchemaTypePtr)
11318 xmlSchemaParseModelGroup(ctxt, schema, child,
11319 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011320 child = child->next;
11321 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011322 type->subtypes = (xmlSchemaTypePtr)
11323 xmlSchemaParseModelGroup(ctxt, schema, child,
11324 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011325 child = child->next;
11326 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011327 type->subtypes = (xmlSchemaTypePtr)
11328 xmlSchemaParseModelGroup(ctxt, schema, child,
11329 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011330 child = child->next;
11331 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011332 type->subtypes = (xmlSchemaTypePtr)
11333 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011334 child = child->next;
11335 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011336 /*
11337 * Parse attribute decls/refs.
11338 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011339 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011340 /*
11341 * Parse attribute wildcard.
11342 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011343 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011344 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
11345 child = child->next;
11346 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011347 }
11348 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011349 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011350 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011351 NULL, type, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011352 NULL, "(annotation?, (simpleContent | complexContent | "
11353 "((group | all | choice | sequence)?, ((attribute | "
11354 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000011355 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011356 /*
11357 * REDEFINE: SPEC src-redefine (5)
11358 */
11359 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
11360 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11361 NULL, NULL, node, "This is a redefinition, thus the "
11362 "<complexType> must have a <restriction> or <extension> "
11363 "grand-child", NULL);
11364 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011365 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000011366 return (type);
11367}
11368
Daniel Veillard4255d502002-04-16 15:50:10 +000011369/************************************************************************
11370 * *
11371 * Validating using Schemas *
11372 * *
11373 ************************************************************************/
11374
11375/************************************************************************
11376 * *
11377 * Reading/Writing Schemas *
11378 * *
11379 ************************************************************************/
11380
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011381#if 0 /* Will be enabled if it is clear what options are needed. */
11382/**
11383 * xmlSchemaParserCtxtSetOptions:
11384 * @ctxt: a schema parser context
11385 * @options: a combination of xmlSchemaParserOption
11386 *
11387 * Sets the options to be used during the parse.
11388 *
11389 * Returns 0 in case of success, -1 in case of an
11390 * API error.
11391 */
11392static int
11393xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
11394 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011395
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011396{
11397 int i;
11398
11399 if (ctxt == NULL)
11400 return (-1);
11401 /*
11402 * WARNING: Change the start value if adding to the
11403 * xmlSchemaParseOption.
11404 */
11405 for (i = 1; i < (int) sizeof(int) * 8; i++) {
11406 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011407 return (-1);
11408 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011409 }
11410 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011411 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011412}
11413
11414/**
11415 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011416 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011417 *
11418 * Returns the option combination of the parser context.
11419 */
11420static int
11421xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011422
11423{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011424 if (ctxt == NULL)
11425 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011426 else
11427 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011428}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011429#endif
11430
Daniel Veillard4255d502002-04-16 15:50:10 +000011431/**
11432 * xmlSchemaNewParserCtxt:
11433 * @URL: the location of the schema
11434 *
11435 * Create an XML Schemas parse context for that file/resource expected
11436 * to contain an XML Schemas file.
11437 *
11438 * Returns the parser context or NULL in case of error
11439 */
11440xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011441xmlSchemaNewParserCtxt(const char *URL)
11442{
Daniel Veillard4255d502002-04-16 15:50:10 +000011443 xmlSchemaParserCtxtPtr ret;
11444
11445 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011446 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011447
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011448 ret = xmlSchemaParserCtxtCreate();
11449 if (ret == NULL)
11450 return(NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011451 ret->dict = xmlDictCreate();
11452 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011453 return (ret);
11454}
11455
11456/**
Daniel Veillard6045c902002-10-09 21:13:59 +000011457 * xmlSchemaNewMemParserCtxt:
11458 * @buffer: a pointer to a char array containing the schemas
11459 * @size: the size of the array
11460 *
11461 * Create an XML Schemas parse context for that memory buffer expected
11462 * to contain an XML Schemas file.
11463 *
11464 * Returns the parser context or NULL in case of error
11465 */
11466xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011467xmlSchemaNewMemParserCtxt(const char *buffer, int size)
11468{
Daniel Veillard6045c902002-10-09 21:13:59 +000011469 xmlSchemaParserCtxtPtr ret;
11470
11471 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011472 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011473 ret = xmlSchemaParserCtxtCreate();
11474 if (ret == NULL)
11475 return(NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000011476 ret->buffer = buffer;
11477 ret->size = size;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011478 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000011479 return (ret);
11480}
11481
11482/**
Daniel Veillard9d751502003-10-29 13:21:47 +000011483 * xmlSchemaNewDocParserCtxt:
11484 * @doc: a preparsed document tree
11485 *
11486 * Create an XML Schemas parse context for that document.
11487 * NB. The document may be modified during the parsing process.
11488 *
11489 * Returns the parser context or NULL in case of error
11490 */
11491xmlSchemaParserCtxtPtr
11492xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
11493{
11494 xmlSchemaParserCtxtPtr ret;
11495
11496 if (doc == NULL)
11497 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011498 ret = xmlSchemaParserCtxtCreate();
11499 if (ret == NULL)
11500 return(NULL);
Daniel Veillard9d751502003-10-29 13:21:47 +000011501 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000011502 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000011503 /* The application has responsibility for the document */
11504 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000011505
11506 return (ret);
11507}
11508
11509/**
Daniel Veillard4255d502002-04-16 15:50:10 +000011510 * xmlSchemaFreeParserCtxt:
11511 * @ctxt: the schema parser context
11512 *
11513 * Free the resources associated to the schema parser context
11514 */
11515void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011516xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
11517{
Daniel Veillard4255d502002-04-16 15:50:10 +000011518 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011519 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000011520 if (ctxt->doc != NULL && !ctxt->preserve)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011521 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011522 if (ctxt->vctxt != NULL) {
11523 xmlSchemaFreeValidCtxt(ctxt->vctxt);
11524 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011525 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
11526 xmlSchemaConstructionCtxtFree(ctxt->constructor);
11527 ctxt->constructor = NULL;
11528 ctxt->ownsConstructor = 0;
11529 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011530 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000011531 xmlFree(ctxt);
11532}
11533
11534/************************************************************************
11535 * *
11536 * Building the content models *
11537 * *
11538 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011539
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011540static void
11541xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011542 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011543{
Daniel Veillarda980bef2005-07-18 21:34:03 +000011544 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011545 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011546 xmlSchemaSubstGroupPtr substGroup;
11547 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011548
11549 elemDecl = (xmlSchemaElementPtr) particle->children;
11550 /*
11551 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011552 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011553 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000011554 if (end == NULL)
11555 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011556 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011557 if (substGroup == NULL) {
11558 xmlSchemaPErr(pctxt, GET_NODE(particle),
11559 XML_SCHEMAP_INTERNAL,
11560 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
11561 "declaration is marked having a subst. group but none "
11562 "available.\n", elemDecl->name, NULL);
11563 return;
11564 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000011565 if (counter >= 0) {
11566 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011567 * NOTE that we put the declaration in, even if it's abstract.
11568 * However, an error will be raised during *validation* if an element
11569 * information item shall be validated against an abstract element
11570 * declaration.
Daniel Veillarda980bef2005-07-18 21:34:03 +000011571 */
11572 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
11573 xmlAutomataNewTransition2(pctxt->am, tmp, end,
11574 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11575 /*
11576 * Add subst. group members.
11577 */
11578 for (i = 0; i < substGroup->members->nbItems; i++) {
11579 member = (xmlSchemaElementPtr) substGroup->members->items[i];
11580 xmlAutomataNewTransition2(pctxt->am, tmp, end,
11581 member->name, member->targetNamespace, member);
11582 }
11583 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011584 /*
11585 * NOTE that we put the declaration in, even if it's abstract,
11586 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011587 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011588 xmlAutomataNewTransition2(pctxt->am,
11589 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011590 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
11591 /*
11592 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011593 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011594 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011595 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000011596 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
11597 member->name, member->targetNamespace,
11598 1, 1, member);
11599 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011600 }
11601 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011602 xmlAutomataStatePtr hop;
11603 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11604 UNBOUNDED : particle->maxOccurs - 1;
11605 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
11606
11607 counter =
11608 xmlAutomataNewCounter(pctxt->am, minOccurs,
11609 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011610 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011611
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011612 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011613 xmlAutomataNewTransition2(pctxt->am,
11614 start, NULL,
11615 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011616 hop);
11617 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000011618 * Add subst. group members.
11619 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011620 for (i = 0; i < substGroup->members->nbItems; i++) {
11621 member = (xmlSchemaElementPtr) substGroup->members->items[i];
11622 xmlAutomataNewEpsilon(pctxt->am,
11623 xmlAutomataNewTransition2(pctxt->am,
11624 start, NULL,
11625 member->name, member->targetNamespace, member),
11626 hop);
11627 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011628 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
11629 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
11630 }
11631 if (particle->minOccurs == 0)
11632 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011633 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011634}
11635
11636static void
11637xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
11638 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011639{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011640 if (((xmlSchemaElementPtr) particle->children)->flags &
11641 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011642 /*
11643 * Substitution groups.
11644 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000011645 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011646 } else {
11647 xmlSchemaElementPtr elemDecl;
11648 xmlAutomataStatePtr start;
11649
11650 elemDecl = (xmlSchemaElementPtr) particle->children;
11651
11652 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011653 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011654 if (particle->maxOccurs == 1) {
11655 start = ctxt->state;
11656 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011657 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11658 } else if ((particle->maxOccurs >= UNBOUNDED) &&
11659 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011660 /* Special case. */
11661 start = ctxt->state;
11662 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11663 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011664 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011665 } else {
11666 int counter;
11667 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11668 UNBOUNDED : particle->maxOccurs - 1;
11669 int minOccurs = particle->minOccurs < 1 ?
11670 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011671
11672 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011673 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11674 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11675 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11676 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
11677 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
11678 NULL, counter);
11679 }
11680 if (particle->minOccurs == 0)
11681 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
11682 }
11683}
11684
Daniel Veillard4255d502002-04-16 15:50:10 +000011685/**
11686 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011687 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011688 * @particle: the particle component
11689 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011690 *
11691 * Generate the automata sequence needed for that type
11692 */
11693static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011694xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011695 xmlSchemaParticlePtr particle)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011696{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011697 if (particle == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011698 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011699 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011700 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011701 if (particle->children == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011702 PERROR_INT("xmlSchemaBuildAContentModel", "no term on particle");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011703 return;
11704 }
11705
11706 switch (particle->children->type) {
11707 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011708 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011709 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011710 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011711
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011712 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011713
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011714 start = pctxt->state;
11715 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011716
11717 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011718 if (wild->any == 1) {
11719 /*
11720 * We need to add both transitions:
11721 *
11722 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011723 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011724 pctxt->state =
11725 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011726 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011727 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011728 /*
11729 * 2. the {"*"} for elements in no namespace.
11730 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011731 pctxt->state =
11732 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011733 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011734 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011735
11736 } else if (wild->nsSet != NULL) {
11737 ns = wild->nsSet;
11738 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011739 pctxt->state = start;
11740 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
11741 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
11742 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011743 ns = ns->next;
11744 } while (ns != NULL);
11745
11746 } else if (wild->negNsSet != NULL) {
Daniel Veillard6e65e152005-08-09 11:09:52 +000011747 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
11748 start, end, BAD_CAST "*", wild->negNsSet->value,
11749 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011750 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011751 } else {
11752 int counter;
11753 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011754 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011755 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011756 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011757 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011758
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011759 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
11760 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011761 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011762 pctxt->state =
11763 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011764 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011765 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
11766 pctxt->state =
11767 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011768 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011769 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011770 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011771 ns = wild->nsSet;
11772 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011773 pctxt->state =
11774 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011775 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011776 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011777 ns = ns->next;
11778 } while (ns != NULL);
11779
11780 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011781 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000011782 start, hop, BAD_CAST "*", wild->negNsSet->value,
11783 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011784 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011785 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
11786 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011787 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011788 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011789 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011790 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011791 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011792 break;
11793 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011794 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011795 xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011796 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011797 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011798 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011799
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011800 /*
11801 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011802 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011803 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011804 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11805 sub = particle->children->children;
11806 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011807 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011808 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011809 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011810 }
11811 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011812 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011813
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011814 if (particle->maxOccurs >= UNBOUNDED) {
11815 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011816 xmlAutomataStatePtr tmp;
11817 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011818
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011819 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011820 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011821 oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011822
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011823 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011824 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011825
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011826 sub = particle->children->children;
11827 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011828 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011829 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011830 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011831 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011832 tmp = pctxt->state;
11833 xmlAutomataNewCountedTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011834 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011835 pctxt->state =
11836 xmlAutomataNewCounterTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011837 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011838
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011839 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011840 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillardafc05b62005-07-17 06:11:19 +000011841 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011842 oldstate = pctxt->state;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011843
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011844 sub = particle->children->children;
11845 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011846 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011847 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011848 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011849 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011850 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011851 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011852 /*
11853 * epsilon needed to block previous trans from
11854 * being allowed to enter back from another
11855 * construct
11856 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011857 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
11858 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011859 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011860 xmlAutomataNewEpsilon(pctxt->am,
11861 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011862 }
11863 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011864 } else if ((particle->maxOccurs > 1)
11865 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011866 xmlAutomataStatePtr tmp;
11867 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011868
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011869 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011870 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011871 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011872
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011873 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011874 particle->minOccurs - 1,
11875 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011876
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011877 sub = particle->children->children;
11878 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011879 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011880 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011881 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011882 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011883 tmp = pctxt->state;
11884 xmlAutomataNewCountedTrans(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011885 tmp, oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011886 pctxt->state =
11887 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011888 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011889 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011890 xmlAutomataNewEpsilon(pctxt->am,
11891 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011892 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011893 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011894 sub = particle->children->children;
11895 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011896 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011897 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011898 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011899 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011900 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011901 xmlAutomataNewEpsilon(pctxt->am, oldstate,
11902 pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011903 }
11904 }
11905 }
11906 break;
11907 }
11908 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011909 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011910 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011911
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011912 start = pctxt->state;
11913 end = xmlAutomataNewState(pctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011914
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011915 /*
11916 * iterate over the subtypes and remerge the end with an
11917 * epsilon transition
11918 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011919 if (particle->maxOccurs == 1) {
11920 sub = particle->children->children;
11921 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011922 pctxt->state = start;
11923 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011924 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011925 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011926 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011927 }
11928 } else {
11929 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011930 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011931 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11932 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011933 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011934 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011935
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011936 /*
11937 * use a counter to keep track of the number of transtions
11938 * which went through the choice.
11939 */
11940 counter =
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011941 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
11942 hop = xmlAutomataNewState(pctxt->am);
11943 base = xmlAutomataNewState(pctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011944
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011945 sub = particle->children->children;
11946 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011947 pctxt->state = base;
11948 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000011949 (xmlSchemaParticlePtr) sub);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011950 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011951 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000011952 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011953 xmlAutomataNewEpsilon(pctxt->am, start, base);
11954 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
11955 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011956 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011957 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011958 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011959 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011960 pctxt->state = end;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011961 break;
11962 }
11963 case XML_SCHEMA_TYPE_ALL:{
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +000011964 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011965 xmlSchemaParticlePtr sub;
11966 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011967 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011968
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011969 sub = (xmlSchemaParticlePtr) particle->children->children;
11970 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011971 break;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011972 start = pctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011973 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011974 pctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011975
11976 elemDecl = (xmlSchemaElementPtr) sub->children;
11977 if (elemDecl == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011978 PERROR_INT("xmlSchemaBuildAContentModel",
11979 "<element> particle has no term");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011980 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011981 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011982 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011983 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011984 * {particles} of the group must be 0 or 1; this is
11985 * already ensured during the parse of the content of
11986 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011987 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000011988 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
11989 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011990
Daniel Veillarda980bef2005-07-18 21:34:03 +000011991 /*
11992 * This is an abstract group, we need to share
11993 * the same counter for all the element transitions
11994 * derived from the group
11995 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011996 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011997 sub->minOccurs, sub->maxOccurs);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011998 xmlSchemaBuildContentModelForSubstGroup(pctxt,
11999 sub, counter, pctxt->state);
Daniel Veillarda980bef2005-07-18 21:34:03 +000012000 } else {
12001 if ((sub->minOccurs == 1) &&
12002 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012003 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
12004 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012005 elemDecl->name,
12006 elemDecl->targetNamespace,
12007 1, 1, elemDecl);
12008 } else if ((sub->minOccurs == 0) &&
12009 (sub->maxOccurs == 1)) {
12010
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012011 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
12012 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000012013 elemDecl->name,
12014 elemDecl->targetNamespace,
12015 0,
12016 1,
12017 elemDecl);
12018 }
12019 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012020 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012021 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012022 lax = particle->minOccurs == 0;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012023 pctxt->state =
12024 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012025 break;
12026 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012027 case XML_SCHEMA_TYPE_GROUP:
12028 /*
12029 * If we hit a model group definition, then this means that
12030 * it was empty, thus was not substituted for the containing
12031 * model group. Just do nothing in this case.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012032 * TODO: But the group should be substituted and not occur at
12033 * all in the content model at this point. Fix this.
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000012034 */
12035 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012036 default:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012037 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
12038 "xmlSchemaBuildAContentModel",
12039 "found unexpected term of type '%s' in content model",
12040 xmlSchemaCompTypeToString(particle->children->type), NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012041 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012042 }
12043}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012044
Daniel Veillard4255d502002-04-16 15:50:10 +000012045/**
12046 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000012047 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012048 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000012049 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000012050 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012051 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000012052 */
12053static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012054xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012055 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012056{
Daniel Veillard4255d502002-04-16 15:50:10 +000012057 xmlAutomataStatePtr start;
12058
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012059 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
12060 (type->contModel != NULL) ||
12061 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
12062 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012063 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012064
12065#ifdef DEBUG_CONTENT
12066 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012067 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000012068#endif
12069
Daniel Veillard4255d502002-04-16 15:50:10 +000012070 ctxt->am = xmlNewAutomata();
12071 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012072 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012073 "Cannot create automata for complex type %s\n", type->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012074 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000012075 }
12076 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012077 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes);
Daniel Veillard4255d502002-04-16 15:50:10 +000012078 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012079 type->contModel = xmlAutomataCompile(ctxt->am);
12080 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012081 xmlSchemaPCustomErr(ctxt,
12082 XML_SCHEMAP_INTERNAL,
12083 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012084 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012085 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012086 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012087 XML_SCHEMAP_NOT_DETERMINISTIC,
12088 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012089 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012090 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000012091 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000012092#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012093 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012094 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012095 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000012096#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000012097 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000012098 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000012099 xmlFreeAutomata(ctxt->am);
12100 ctxt->am = NULL;
12101}
12102
12103/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012104 * xmlSchemaResolveElementReferences:
Daniel Veillard4255d502002-04-16 15:50:10 +000012105 * @elem: the schema element context
12106 * @ctxt: the schema parser context
12107 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000012108 * Resolves the references of an element declaration
12109 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012110 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000012111 */
12112static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012113xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
12114 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000012115{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012116 if ((ctxt == NULL) || (elemDecl == NULL) ||
12117 ((elemDecl != NULL) &&
12118 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000012119 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012120 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012121
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012122 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012123 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012124
12125 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012126 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012127 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012128 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012129 elemDecl->namedTypeNs);
12130 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012131 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012132 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012133 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012134 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012135 XML_SCHEMA_TYPE_BASIC, "type definition");
12136 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012137 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012138 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012139 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012140 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012141
Daniel Veillardc0826a72004-08-10 14:17:33 +000012142 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012143 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012144 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000012145 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012146 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
12147 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012148 if (substHead == NULL) {
12149 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012150 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012151 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012152 "substitutionGroup", elemDecl->substGroup,
12153 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012154 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012155 xmlSchemaResolveElementReferences(substHead, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012156 /*
12157 * Set the "substitution group affiliation".
12158 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012159 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012160 SUBST_GROUP_AFF(elemDecl) = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012161 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012162 * The type definitions is set to:
12163 * SPEC "...the {type definition} of the element
12164 * declaration ·resolved· to by the ·actual value·
12165 * of the substitutionGroup [attribute], if present"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012166 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012167 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012168 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012169 }
12170 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012171 /*
12172 * SPEC "The definition of anyType serves as the default type definition
12173 * for element declarations whose XML representation does not specify one."
12174 */
12175 if ((elemDecl->subtypes == NULL) &&
12176 (elemDecl->namedType == NULL) &&
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012177 (elemDecl->substGroup == NULL))
12178 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000012179}
12180
12181/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012182 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000012183 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012184 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000012185 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012186 * Checks and builds the "member type definitions" property of the union
12187 * simple type. This handles part (1), part (2) is done in
12188 * xmlSchemaFinishMemberTypeDefinitionsProperty()
12189 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000012190 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000012191 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012192static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012193xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
12194 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000012195{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012196
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012197 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012198 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000012199
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012200 /*
12201 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
12202 * define the explicit members as the type definitions ·resolved·
12203 * to by the items in the ·actual value· of the memberTypes [attribute],
12204 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012205 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000012206 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012207 /*
12208 * Resolve references.
12209 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012210 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012211 lastLink = NULL;
12212 while (link != NULL) {
12213 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012214
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012215 name = ((xmlSchemaQNameRefPtr) link->type)->name;
12216 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
12217
12218 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
12219 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
12220 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012221 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012222 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
12223 /*
12224 * Remove the member type link.
12225 */
12226 if (lastLink == NULL)
12227 type->memberTypes = link->next;
12228 else
12229 lastLink->next = link->next;
12230 newLink = link;
12231 link = link->next;
12232 xmlFree(newLink);
12233 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012234 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012235 lastLink = link;
12236 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012237 }
12238 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012239 /*
12240 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012241 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012242 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012243 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012244 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
12245 if (link == NULL) {
12246 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
12247 return (-1);
12248 }
12249 link->type = memberType;
12250 link->next = NULL;
12251 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012252 type->memberTypes = link;
12253 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000012254 lastLink->next = link;
12255 lastLink = link;
12256 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012257 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012258 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000012259}
12260
Daniel Veillard4255d502002-04-16 15:50:10 +000012261/**
Daniel Veillard3646d642004-06-02 19:19:14 +000012262 * xmlSchemaIsDerivedFromBuiltInType:
12263 * @ctxt: the schema parser context
12264 * @type: the type definition
12265 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012266 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012267 *
12268 * Returns 1 if the type has the given value type, or
12269 * is derived from such a type.
12270 */
William M. Brack803812b2004-06-03 02:11:24 +000012271static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012272xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000012273{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012274 if (type == NULL)
12275 return (0);
12276 if (IS_COMPLEX_TYPE(type))
12277 return (0);
12278 if (type->type == XML_SCHEMA_TYPE_BASIC) {
12279 if (type->builtInType == valType)
12280 return(1);
12281 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
12282 (type->builtInType == XML_SCHEMAS_ANYTYPE))
12283 return (0);
12284 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
12285 } else
12286 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000012287
12288 return (0);
12289}
12290
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012291#if 0
12292/**
12293 * xmlSchemaIsDerivedFromBuiltInType:
12294 * @ctxt: the schema parser context
12295 * @type: the type definition
12296 * @valType: the value type
12297 *
12298 *
12299 * Returns 1 if the type has the given value type, or
12300 * is derived from such a type.
12301 */
12302static int
12303xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
12304{
12305 if (type == NULL)
12306 return (0);
12307 if (IS_COMPLEX_TYPE(type))
12308 return (0);
12309 if (type->type == XML_SCHEMA_TYPE_BASIC) {
12310 if (type->builtInType == valType)
12311 return(1);
12312 return (0);
12313 } else
12314 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
12315
12316 return (0);
12317}
12318#endif
12319
12320static xmlSchemaTypePtr
12321xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
12322{
12323 if (type == NULL)
12324 return (NULL);
12325 if (IS_COMPLEX_TYPE(type))
12326 return (NULL);
12327 if (type->type == XML_SCHEMA_TYPE_BASIC)
12328 return(type);
12329 else
12330 return(xmlSchemaQueryBuiltInType(type->subtypes));
12331
12332 return (NULL);
12333}
12334
Daniel Veillard3646d642004-06-02 19:19:14 +000012335/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000012336 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000012337 * @type: the simpleType definition
12338 *
12339 * Returns the primitive type of the given type or
12340 * NULL in case of error.
12341 */
12342static xmlSchemaTypePtr
12343xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
12344{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000012345
Daniel Veillard01fa6152004-06-29 17:04:39 +000012346 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000012347 /*
12348 * Note that anySimpleType is actually not a primitive type
12349 * but we need that here.
12350 */
12351 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
12352 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012353 return (type);
12354 type = type->baseType;
12355 }
12356
12357 return (NULL);
12358}
12359
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000012360#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000012361/**
12362 * xmlSchemaGetBuiltInTypeAncestor:
12363 * @type: the simpleType definition
12364 *
12365 * Returns the primitive type of the given type or
12366 * NULL in case of error.
12367 */
12368static xmlSchemaTypePtr
12369xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
12370{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012371 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000012372 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000012373 while (type != NULL) {
12374 if (type->type == XML_SCHEMA_TYPE_BASIC)
12375 return (type);
12376 type = type->baseType;
12377 }
12378
12379 return (NULL);
12380}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000012381#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000012382
Daniel Veillard01fa6152004-06-29 17:04:39 +000012383/**
Daniel Veillard3646d642004-06-02 19:19:14 +000012384 * xmlSchemaBuildAttributeUsesOwned:
12385 * @ctxt: the schema parser context
12386 * @type: the complex type definition
12387 * @cur: the attribute declaration list
12388 * @lastUse: the top of the attribute use list
12389 *
12390 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012391 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000012392 * xmlSchemaBuildAttributeValidation only.
12393 */
12394static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012395xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012396 int isRestriction,
Daniel Veillard3646d642004-06-02 19:19:14 +000012397 xmlSchemaAttributePtr cur,
12398 xmlSchemaAttributeLinkPtr *uses,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012399 xmlSchemaAttributeLinkPtr *lastUse,
12400 int *hasProhibitions)
Daniel Veillard3646d642004-06-02 19:19:14 +000012401{
12402 xmlSchemaAttributeLinkPtr tmp;
12403 while (cur != NULL) {
12404 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012405 /*
12406 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
12407 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000012408 * <attributeGroup> [children], if any."
12409 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012410 if (xmlSchemaBuildAttributeUsesOwned(ctxt, isRestriction,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012411 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012412 lastUse, hasProhibitions) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012413 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012414 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012415 } else if ((! isRestriction) &&
12416 (cur->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
12417 /*
12418 * Warn about pointless prohibitions when extending.
12419 */
12420 xmlSchemaCustomWarning(ACTXT_CAST ctxt,
12421 XML_SCHEMAP_WARN_ATTR_REDECL_PROH,
12422 cur->node, NULL,
12423 "Attribute use prohibitions are pointless when "
12424 "extending a type", NULL, NULL, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012425 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012426 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000012427 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012428 */
12429 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000012430 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12431 if (tmp == NULL) {
12432 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
12433 return (-1);
12434 }
12435 tmp->attr = cur;
12436 tmp->next = NULL;
12437 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012438 *uses = tmp;
12439 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012440 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012441 *lastUse = tmp;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000012442 if (cur->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
12443 (*hasProhibitions)++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012444 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012445 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012446 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012447 return (0);
12448}
12449
Daniel Veillard50355f02004-06-08 17:52:16 +000012450/**
12451 * xmlSchemaCloneWildcardNsConstraints:
12452 * @ctxt: the schema parser context
12453 * @dest: the destination wildcard
12454 * @source: the source wildcard
12455 *
12456 * Clones the namespace constraints of source
12457 * and assignes them to dest.
12458 * Returns -1 on internal error, 0 otherwise.
12459 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012460static int
12461xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
12462 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012463 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000012464{
12465 xmlSchemaWildcardNsPtr cur, tmp, last;
12466
12467 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012468 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012469 (*dest)->any = source->any;
12470 cur = source->nsSet;
12471 last = NULL;
12472 while (cur != NULL) {
12473 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
12474 if (tmp == NULL)
12475 return(-1);
12476 tmp->value = cur->value;
12477 if (last == NULL)
12478 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012479 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012480 last->next = tmp;
12481 last = tmp;
12482 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012483 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012484 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012485 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000012486 if (source->negNsSet != NULL) {
12487 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12488 if ((*dest)->negNsSet == NULL)
12489 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012490 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012491 } else
12492 (*dest)->negNsSet = NULL;
12493 return(0);
12494}
12495
Daniel Veillard50355f02004-06-08 17:52:16 +000012496/**
12497 * xmlSchemaUnionWildcards:
12498 * @ctxt: the schema parser context
12499 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012500 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012501 *
12502 * Unions the namespace constraints of the given wildcards.
12503 * @completeWild will hold the resulting union.
12504 * Returns a positive error code on failure, -1 in case of an
12505 * internal error, 0 otherwise.
12506 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012507static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012508xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012509 xmlSchemaWildcardPtr completeWild,
12510 xmlSchemaWildcardPtr curWild)
12511{
12512 xmlSchemaWildcardNsPtr cur, curB, tmp;
12513
12514 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012515 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012516 * value.
12517 */
12518 if ((completeWild->any == curWild->any) &&
12519 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12520 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012521
Daniel Veillard3646d642004-06-02 19:19:14 +000012522 if ((completeWild->negNsSet == NULL) ||
12523 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012524
Daniel Veillard3646d642004-06-02 19:19:14 +000012525 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012526 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012527
12528 /*
12529 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012530 */
12531 cur = completeWild->nsSet;
12532 while (cur != NULL) {
12533 found = 0;
12534 curB = curWild->nsSet;
12535 while (curB != NULL) {
12536 if (cur->value == curB->value) {
12537 found = 1;
12538 break;
12539 }
12540 curB = curB->next;
12541 }
12542 if (!found)
12543 break;
12544 cur = cur->next;
12545 }
12546 if (found)
12547 return(0);
12548 } else
12549 return(0);
12550 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012551 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012552 /*
12553 * 2 If either O1 or O2 is any, then any must be the value
12554 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012555 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012556 if (completeWild->any == 0) {
12557 completeWild->any = 1;
12558 if (completeWild->nsSet != NULL) {
12559 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12560 completeWild->nsSet = NULL;
12561 }
12562 if (completeWild->negNsSet != NULL) {
12563 xmlFree(completeWild->negNsSet);
12564 completeWild->negNsSet = NULL;
12565 }
12566 }
Daniel Veillard50355f02004-06-08 17:52:16 +000012567 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012568 }
12569 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012570 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012571 * then the union of those sets must be the value.
12572 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012573 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012574 int found;
12575 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012576
Daniel Veillard3646d642004-06-02 19:19:14 +000012577 cur = curWild->nsSet;
12578 start = completeWild->nsSet;
12579 while (cur != NULL) {
12580 found = 0;
12581 curB = start;
12582 while (curB != NULL) {
12583 if (cur->value == curB->value) {
12584 found = 1;
12585 break;
12586 }
12587 curB = curB->next;
12588 }
12589 if (!found) {
12590 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012591 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012592 return (-1);
12593 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012594 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000012595 completeWild->nsSet = tmp;
12596 }
12597 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012598 }
12599
Daniel Veillard3646d642004-06-02 19:19:14 +000012600 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012601 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012602 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012603 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000012604 * or ·absent·), then a pair of not and ·absent· must be the value.
12605 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012606 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012607 (curWild->negNsSet != NULL) &&
12608 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
12609 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000012610
12611 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012612 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012613 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012614 * 5.
12615 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012616 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012617 (completeWild->negNsSet->value != NULL) &&
12618 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012619 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012620 (curWild->negNsSet->value != NULL) &&
12621 (completeWild->nsSet != NULL))) {
12622
12623 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012624
Daniel Veillard3646d642004-06-02 19:19:14 +000012625 if (completeWild->nsSet != NULL) {
12626 cur = completeWild->nsSet;
12627 curB = curWild->negNsSet;
12628 } else {
12629 cur = curWild->nsSet;
12630 curB = completeWild->negNsSet;
12631 }
12632 nsFound = 0;
12633 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012634 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012635 absentFound = 1;
12636 else if (cur->value == curB->value)
12637 nsFound = 1;
12638 if (nsFound && absentFound)
12639 break;
12640 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012641 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012642
12643 if (nsFound && absentFound) {
12644 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012645 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000012646 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012647 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012648 completeWild->any = 1;
12649 if (completeWild->nsSet != NULL) {
12650 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12651 completeWild->nsSet = NULL;
12652 }
12653 if (completeWild->negNsSet != NULL) {
12654 xmlFree(completeWild->negNsSet);
12655 completeWild->negNsSet = NULL;
12656 }
12657 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012658 /*
12659 * 5.2 If the set S includes the negated namespace name
12660 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000012661 * be the value.
12662 */
12663 if (completeWild->nsSet != NULL) {
12664 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12665 completeWild->nsSet = NULL;
12666 }
12667 if (completeWild->negNsSet == NULL) {
12668 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12669 if (completeWild->negNsSet == NULL)
12670 return (-1);
12671 }
12672 completeWild->negNsSet->value = NULL;
12673 } else if ((!nsFound) && absentFound) {
12674 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012675 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000012676 * namespace name, then the union is not expressible.
12677 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012678 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000012679 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012680 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012681 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012682 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012683 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012684 /*
12685 * 5.4 If the set S does not include either the negated namespace
12686 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012687 * and a namespace name must be the value.
12688 */
12689 if (completeWild->negNsSet == NULL) {
12690 if (completeWild->nsSet != NULL) {
12691 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12692 completeWild->nsSet = NULL;
12693 }
12694 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12695 if (completeWild->negNsSet == NULL)
12696 return (-1);
12697 completeWild->negNsSet->value = curWild->negNsSet->value;
12698 }
12699 }
12700 return (0);
12701 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012702 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012703 * 6.
12704 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012705 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012706 (completeWild->negNsSet->value == NULL) &&
12707 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012708 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012709 (curWild->negNsSet->value == NULL) &&
12710 (completeWild->nsSet != NULL))) {
12711
12712 if (completeWild->nsSet != NULL) {
12713 cur = completeWild->nsSet;
12714 } else {
12715 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012716 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012717 while (cur != NULL) {
12718 if (cur->value == NULL) {
12719 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012720 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012721 * value.
12722 */
12723 completeWild->any = 1;
12724 if (completeWild->nsSet != NULL) {
12725 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12726 completeWild->nsSet = NULL;
12727 }
12728 if (completeWild->negNsSet != NULL) {
12729 xmlFree(completeWild->negNsSet);
12730 completeWild->negNsSet = NULL;
12731 }
12732 return (0);
12733 }
12734 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012735 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012736 if (completeWild->negNsSet == NULL) {
12737 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012738 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012739 * and ·absent· must be the value.
12740 */
12741 if (completeWild->nsSet != NULL) {
12742 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12743 completeWild->nsSet = NULL;
12744 }
12745 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12746 if (completeWild->negNsSet == NULL)
12747 return (-1);
12748 completeWild->negNsSet->value = NULL;
12749 }
12750 return (0);
12751 }
12752 return (0);
12753
12754}
12755
Daniel Veillard50355f02004-06-08 17:52:16 +000012756/**
12757 * xmlSchemaIntersectWildcards:
12758 * @ctxt: the schema parser context
12759 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012760 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012761 *
12762 * Intersects the namespace constraints of the given wildcards.
12763 * @completeWild will hold the resulting intersection.
12764 * Returns a positive error code on failure, -1 in case of an
12765 * internal error, 0 otherwise.
12766 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012767static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012768xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012769 xmlSchemaWildcardPtr completeWild,
12770 xmlSchemaWildcardPtr curWild)
12771{
William M. Brack803812b2004-06-03 02:11:24 +000012772 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012773
12774 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012775 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012776 * value.
12777 */
12778 if ((completeWild->any == curWild->any) &&
12779 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12780 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012781
Daniel Veillard3646d642004-06-02 19:19:14 +000012782 if ((completeWild->negNsSet == NULL) ||
12783 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012784
Daniel Veillard3646d642004-06-02 19:19:14 +000012785 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012786 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012787
12788 /*
12789 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012790 */
12791 cur = completeWild->nsSet;
12792 while (cur != NULL) {
12793 found = 0;
12794 curB = curWild->nsSet;
12795 while (curB != NULL) {
12796 if (cur->value == curB->value) {
12797 found = 1;
12798 break;
12799 }
12800 curB = curB->next;
12801 }
12802 if (!found)
12803 break;
12804 cur = cur->next;
12805 }
12806 if (found)
12807 return(0);
12808 } else
12809 return(0);
12810 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012811 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012812 /*
12813 * 2 If either O1 or O2 is any, then the other must be the value.
12814 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012815 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012816 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012817 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012818 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012819 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012820 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012821 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12822 * name or ·absent·) and the other is a set of (namespace names or
12823 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012824 * the set, minus ·absent· if it was in the set, must be the value.
12825 */
12826 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12827 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12828 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012829
Daniel Veillard3646d642004-06-02 19:19:14 +000012830 if (completeWild->nsSet == NULL) {
12831 neg = completeWild->negNsSet->value;
12832 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12833 return(-1);
12834 } else
12835 neg = curWild->negNsSet->value;
12836 /*
12837 * Remove absent and negated.
12838 */
12839 prev = NULL;
12840 cur = completeWild->nsSet;
12841 while (cur != NULL) {
12842 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012843 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012844 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012845 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012846 prev->next = cur->next;
12847 xmlFree(cur);
12848 break;
12849 }
12850 prev = cur;
12851 cur = cur->next;
12852 }
12853 if (neg != NULL) {
12854 prev = NULL;
12855 cur = completeWild->nsSet;
12856 while (cur != NULL) {
12857 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012858 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012859 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012860 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012861 prev->next = cur->next;
12862 xmlFree(cur);
12863 break;
12864 }
12865 prev = cur;
12866 cur = cur->next;
12867 }
12868 }
12869
12870 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012871 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012872 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012873 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012874 * then the intersection of those sets must be the value.
12875 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012876 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012877 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012878
Daniel Veillard3646d642004-06-02 19:19:14 +000012879 cur = completeWild->nsSet;
12880 prev = NULL;
12881 while (cur != NULL) {
12882 found = 0;
12883 curB = curWild->nsSet;
12884 while (curB != NULL) {
12885 if (cur->value == curB->value) {
12886 found = 1;
12887 break;
12888 }
12889 curB = curB->next;
12890 }
12891 if (!found) {
12892 if (prev == NULL)
12893 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012894 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012895 prev->next = cur->next;
12896 tmp = cur->next;
12897 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012898 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012899 continue;
12900 }
12901 prev = cur;
12902 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012903 }
12904
Daniel Veillard3646d642004-06-02 19:19:14 +000012905 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012906 }
12907 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012908 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012909 */
12910 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012911 (curWild->negNsSet != NULL) &&
12912 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012913 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012914 (curWild->negNsSet->value != NULL)) {
12915
12916 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012917 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012918 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012919 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012920 }
12921 /*
12922 * 6 If the one is a negation of a namespace name and the other
12923 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012924 * of a namespace name must be the value.
12925 */
12926 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12927 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012928 (completeWild->negNsSet->value == NULL)) {
12929 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012930 }
12931 return(0);
12932}
12933
Daniel Veillard50355f02004-06-08 17:52:16 +000012934/**
12935 * xmlSchemaIsWildcardNsConstraintSubset:
12936 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012937 * @sub: the first wildcard
12938 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012939 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012940 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12941 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012942 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012943 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012944 */
12945static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012946xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12947 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012948{
Daniel Veillard50355f02004-06-08 17:52:16 +000012949 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012950 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012951 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012952 if (super->any)
12953 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012954 /*
12955 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12956 * 2.2 super must be a pair of not and the same value.
12957 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012958 if ((sub->negNsSet != NULL) &&
12959 (super->negNsSet != NULL) &&
12960 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012961 return (0);
12962 /*
12963 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012964 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012965 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012966 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012967 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012968 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012969 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012970 xmlSchemaWildcardNsPtr cur, curB;
12971 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012972
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012973 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012974 while (cur != NULL) {
12975 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012976 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012977 while (curB != NULL) {
12978 if (cur->value == curB->value) {
12979 found = 1;
12980 break;
12981 }
12982 curB = curB->next;
12983 }
12984 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012985 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012986 cur = cur->next;
12987 }
12988 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012989 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012990 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012991 xmlSchemaWildcardNsPtr cur;
12992 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012993 * 3.2.2 super must be a pair of not and a namespace name or
12994 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012995 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012996 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012997 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012998 if (cur->value == super->negNsSet->value)
12999 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013000 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013001 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013002 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000013003 }
13004 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013005 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013006}
13007
13008/**
13009 * xmlSchemaBuildCompleteAttributeWildcard:
13010 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013011 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000013012 * @completeWild: the resulting complete wildcard
13013 *
13014 * Returns -1 in case of an internal error, 0 otherwise.
13015 */
13016static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013017xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000013018 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013019 xmlSchemaWildcardPtr *completeWild)
13020{
Daniel Veillard3646d642004-06-02 19:19:14 +000013021 while (attrs != NULL) {
13022 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
13023 xmlSchemaAttributeGroupPtr group;
13024
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013025 group = (xmlSchemaAttributeGroupPtr) attrs;
13026 /*
13027 * Handle attribute group references.
13028 */
13029 if (group->ref != NULL) {
13030 if (group->refItem == NULL) {
13031 /*
13032 * TODO: Should we raise a warning here?
13033 */
13034 /*
13035 * The referenced attribute group definition could not
13036 * be resolved beforehand, so skip.
13037 */
13038 attrs = attrs->next;
13039 continue;
13040 } else
13041 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013042 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013043 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013044 * For every attribute group definition, an intersected wildcard
13045 * will be created (assumed that a wildcard exists on the
13046 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013047 * at all).
13048 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
13049 * that the intersection will be performed only once.
13050 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013051 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
13052 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013053 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000013054 group->attributes, &group->attributeWildcard) == -1)
13055 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013056 }
13057 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013058 }
13059 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000013060 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013061 /*
13062 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013063 *
13064 * Although the complete wildcard might not correspond to any
13065 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000013066 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013067 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
13068 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
13069 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013070 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000013071 completeWild, group->attributeWildcard) == -1)
13072 return (-1);
13073 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013074 (*completeWild)->node = group->attributeWildcard->node;
13075 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000013076 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013077 }
13078 }
13079 attrs = attrs->next;
13080 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013081
13082 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000013083}
13084
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013085static int
13086xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
13087 int *fixed,
13088 const xmlChar **value,
13089 xmlSchemaValPtr *val)
13090{
13091 *fixed = 0;
13092 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013093 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013094 *val = NULL;
13095
13096 if (item->defValue == NULL)
13097 item = item->refDecl;
13098
13099 if (item == NULL)
13100 return (0);
13101
13102 if (item->defValue != NULL) {
13103 *value = item->defValue;
13104 if (val != 0)
13105 *val = item->defVal;
13106 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
13107 *fixed = 1;
13108 return (1);
13109 }
13110 return (0);
13111}
Daniel Veillard3646d642004-06-02 19:19:14 +000013112/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013113 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000013114 * @wild: the wildcard
13115 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013116 *
13117 * Validation Rule: Wildcard allows Namespace Name
13118 * (cvc-wildcard-namespace)
13119 *
Daniel Veillard3646d642004-06-02 19:19:14 +000013120 *
13121 * Returns 1 if the given namespace matches the wildcard,
13122 * 0 otherwise.
13123 */
13124static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013125xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
13126 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000013127{
13128 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013129 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013130
13131 if (wild->any)
13132 return(1);
13133 else if (wild->nsSet != NULL) {
13134 xmlSchemaWildcardNsPtr cur;
13135
13136 cur = wild->nsSet;
13137 while (cur != NULL) {
13138 if (xmlStrEqual(cur->value, ns))
13139 return(1);
13140 cur = cur->next;
13141 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013142 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013143 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013144 return(1);
13145
Daniel Veillard3646d642004-06-02 19:19:14 +000013146 return(0);
13147}
13148
13149/**
13150 * xmlSchemaBuildAttributeValidation:
13151 * @ctxt: the schema parser context
13152 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013153 *
Daniel Veillard3646d642004-06-02 19:19:14 +000013154 *
13155 * Builds the wildcard and the attribute uses on the given complex type.
13156 * Returns -1 if an internal error occurs, 0 otherwise.
13157 */
13158static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013159xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
13160 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000013161{
13162 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013163 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013164 prev = NULL, localUses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000013165 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013166 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013167 xmlChar *str = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013168 int err = 0, hasProhibitions = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000013169
Daniel Veillard01fa6152004-06-29 17:04:39 +000013170 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013171 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013172 * Complex Type Definition with complex content Schema Component.
13173 *
13174 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013175 * TODO: Add checks for absent referenced attribute declarations and
13176 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000013177 */
13178 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013179 PERROR_INT("xmlSchemaBuildAttributeValidation",
13180 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000013181 return (-1);
13182 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013183 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013184 PERROR_INT("xmlSchemaBuildAttributeValidation",
13185 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013186 return (-1);
13187 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013188 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013189 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013190 * Gather attribute uses defined by this type.
13191 */
13192 attrs = type->attributes;
13193 if (attrs != NULL) {
13194 if (xmlSchemaBuildAttributeUsesOwned(pctxt,
13195 WXS_IS_RESTRICTION(type) ? 1 : 0,
13196 attrs,
13197 &localUses, &lastUse, &hasProhibitions) == -1) {
13198 return (-1);
13199 }
13200 /*
13201 * Handle attribute wildcards.
13202 */
13203 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
13204 attrs, &type->attributeWildcard);
13205 /*
13206 * NOTE: During the parse time, the wildcard is created
13207 * on the complexType directly, if encountered in a
13208 * <restriction> or <extension> element.
13209 */
13210 if (err == -1) {
13211 PERROR_INT("xmlSchemaBuildAttributeValidation",
13212 "failed to build an intersected attribute wildcard");
13213 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013214 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013215 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013216
13217 if (hasProhibitions) {
13218 xmlSchemaAttributeLinkPtr tmpPrev = NULL;
13219 /*
13220 * Handle annoying pointless prohibitions.
13221 * Note that this will be done for restrictions only, since
13222 * prohibitions are not gathered for extensions.
13223 */
13224 cur = localUses;
13225
13226pointless_prohib_next:
13227 while (cur != NULL) {
13228 tmp = cur->next;
13229 tmpPrev = cur;
13230 while (tmp != NULL) {
13231 if ( ((cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
13232 (tmp->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED)) ||
13233 (xmlSchemaGetAttrName(cur->attr) !=
13234 xmlSchemaGetAttrName(tmp->attr)) ||
13235 (xmlSchemaGetAttrTargetNsURI(cur->attr) !=
13236 xmlSchemaGetAttrTargetNsURI(tmp->attr)))
13237 {
13238 tmpPrev = tmp;
13239 tmp = tmp->next;
13240 continue;
13241 }
13242 if (cur->attr->occurs == tmp->attr->occurs) {
13243 xmlSchemaAttributeLinkPtr tmpFree;
13244 /*
13245 * Warn about duplicate prohibitions.
13246 */
13247 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
13248 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
13249 tmp->attr->node, NULL,
13250 "Skipping duplicate prohibition "
13251 "of attribute use '%s'",
13252 xmlSchemaFormatQName(&str,
13253 xmlSchemaGetAttrTargetNsURI(tmp->attr),
13254 xmlSchemaGetAttrName(tmp->attr)),
13255 NULL, NULL);
13256 FREE_AND_NULL(str)
13257 /*
13258 * Remove the duplicate prohibition.
13259 */
13260 tmpFree = tmp;
13261 tmpPrev->next = tmp->next;
13262 tmp = tmp->next;
13263 xmlFree(tmpFree);
13264 hasProhibitions--;
13265 continue;
13266 } else {
13267 xmlSchemaAttributeLinkPtr tmpFree;
13268 xmlSchemaAttributePtr reattr;
13269 /*
13270 * Annoying case:
13271 * This is the case when we prohibited
13272 * the base attribute decl in the previous
13273 * step; i.e. when we prohibit and declare the
13274 * same attribute in the same <complexType>.
13275 */
13276 if (cur->attr->occurs ==
13277 XML_SCHEMAS_ATTR_USE_PROHIBITED)
13278 reattr = cur->attr;
13279 else
13280 reattr = tmp->attr;
13281 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
13282 XML_SCHEMAP_WARN_ATTR_REDECL_PROH,
13283 reattr->node, NULL,
13284 "Skipping pointless prohibition of "
13285 "attribute use '%s', since a corresponding "
13286 "attribute was explicitely declared as well",
13287 xmlSchemaFormatQName(&str,
13288 xmlSchemaGetAttrTargetNsURI(reattr),
13289 xmlSchemaGetAttrName(reattr)),
13290 NULL, NULL);
13291 FREE_AND_NULL(str);
13292 /*
13293 * Remove the prohibition.
13294 */
13295 if (reattr == cur->attr) {
13296 tmpFree = cur;
13297 if (prev != NULL)
13298 prev->next = cur->next;
13299 else
13300 localUses = cur->next;
13301 cur = cur->next;
13302 xmlFree(tmpFree);
13303 hasProhibitions--;
13304 goto pointless_prohib_next;
13305 } else {
13306 tmpFree = tmp;
13307 tmpPrev->next = tmp->next;
13308 tmp = tmp->next;
13309 xmlFree(tmpFree);
13310 hasProhibitions--;
13311 continue;
13312 }
13313 }
13314 tmpPrev = tmp;
13315 tmp = tmp->next;
13316 }
13317 prev = cur;
13318 cur = cur->next;
13319 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013320 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013321
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013322 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
13323 * "Two distinct attribute declarations in the {attribute uses} must
13324 * not have identical {name}s and {target namespace}s."
13325 *
13326 * This is done here for <restriction>s. We will compare only the
13327 * attr uses of the current type.
13328 * For <extension>s this is done further down.
13329 */
13330 if ((localUses != NULL) && (localUses->next != NULL) &&
13331 (WXS_IS_RESTRICTION(type))) {
13332 cur = localUses;
13333 while (cur != NULL) {
13334 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
13335 cur = cur->next;
13336 continue;
13337 }
13338 tmp = cur->next;
13339 while (tmp != NULL) {
13340 if (tmp->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
13341 tmp = tmp->next;
13342 continue;
13343 }
13344 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
13345 xmlSchemaGetAttrName(tmp->attr))) &&
13346 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
13347 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
13348 /*
13349 * Duplicate attr uses.
13350 */
13351 xmlSchemaPAttrUseErr(pctxt,
13352 XML_SCHEMAP_CT_PROPS_CORRECT_4,
13353 type, cur->attr,
13354 "Duplicate attribute use '%s' specified",
13355 xmlSchemaFormatQName(&str,
13356 xmlSchemaGetAttrTargetNsURI(tmp->attr),
13357 xmlSchemaGetAttrName(tmp->attr)));
13358 FREE_AND_NULL(str)
13359 break;
13360 }
13361 tmp = tmp->next;
13362 }
13363 cur = cur->next;
13364 }
13365 }
13366
13367 /*
13368 * Inherit the attribute uses of the base type, but leave out
13369 * prohibited ones.
13370 * NOTE: It is allowed to "extend" the anyType complex type.
13371 */
13372 if (baseType->attributeUses != NULL) {
13373 base = baseType->attributeUses;
13374inherit_start:
13375 while (base != NULL) {
13376 /*
13377 * Check if prohibited.
13378 */
13379 if (hasProhibitions) {
13380 cur = localUses;
13381 while (cur != NULL) {
13382 if ((cur->attr->occurs ==
13383 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
13384 xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
13385 xmlSchemaGetAttrName(base->attr)) &&
13386 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
13387 xmlSchemaGetAttrTargetNsURI(base->attr)))
13388 {
13389 /*
13390 * Don't inherit prohibited attr uses.
13391 */
13392 if (base->attr->occurs ==
13393 XML_SCHEMAS_ATTR_USE_REQUIRED) {
13394 /*
13395 * derivation-ok-restriction 3
13396 * There won't be an attr use left if
13397 * prohibiting the inherited one, so this
13398 * will automatically violate required
13399 * attr uses.
13400 */
13401 xmlSchemaPCustomErr(pctxt,
13402 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
13403 NULL, type, NULL,
13404 "A matching attribute use for the "
13405 "'required' attribute use '%s' of the "
13406 "base type is missing",
13407 xmlSchemaFormatQName(&str,
13408 xmlSchemaGetAttrTargetNsURI(base->attr),
13409 xmlSchemaGetAttrName(base->attr)));
13410 FREE_AND_NULL(str)
13411 }
13412 base = base->next;
13413 goto inherit_start;
13414 }
13415 cur = cur->next;
13416 }
13417 }
13418 tmp = (xmlSchemaAttributeLinkPtr)
13419 xmlMalloc(sizeof(xmlSchemaAttributeLink));
13420 if (tmp == NULL) {
13421 xmlSchemaPErrMemory(pctxt,
13422 "allocating attribute uses", NULL);
13423 return (-1);
13424 }
13425 tmp->attr = base->attr;
13426 tmp->next = NULL;
13427 if (type->attributeUses == NULL) {
13428 type->attributeUses = tmp;
13429 } else
13430 lastBaseUse->next = tmp;
13431 lastBaseUse = tmp;
13432 /* next */
13433 base = base->next;
13434 }
13435 }
13436
13437 if ((WXS_IS_EXTENSION(type)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013438 ((IS_ANYTYPE(baseType)) ||
13439 ((baseType != NULL) &&
13440 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
13441 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013442 if (type->attributeWildcard != NULL) {
13443 /*
13444 * Union the complete wildcard with the base wildcard.
13445 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013446 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013447 baseType->attributeWildcard) == -1)
13448 return (-1);
13449 } else {
13450 /*
13451 * Just inherit the wildcard.
13452 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013453 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013454 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013455 * wildcard is shared.
13456 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013457 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000013458 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013459 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013460
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013461 if (WXS_IS_RESTRICTION(type)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013462 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013463 /*
13464 * Derivation Valid (Restriction, Complex)
13465 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013466 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013467 if (baseType->attributeWildcard == NULL) {
13468 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013469 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013470 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013471 "The type has an attribute wildcard, "
13472 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013473 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013474 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013475 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013476 } else if (xmlSchemaCheckCOSNSSubset(
13477 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013478 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013479 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013480 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013481 NULL, type, NULL,
13482 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013483 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013484 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
13485 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013486 return (1);
13487 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013488 /* 4.3 Unless the {base type definition} is the ·ur-type
13489 * definition·, the complex type definition's {attribute
13490 * wildcard}'s {process contents} must be identical to or
13491 * stronger than the {base type definition}'s {attribute
13492 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013493 * than lax is stronger than skip.
13494 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013495 if ((! IS_ANYTYPE(baseType)) &&
13496 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013497 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013498 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013499 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013500 NULL, type, NULL,
13501 "The 'process contents' of the attribute wildcard is "
13502 "weaker than the one in the base type %s",
13503 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013504 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013505 return (1);
13506 }
13507 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013508 } else if (WXS_IS_EXTENSION(type)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013509 /*
13510 * Derivation Valid (Extension)
13511 * At this point the type and the base have both, either
13512 * no wildcard or a wildcard.
13513 */
13514 if ((baseType->attributeWildcard != NULL) &&
13515 (baseType->attributeWildcard != type->attributeWildcard)) {
13516 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013517 if (xmlSchemaCheckCOSNSSubset(
13518 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013519 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013520 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013521 NULL, type, NULL,
13522 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013523 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013524 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
13525 FREE_AND_NULL(str)
13526 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013527 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013528 }
13529 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013530
13531 if (localUses == NULL) {
13532 /* PASS */
13533 } else if (WXS_IS_RESTRICTION(type)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013534 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013535 * Derive by restriction. At this point prohibited uses are already
13536 * filtered out.
Daniel Veillard3646d642004-06-02 19:19:14 +000013537 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013538 if (IS_ANYTYPE(baseType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013539 type->attributeUses = localUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000013540 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013541 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013542 const xmlChar *bEffValue;
13543 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000013544
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013545 cur = localUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000013546 while (cur != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013547 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
13548 prev = cur;
13549 cur = cur->next;
13550 continue;
13551 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013552 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013553 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000013554 base = type->attributeUses;
13555 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013556 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013557 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013558 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013559 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013560
13561 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000013562
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013563 if ((cur->attr->occurs ==
13564 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
13565 (base->attr->occurs ==
13566 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013567 /*
13568 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000013569 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013570 xmlSchemaPAttrUseErr(pctxt,
13571 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
13572 type, cur->attr,
13573 "The 'optional' use is inconsistent with a "
13574 "matching 'required' use of the base type",
13575 NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013576 } else if (xmlSchemaCheckCOSSTDerivedOK(
13577 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
13578
13579 /*
13580 * SPEC (2.1.2) "R's {attribute declaration}'s
13581 * {type definition} must be validly derived from
13582 * B's {type definition} given the empty set as
13583 * defined in Type Derivation OK (Simple) (§3.14.6)."
13584 */
13585 xmlSchemaPAttrUseErr(pctxt,
13586 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
13587 type, cur->attr,
13588 "The attribute declaration's type "
13589 "definition is not validly derived from "
13590 "the corresponding definition in the "
13591 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000013592 } else {
13593 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013594 * 2.1.3 [Definition:] Let the effective value
13595 * constraint of an attribute use be its {value
13596 * constraint}, if present, otherwise its {attribute
13597 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013598 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013599 xmlSchemaGetEffectiveValueConstraint(base->attr,
Daniel Veillard24505b02005-07-28 23:49:35 +000013600 &effFixed, &bEffValue, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013601 /*
13602 * 2.1.3 ... one of the following must be true
13603 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013604 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013605 * ·absent· or default.
13606 */
13607 if ((bEffValue != NULL) &&
13608 (effFixed == 1)) {
13609 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013610
13611 xmlSchemaGetEffectiveValueConstraint(base->attr,
Daniel Veillard24505b02005-07-28 23:49:35 +000013612 &effFixed, &rEffValue, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013613 /*
13614 * 2.1.3.2 R's ·effective value constraint· is
13615 * fixed with the same string as B's.
13616 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013617 */
13618 if ((effFixed == 0) ||
13619 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013620 xmlSchemaPAttrUseErr(pctxt,
13621 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
13622 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013623 "The effective value constraint of the "
13624 "attribute use is inconsistent with "
13625 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013626 NULL);
13627 } else {
13628 /*
13629 * Override the attribute use.
13630 */
13631 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013632 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013633 } else
13634 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000013635 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013636
Daniel Veillard3646d642004-06-02 19:19:14 +000013637 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013638 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013639 base = base->next;
13640 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013641
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013642 if (!found) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013643 /*
13644 * derivation-ok-restriction 2.2
13645 */
13646 if ((baseType->attributeWildcard == NULL) ||
13647 (xmlSchemaCheckCVCWildcardNamespace(
13648 baseType->attributeWildcard,
13649 cur->attr->targetNamespace) != 1)) {
13650 xmlSchemaPAttrUseErr(pctxt,
13651 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
13652 type, cur->attr,
13653 "Neither a matching attribute use, "
13654 "nor a matching wildcard in the base type does exist",
13655 NULL);
13656 } else {
13657 /*
13658 * Add the attribute use.
13659 *
13660 * Note that this may lead to funny derivation error reports, if
13661 * multiple equal attribute uses exist; but this is not
13662 * allowed anyway, and it will be reported beforehand.
13663 */
13664 tmp = cur;
13665 if (prev != NULL)
13666 prev->next = cur->next;
13667 else
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013668 localUses = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013669 cur = cur->next;
13670 tmp->next = NULL;
13671 if (type->attributeUses == NULL) {
13672 type->attributeUses = tmp;
13673 } else
13674 lastBaseUse->next = tmp;
13675 lastBaseUse = tmp;
13676
13677 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000013678 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013679 }
13680 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000013681 cur = cur->next;
13682 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013683 if (localUses != NULL)
13684 xmlSchemaFreeAttributeUseList(localUses);
Daniel Veillard3646d642004-06-02 19:19:14 +000013685 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013686 } else if (WXS_IS_EXTENSION(type)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013687 /*
13688 * The spec allows only appending, and not other kinds of extensions.
13689 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013690 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000013691 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013692 if (localUses != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013693 if (type->attributeUses == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013694 type->attributeUses = localUses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013695 } else
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013696 lastBaseUse->next = localUses;
Daniel Veillard50355f02004-06-08 17:52:16 +000013697 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013698 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013699 PERROR_INT("xmlSchemaBuildAttributeValidation",
13700 "no derivation method");
13701 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013702 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013703 /*
13704 * 3.4.6 -> Complex Type Definition Properties Correct
13705 */
13706 if (type->attributeUses != NULL) {
13707 cur = type->attributeUses;
13708 prev = NULL;
13709 while (cur != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013710 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
13711 /*
13712 * Remove "prohibited" attribute uses. The reason this is
13713 * done at this late stage is to be able to catch
13714 * dublicate attribute uses. So we had to keep prohibited
13715 * uses in the list as well.
13716 */
13717 tmp = cur;
13718 if (prev == NULL)
13719 type->attributeUses = cur->next;
13720 else
13721 prev->next = cur->next;
13722 cur = cur->next;
13723 xmlFree(tmp);
13724 continue;
13725 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013726 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013727 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000013728 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000013729 *
Daniel Veillard3646d642004-06-02 19:19:14 +000013730 * Note that this was already done for "restriction" and types derived from
13731 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000013732 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013733 if (WXS_IS_EXTENSION(type)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013734 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013735 while (tmp != NULL) {
13736 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000013737 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013738 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000013739 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013740
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013741 xmlSchemaPAttrUseErr(pctxt,
13742 XML_SCHEMAP_CT_PROPS_CORRECT_4,
13743 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013744 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013745 break;
13746 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013747 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000013748 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013749 }
13750
Daniel Veillard3646d642004-06-02 19:19:14 +000013751 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013752 * 5. Two distinct attribute declarations in the
13753 * {attribute uses} must not have {type definition}s which
13754 * are or are derived from ID.
Daniel Veillard3646d642004-06-02 19:19:14 +000013755 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013756 if ((cur->attr->subtypes != NULL) &&
13757 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013758 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013759 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013760 xmlSchemaPAttrUseErr(pctxt,
13761 XML_SCHEMAP_CT_PROPS_CORRECT_5,
13762 type, cur->attr,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013763 "There must not exist more than one attribute "
13764 "use, declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000013765 NULL);
13766 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013767 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013768 id = cur;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000013769 }
13770 prev = cur;
13771 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013772 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013773 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013774 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013775 * TODO: This check should be removed if we are 100% sure of
13776 * the base type attribute uses already being built.
13777 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013778 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013779 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013780 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013781 PERROR_INT("xmlSchemaBuildAttributeValidation",
13782 "attribute uses not builded on base type");
13783 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013784 return (0);
13785}
13786
13787/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013788 * xmlSchemaTypeFinalContains:
13789 * @schema: the schema
13790 * @type: the type definition
13791 * @final: the final
13792 *
13793 * Evaluates if a type definition contains the given "final".
13794 * This does take "finalDefault" into account as well.
13795 *
13796 * Returns 1 if the type does containt the given "final",
13797 * 0 otherwise.
13798 */
13799static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013800xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013801{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013802 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013803 return (0);
13804 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013805 return (1);
13806 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013807 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013808}
13809
13810/**
13811 * xmlSchemaGetUnionSimpleTypeMemberTypes:
13812 * @type: the Union Simple Type
13813 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013814 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013815 * returns NULL otherwise.
13816 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013817static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000013818xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
13819{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013820 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013821 if (type->memberTypes != NULL)
13822 return (type->memberTypes);
13823 else
13824 type = type->baseType;
13825 }
13826 return (NULL);
13827}
13828
13829/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013830 * xmlSchemaGetParticleTotalRangeMin:
13831 * @particle: the particle
13832 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013833 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013834 * (all and sequence) + (choice)
13835 *
13836 * Returns the minimun Effective Total Range.
13837 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013838static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013839xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013840{
13841 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013842 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013843 return (0);
13844 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013845 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013846 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013847 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013848
13849 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013850 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013851 while (part != NULL) {
13852 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13853 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013854 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013855 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013856 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013857 if (cur == 0)
13858 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013859 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013860 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013861 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013862 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013863 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013864 } else {
13865 /* <all> and <sequence> */
13866 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013867 xmlSchemaParticlePtr part =
13868 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013869
13870 if (part == NULL)
13871 return (0);
13872 do {
13873 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13874 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013875 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013876 else
13877 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013878 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013879 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013880 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013881 }
13882}
13883
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013884/**
13885 * xmlSchemaGetParticleTotalRangeMax:
13886 * @particle: the particle
13887 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013888 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013889 * (all and sequence) + (choice)
13890 *
13891 * Returns the maximum Effective Total Range.
13892 */
13893static int
13894xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13895{
13896 if ((particle->children == NULL) ||
13897 (particle->children->children == NULL))
13898 return (0);
13899 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13900 int max = -1, cur;
13901 xmlSchemaParticlePtr part =
13902 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013903
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013904 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13905 if (part->children == NULL)
13906 continue;
13907 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13908 (part->children->type == XML_SCHEMA_TYPE_ANY))
13909 cur = part->maxOccurs;
13910 else
13911 cur = xmlSchemaGetParticleTotalRangeMax(part);
13912 if (cur == UNBOUNDED)
13913 return (UNBOUNDED);
13914 if ((max < cur) || (max == -1))
13915 max = cur;
13916 }
13917 /* TODO: Handle overflows? */
13918 return (particle->maxOccurs * max);
13919 } else {
13920 /* <all> and <sequence> */
13921 int sum = 0, cur;
13922 xmlSchemaParticlePtr part =
13923 (xmlSchemaParticlePtr) particle->children->children;
13924
13925 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13926 if (part->children == NULL)
13927 continue;
13928 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13929 (part->children->type == XML_SCHEMA_TYPE_ANY))
13930 cur = part->maxOccurs;
13931 else
13932 cur = xmlSchemaGetParticleTotalRangeMax(part);
13933 if (cur == UNBOUNDED)
13934 return (UNBOUNDED);
13935 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13936 return (UNBOUNDED);
13937 sum += cur;
13938 }
13939 /* TODO: Handle overflows? */
13940 return (particle->maxOccurs * sum);
13941 }
13942}
13943
13944/**
13945 * xmlSchemaIsParticleEmptiable:
13946 * @particle: the particle
13947 *
13948 * Schema Component Constraint: Particle Emptiable
13949 * Checks whether the given particle is emptiable.
13950 *
13951 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013952 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013953static int
13954xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13955{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013956 /*
13957 * SPEC (1) "Its {min occurs} is 0."
13958 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013959 if ((particle == NULL) || (particle->minOccurs == 0) ||
13960 (particle->children == NULL))
13961 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013962 /*
13963 * SPEC (2) "Its {term} is a group and the minimum part of the
13964 * effective total range of that group, [...] is 0."
13965 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013966 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013967 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013968 return (1);
13969 }
13970 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013971}
13972
13973/**
13974 * xmlSchemaCheckCOSSTDerivedOK:
13975 * @type: the derived simple type definition
13976 * @baseType: the base type definition
13977 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013978 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013979 * Type Derivation OK (Simple) (cos-st-derived-OK)
13980 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013981 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013982 * derived from @baseType.
13983 *
13984 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013985 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013986static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013987xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13988 xmlSchemaTypePtr baseType,
13989 int subset)
13990{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013991 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013992 * 1 They are the same type definition.
13993 * TODO: The identy check might have to be more complex than this.
13994 */
13995 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013996 return (0);
13997 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013998 * 2.1 restriction is not in the subset, or in the {final}
13999 * of its own {base type definition};
14000 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014001 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014002 (xmlSchemaTypeFinalContains(type->baseType,
14003 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14004 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014005 }
14006 /* 2.2 */
14007 if (type->baseType == baseType) {
14008 /*
14009 * 2.2.1 D's ·base type definition· is B.
14010 */
14011 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014012 }
14013 /*
14014 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
14015 * and is validly derived from B given the subset, as defined by this
14016 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014017 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014018 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014019 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014020 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014021 return (0);
14022 }
14023 /*
14024 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000014025 * definition·.
14026 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014027 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014028 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014029 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014030 }
14031 /*
14032 * 2.2.4 B's {variety} is union and D is validly derived from a type
14033 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000014034 * defined by this constraint.
14035 *
14036 * NOTE: This seems not to involve built-in types, since there is no
14037 * built-in Union Simple Type.
14038 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014039 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014040 xmlSchemaTypeLinkPtr cur;
14041
14042 cur = baseType->memberTypes;
14043 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014044 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014045 return (0);
14046 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014047 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014048 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014049
Daniel Veillard01fa6152004-06-29 17:04:39 +000014050 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14051}
14052
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014053/**
14054 * xmlSchemaCheckTypeDefCircularInternal:
14055 * @pctxt: the schema parser context
14056 * @ctxtType: the type definition
14057 * @ancestor: an ancestor of @ctxtType
14058 *
14059 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014060 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014061 *
14062 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14063 * circular, 0 otherwise.
14064 */
14065static int
14066xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14067 xmlSchemaTypePtr ctxtType,
14068 xmlSchemaTypePtr ancestor)
14069{
14070 int ret;
14071
14072 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14073 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014074
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014075 if (ctxtType == ancestor) {
14076 xmlSchemaPCustomErr(pctxt,
14077 XML_SCHEMAP_ST_PROPS_CORRECT_2,
14078 NULL, ctxtType, GET_NODE(ctxtType),
14079 "The definition is circular", NULL);
14080 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14081 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014082 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14083 /*
14084 * Avoid inifinite recursion on circular types not yet checked.
14085 */
14086 return (0);
14087 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014088 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14089 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14090 ancestor->baseType);
14091 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14092 return (ret);
14093}
14094
14095/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014096 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014097 * @item: the complex/simple type definition
14098 * @ctxt: the parser context
14099 * @name: the name
14100 *
14101 * Checks for circular type definitions.
14102 */
14103static void
14104xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014105 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014106{
14107 if ((item == NULL) ||
14108 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
14109 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
14110 return;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000014111 if (item->redef != NULL) {
14112 xmlSchemaTypePtr cur = item;
14113 do {
14114 xmlSchemaCheckTypeDefCircularInternal(ctxt, cur, cur->baseType);
14115 cur = cur->redef;
14116 } while (cur != NULL);
14117 } else
14118 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014119}
Daniel Veillard01fa6152004-06-29 17:04:39 +000014120
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014121/*
14122* Simple Type Definition Representation OK (src-simple-type) 4
14123*
14124* "4 Circular union type definition is disallowed. That is, if the
14125* <union> alternative is chosen, there must not be any entries in the
14126* memberTypes [attribute] at any depth which resolve to the component
14127* corresponding to the <simpleType>."
14128*
14129* Note that this should work on the *representation* of a component,
14130* thus assumes any union types in the member types not being yet
14131* substituted. At this stage we need the variety of the types
14132* to be already computed.
14133*/
14134static int
14135xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14136 xmlSchemaTypePtr ctxType,
14137 xmlSchemaTypeLinkPtr members)
14138{
14139 xmlSchemaTypeLinkPtr member;
14140 xmlSchemaTypePtr memberType;
14141
14142 member = members;
14143 while (member != NULL) {
14144 memberType = member->type;
14145 while ((memberType != NULL) &&
14146 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14147 if (memberType == ctxType) {
14148 xmlSchemaPCustomErr(pctxt,
14149 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14150 NULL, ctxType, NULL,
14151 "The union type definition is circular", NULL);
14152 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14153 }
14154 if ((VARIETY_UNION(memberType)) &&
14155 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14156 {
14157 int res;
14158 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14159 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14160 ctxType,
14161 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14162 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14163 if (res != 0)
14164 return(res);
14165 }
14166 memberType = memberType->baseType;
14167 }
14168 member = member->next;
14169 }
14170 return(0);
14171}
14172
14173static int
14174xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14175 xmlSchemaTypePtr type)
14176{
14177 if (! VARIETY_UNION(type))
14178 return(0);
14179 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14180 type->memberTypes));
14181}
14182
Daniel Veillard01fa6152004-06-29 17:04:39 +000014183/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014184 * xmlSchemaResolveTypeReferences:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014185 * @item: the complex/simple type definition
14186 * @ctxt: the parser context
14187 * @name: the name
14188 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014189 * Resolvese type definition references
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014190 */
14191static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014192xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014193 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014194 const xmlChar * name ATTRIBUTE_UNUSED)
14195{
14196 if (typeDef == NULL)
14197 return;
14198
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014199 /*
14200 * Resolve the base type.
14201 */
14202 if (typeDef->baseType == NULL) {
14203 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
14204 typeDef->base, typeDef->baseNs);
14205 if (typeDef->baseType == NULL) {
14206 xmlSchemaPResCompAttrErr(ctxt,
14207 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014208 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014209 "base", typeDef->base, typeDef->baseNs,
14210 XML_SCHEMA_TYPE_SIMPLE, NULL);
14211 return;
14212 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014213 }
14214 if (IS_SIMPLE_TYPE(typeDef)) {
14215 if (VARIETY_UNION(typeDef)) {
14216 /*
14217 * Resolve the memberTypes.
14218 */
14219 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
14220 return;
14221 } else if (VARIETY_LIST(typeDef)) {
14222 /*
14223 * Resolve the itemType.
14224 */
14225 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
14226 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
14227 typeDef->ref, typeDef->refNs);
14228 if ((typeDef->subtypes == NULL) ||
14229 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
14230 typeDef->subtypes = NULL;
14231 xmlSchemaPResCompAttrErr(ctxt,
14232 XML_SCHEMAP_SRC_RESOLVE,
14233 typeDef, typeDef->node,
14234 "itemType", typeDef->ref, typeDef->refNs,
14235 XML_SCHEMA_TYPE_SIMPLE, NULL);
14236 }
14237 }
14238 return;
14239 }
14240 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014241}
14242
14243
14244
14245/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000014246 * xmlSchemaCheckSTPropsCorrect:
14247 * @ctxt: the schema parser context
14248 * @type: the simple type definition
14249 *
14250 * Checks st-props-correct.
14251 *
14252 * Returns 0 if the properties are correct,
14253 * if not, a positive error code and -1 on internal
14254 * errors.
14255 */
14256static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014257xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014258 xmlSchemaTypePtr type)
14259{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014260 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014261 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014262
Daniel Veillardc0826a72004-08-10 14:17:33 +000014263 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014264 /*
14265 * Schema Component Constraint: Simple Type Definition Properties Correct
14266 *
14267 * NOTE: This is somehow redundant, since we actually built a simple type
14268 * to have all the needed information; this acts as an self test.
14269 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014270 /* Base type: If the datatype has been ·derived· by ·restriction·
14271 * then the Simple Type Definition component from which it is ·derived·,
14272 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000014273 */
14274 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014275 /*
14276 * TODO: Think about: "modulo the impact of Missing
14277 * Sub-components (§5.3)."
14278 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014279 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014280 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014281 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014282 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014283 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014284
Daniel Veillard01fa6152004-06-29 17:04:39 +000014285 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014286 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014287 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014288 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014289 NULL, type, NULL,
14290 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014291 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014292 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014293 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
14294 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014295 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014296 (WXS_IS_RESTRICTION(type) == 0) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014297 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014298 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014299 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014300 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014301 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014302 "the simple ur-type definition as base type, not '%s'",
14303 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014304 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014305 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
14306 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014307 /*
14308 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014309 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014310 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
14311 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014312 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014313 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014314 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014315 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014316 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
14317 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014318 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014319
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014320 /*
14321 * 3 The {final} of the {base type definition} must not contain restriction.
14322 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014323 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014324 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
14325 xmlSchemaPCustomErr(ctxt,
14326 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014327 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014328 "The 'final' of its base type '%s' must not contain "
14329 "'restriction'",
14330 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014331 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014332 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014333 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014334
14335 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014336 * 2 All simple type definitions must be derived ultimately from the ·simple
14337 * ur-type definition (so· circular definitions are disallowed). That is, it
14338 * must be possible to reach a built-in primitive datatype or the ·simple
14339 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014340 *
14341 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000014342 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014343 return (0);
14344}
14345
14346/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014347 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000014348 * @ctxt: the schema parser context
14349 * @type: the simple type definition
14350 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014351 * Schema Component Constraint:
14352 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
14353
14354 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014355 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000014356 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014357 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014358 * a positive error code otherwise.
14359 */
14360static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014361xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014362 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014363{
Daniel Veillardc0826a72004-08-10 14:17:33 +000014364 xmlChar *str = NULL;
14365
Daniel Veillard01fa6152004-06-29 17:04:39 +000014366 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014367 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
14368 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014369 return (-1);
14370 }
14371
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014372 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014373 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014374 /*
14375 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000014376 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014377 */
14378 if (! VARIETY_ATOMIC(type->baseType)) {
14379 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014380 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014381 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014382 "The base type '%s' is not an atomic simple type",
14383 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014384 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014385 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
14386 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014387 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000014388 * restriction.
14389 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014390 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014391 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014392 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014393 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014394 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014395 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014396 "The final of its base type '%s' must not contain 'restriction'",
14397 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014398 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014399 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
14400 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014401
14402 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014403 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014404 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000014405 * Primitive datatypes.
14406 */
14407 if (type->facets != NULL) {
14408 xmlSchemaFacetPtr facet;
14409 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014410
Daniel Veillard01fa6152004-06-29 17:04:39 +000014411 primitive = xmlSchemaGetPrimitiveType(type);
14412 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014413 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
14414 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014415 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014416 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014417 facet = type->facets;
14418 do {
14419 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014420 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014421 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014422 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014423 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014424 }
14425 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014426 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014427 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014428 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014429 }
14430 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014431 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
14432 * of the {base type definition} (call this BF),then the DF's {value}
14433 * must be a valid restriction of BF's {value} as defined in
14434 * [XML Schemas: Datatypes]."
14435 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014436 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014437 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000014438 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014439 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014440 xmlSchemaTypePtr itemType = NULL;
14441
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014442 itemType = type->subtypes;
14443 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014444 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
14445 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014446 return (-1);
14447 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014448 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014449 xmlSchemaTypeFixup(itemType, pctxt);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014450 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014451 * 2.1 The {item type definition} must have a {variety} of atomic or
14452 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000014453 * must be atomic).
14454 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014455 if ((! VARIETY_ATOMIC(itemType)) &&
14456 (! VARIETY_UNION(itemType))) {
14457 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014458 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014459 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014460 "The item type '%s' does not have a variety of atomic or union",
14461 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014462 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014463 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014464 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014465 xmlSchemaTypeLinkPtr member;
14466
14467 member = itemType->memberTypes;
14468 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014469 if (! VARIETY_ATOMIC(member->type)) {
14470 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014471 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014472 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014473 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014474 "member type '%s' of this item type is not atomic",
14475 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014476 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014477 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
14478 }
14479 member = member->next;
14480 }
14481 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014482
14483 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014484 xmlSchemaFacetPtr facet;
14485 /*
14486 * This is the case if we have: <simpleType><list ..
14487 */
14488 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014489 * 2.3.1
14490 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000014491 * contain list.
14492 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014493 if (xmlSchemaTypeFinalContains(itemType,
14494 XML_SCHEMAS_TYPE_FINAL_LIST)) {
14495 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014496 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014497 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014498 "The final of its item type '%s' must not contain 'list'",
14499 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014500 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014501 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
14502 }
14503 /*
14504 * 2.3.1.2 The {facets} must only contain the whiteSpace
14505 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014506 * OPTIMIZE TODO: the S4S already disallows any facet
14507 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014508 */
14509 if (type->facets != NULL) {
14510 facet = type->facets;
14511 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014512 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014513 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014514 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014515 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014516 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
14517 }
14518 facet = facet->next;
14519 } while (facet != NULL);
14520 }
14521 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014522 * MAYBE TODO: (Hmm, not really) Datatypes states:
14523 * A ·list· datatype can be ·derived· from an ·atomic· datatype
14524 * whose ·lexical space· allows space (such as string or anyURI)or
14525 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000014526 * ·lexical space· allows space.
14527 */
14528 } else {
14529 /*
14530 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014531 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014532 */
14533 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014534 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000014535 * 2.3.2.1 The {base type definition} must have a {variety} of list.
14536 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014537 if (! VARIETY_LIST(type->baseType)) {
14538 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014539 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014540 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014541 "The base type '%s' must be a list type",
14542 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014543 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014544 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
14545 }
14546 /*
14547 * 2.3.2.2 The {final} of the {base type definition} must not
14548 * contain restriction.
14549 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014550 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014551 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014552 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014553 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014554 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014555 "The 'final' of the base type '%s' must not contain 'restriction'",
14556 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014557 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014558 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
14559 }
14560 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014561 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000014562 * from the {base type definition}'s {item type definition} given
14563 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
14564 */
14565 {
14566 xmlSchemaTypePtr baseItemType;
14567
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014568 baseItemType = type->baseType->subtypes;
14569 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014570 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
14571 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014572 return (-1);
14573 }
14574 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014575 (xmlSchemaCheckCOSSTDerivedOK(itemType,
14576 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014577 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014578 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014579 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014580 NULL, type, NULL,
14581 "The item type '%s' is not validly derived from "
14582 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014583 xmlSchemaGetComponentQName(&str, itemType),
14584 xmlSchemaGetComponentQName(&strBIT, baseItemType),
14585 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014586
14587 FREE_AND_NULL(str)
14588 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014589 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014590 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
14591 }
14592 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014593
Daniel Veillard01fa6152004-06-29 17:04:39 +000014594 if (type->facets != NULL) {
14595 xmlSchemaFacetPtr facet;
14596 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014597 /*
14598 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000014599 * and enumeration facet components are allowed among the {facets}.
14600 */
14601 facet = type->facets;
14602 do {
14603 switch (facet->type) {
14604 case XML_SCHEMA_FACET_LENGTH:
14605 case XML_SCHEMA_FACET_MINLENGTH:
14606 case XML_SCHEMA_FACET_MAXLENGTH:
14607 case XML_SCHEMA_FACET_WHITESPACE:
14608 /*
14609 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014610 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014611 */
14612 case XML_SCHEMA_FACET_PATTERN:
14613 case XML_SCHEMA_FACET_ENUMERATION:
14614 break;
14615 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014616 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014617 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014618 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014619 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014620 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000014621 * invalid facets.
14622 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014623 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014624 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014625 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014626 facet = facet->next;
14627 } while (facet != NULL);
14628 if (ok == 0)
14629 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
14630 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014631 * SPEC (2.3.2.5) (same as 1.3.2)
14632 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014633 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014634 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000014635 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014636 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014637 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014638 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014639 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014640 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000014641 * atomic or list.
14642 */
14643 xmlSchemaTypeLinkPtr member;
14644
14645 member = type->memberTypes;
14646 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014647 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014648 xmlSchemaTypeFixup(member->type, pctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014649
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014650 if ((! VARIETY_ATOMIC(member->type)) &&
14651 (! VARIETY_LIST(member->type))) {
14652 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014653 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014654 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014655 "The member type '%s' is neither an atomic, nor a list type",
14656 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014657 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014658 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
14659 }
14660 member = member->next;
14661 }
14662 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014663 * 3.3.1 If the {base type definition} is the ·simple ur-type
14664 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000014665 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014666 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014667 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014668 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000014669 * {final} which does not contain union.
14670 */
14671 member = type->memberTypes;
14672 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014673 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014674 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014675 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014676 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014677 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014678 "The 'final' of member type '%s' contains 'union'",
14679 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014680 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014681 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
14682 }
14683 member = member->next;
14684 }
14685 /*
14686 * 3.3.1.2 The {facets} must be empty.
14687 */
14688 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014689 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014690 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014691 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014692 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014693 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
14694 }
14695 } else {
14696 /*
14697 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014698 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014699 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014700 if (! VARIETY_UNION(type->baseType)) {
14701 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014702 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014703 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014704 "The base type '%s' is not a union type",
14705 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014706 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014707 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
14708 }
14709 /*
14710 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
14711 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014712 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014713 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014714 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014715 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014716 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014717 "The 'final' of its base type '%s' must not contain 'restriction'",
14718 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014719 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014720 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
14721 }
14722 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014723 * 3.3.2.3 The {member type definitions}, in order, must be validly
14724 * derived from the corresponding type definitions in the {base
14725 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014726 * as defined in Type Derivation OK (Simple) (§3.14.6).
14727 */
14728 {
14729 xmlSchemaTypeLinkPtr baseMember;
14730
14731 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014732 * OPTIMIZE: if the type is restricting, it has no local defined
14733 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014734 * thus a check for equality can be skipped.
14735 */
14736 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014737 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014738 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000014739 * types of it's base type. This check seems not necessary with
14740 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014741 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014742 */
14743 if (type->memberTypes != NULL) {
14744 member = type->memberTypes;
14745 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014746 if ((member == NULL) && (baseMember != NULL)) {
14747 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
14748 "different number of member types in base");
14749 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014750 while (member != NULL) {
14751 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014752 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
14753 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014754 }
14755 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014756 (xmlSchemaCheckCOSSTDerivedOK(
14757 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014758 xmlChar *strBMT = NULL, *strBT = NULL;
14759
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014760 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014761 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
14762 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014763 "The member type %s is not validly "
14764 "derived from its corresponding member "
14765 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014766 xmlSchemaGetComponentQName(&str, member->type),
14767 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
14768 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014769 FREE_AND_NULL(str)
14770 FREE_AND_NULL(strBMT)
14771 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014772 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014773 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014774 member = member->next;
14775 baseMember = baseMember->next;
14776 }
14777 }
14778 }
14779 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014780 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000014781 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014782 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014783 if (type->facets != NULL) {
14784 xmlSchemaFacetPtr facet;
14785 int ok = 1;
14786
14787 facet = type->facets;
14788 do {
14789 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
14790 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014791 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014792 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014793 NULL, type, facet);
14794 ok = 0;
14795 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014796 facet = facet->next;
14797 } while (facet != NULL);
14798 if (ok == 0)
14799 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014800
Daniel Veillard01fa6152004-06-29 17:04:39 +000014801 }
14802 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014803 * SPEC (3.3.2.5) (same as 1.3.2)
14804 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014805 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014806 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000014807 */
14808 }
14809 }
14810
14811 return (0);
14812}
14813
14814/**
14815 * xmlSchemaCheckSRCSimpleType:
14816 * @ctxt: the schema parser context
14817 * @type: the simple type definition
14818 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014819 * Checks crc-simple-type constraints.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014820 *
14821 * Returns 0 if the constraints are satisfied,
14822 * if not a positive error code and -1 on internal
14823 * errors.
14824 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014825#if 0
Daniel Veillard01fa6152004-06-29 17:04:39 +000014826static int
14827xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
14828 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014829{
14830 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014831 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014832 * must satisfy the conditions set out in Constraints on Simple Type
14833 * Definition Schema Components (§3.14.6).
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014834 */
14835 if (WXS_IS_RESTRICTION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014836 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014837 * src-simple-type.2 "If the <restriction> alternative is chosen,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014838 * either it must have a base [attribute] or a <simpleType> among its
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014839 * [children], but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014840 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014841 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014842 /*
14843 *
14844 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014845 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014846 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014847 * an itemType [attribute] or a <simpleType> among its [children],
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014848 * but not both."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014849 *
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014850 * NOTE: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014851 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014852 } else if (VARIETY_UNION(type)) {
14853 /*
14854 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014855 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014856 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014857 return (0);
14858}
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014859#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000014860
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014861static int
14862xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
14863{
14864 if (ctxt->vctxt == NULL) {
14865 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
14866 if (ctxt->vctxt == NULL) {
14867 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014868 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014869 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014870 "failed to create a temp. validation context.\n",
14871 NULL, NULL);
14872 return (-1);
14873 }
14874 /* TODO: Pass user data. */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014875 xmlSchemaSetValidErrors(ctxt->vctxt,
14876 ctxt->error, ctxt->warning, ctxt->userData);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014877 }
14878 return (0);
14879}
14880
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014881static int
14882xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
14883 xmlNodePtr node,
14884 xmlSchemaTypePtr type,
14885 const xmlChar *value,
14886 xmlSchemaValPtr *retVal,
14887 int fireErrors,
14888 int normalize,
14889 int isNormalized);
14890
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014891/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014892 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014893 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014894 * @type: the simple type definition
14895 * @value: the default value
14896 * @node: an optional node (the holder of the value)
14897 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014898 * Schema Component Constraint: Element Default Valid (Immediate)
14899 * (cos-valid-default)
14900 * This will be used by the parser only. For the validator there's
14901 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014902 *
14903 * Returns 0 if the constraints are satisfied,
14904 * if not, a positive error code and -1 on internal
14905 * errors.
14906 */
14907static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014908xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14909 xmlNodePtr node,
14910 xmlSchemaTypePtr type,
14911 const xmlChar *value,
14912 xmlSchemaValPtr *val)
14913{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014914 int ret = 0;
14915
14916 /*
14917 * cos-valid-default:
14918 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014919 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014920 * definition the appropriate case among the following must be true:
14921 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014922 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014923 /*
14924 * Complex type.
14925 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014926 * SPEC (2.1) "its {content type} must be a simple type definition
14927 * or mixed."
14928 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014929 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014930 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014931 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014932 if ((! HAS_SIMPLE_CONTENT(type)) &&
14933 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14934 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014935 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014936 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014937 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014938 "For a string to be a valid default, the type definition "
14939 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014940 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014941 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14942 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014943 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014944 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014945 * 1 If the type definition is a simple type definition, then the string
14946 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014947 * Valid (§3.14.4).
14948 *
14949 * AND
14950 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014951 * 2.2.1 If the {content type} is a simple type definition, then the
14952 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014953 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014954 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014955 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014956 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014957 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014958 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014959 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014960 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014961 else
14962 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014963
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014964 if (ret < 0) {
14965 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14966 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014967 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014968
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014969 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014970}
14971
14972/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014973 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014974 * @ctxt: the schema parser context
14975 * @type: the complex type definition
14976 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014977 *.(4.6) Constraints on Complex Type Definition Schema Components
14978 * Schema Component Constraint:
14979 * Complex Type Definition Properties Correct (ct-props-correct)
14980 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014981 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014982 * Returns 0 if the constraints are satisfied, a positive
14983 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014984 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014985static int
14986xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14987 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014988{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014989 /*
14990 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14991 *
14992 * SPEC (1) "The values of the properties of a complex type definition must
14993 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014994 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014995 * Sub-components (§5.3)."
14996 */
14997 if ((type->baseType != NULL) &&
14998 (IS_SIMPLE_TYPE(type->baseType)) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000014999 (WXS_IS_EXTENSION(type) == 0)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015000 /*
15001 * SPEC (2) "If the {base type definition} is a simple type definition,
15002 * the {derivation method} must be extension."
15003 */
15004 xmlSchemaPCustomErr(pctxt,
15005 XML_SCHEMAP_SRC_CT_1,
15006 NULL, type, NULL,
15007 "If the base type is a simple type, the derivation method must be "
15008 "'extension'", NULL);
15009 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015010 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015011 /*
15012 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
15013 * definition·. That is, it must be possible to reach the ·ur-type
15014 * definition by repeatedly following the {base type definition}."
15015 *
15016 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15017 *
15018 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015019 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015020 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
15021 * must not have {type definition}s which are or are derived from ID."
15022 *
15023 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
15024 */
15025 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015026}
15027
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015028static int
15029xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15030 xmlSchemaTypePtr typeB)
15031{
15032 /*
15033 * TODO: This should implement component-identity
15034 * in the future.
15035 */
15036 if ((typeA == NULL) || (typeB == NULL))
15037 return (0);
15038 return (typeA == typeB);
15039}
15040
15041/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015042 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015043 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015044 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015045 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000015046 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015047 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015048 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015049 * Type Derivation OK (Complex) (cos-ct-derived-ok)
15050 *
15051 * STATUS: completed
15052 *
15053 * Returns 0 if the constraints are satisfied, or 1
15054 * if not.
15055 */
15056static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015057xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015058 xmlSchemaTypePtr baseType,
15059 int set)
15060{
15061 int equal = xmlSchemaAreEqualTypes(type, baseType);
15062 /* TODO: Error codes. */
15063 /*
15064 * SPEC "For a complex type definition (call it D, for derived)
15065 * to be validly derived from a type definition (call this
15066 * B, for base) given a subset of {extension, restriction}
15067 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015068 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015069 if (! equal) {
15070 /*
15071 * SPEC (1) "If B and D are not the same type definition, then the
15072 * {derivation method} of D must not be in the subset."
15073 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015074 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
15075 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015076 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015077 } else {
15078 /*
15079 * SPEC (2.1) "B and D must be the same type definition."
15080 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015081 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015082 }
15083 /*
15084 * SPEC (2.2) "B must be D's {base type definition}."
15085 */
15086 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015087 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015088 /*
15089 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
15090 * definition·."
15091 */
15092 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015093 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015094
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015095 if (IS_COMPLEX_TYPE(type->baseType)) {
15096 /*
15097 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
15098 * must be validly derived from B given the subset as defined by this
15099 * constraint."
15100 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015101 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015102 baseType, set));
15103 } else {
15104 /*
15105 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
15106 * must be validly derived from B given the subset as defined in Type
15107 * Derivation OK (Simple) (§3.14.6).
15108 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015109 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
15110 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015111}
15112
15113/**
15114 * xmlSchemaCheckCOSDerivedOK:
15115 * @type: the derived simple type definition
15116 * @baseType: the base type definition
15117 *
15118 * Calls:
15119 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015120 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015121 * Checks wheter @type can be validly derived from @baseType.
15122 *
15123 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015124 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015125static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015126xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015127 xmlSchemaTypePtr baseType,
15128 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015129{
15130 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015131 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015132 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015133 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015134}
15135
William M. Brack2f2a6632004-08-20 23:09:47 +000015136/**
15137 * xmlSchemaCheckCOSCTExtends:
15138 * @ctxt: the schema parser context
15139 * @type: the complex type definition
15140 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015141 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015142 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015143 * Derivation Valid (Extension) (cos-ct-extends)
15144 *
15145 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015146 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015147 * (1.5)
15148 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000015149 *
15150 * Returns 0 if the constraints are satisfied, a positive
15151 * error code if not and -1 if an internal error occured.
15152 */
15153static int
15154xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
15155 xmlSchemaTypePtr type)
15156{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015157 xmlSchemaTypePtr base = type->baseType;
15158 /*
15159 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
15160 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000015161 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015162 /*
15163 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015164 * then all of the following must be true:"
15165 */
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +000015166 if (IS_COMPLEX_TYPE(base)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000015167 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015168 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015169 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000015170 */
15171 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
15172 xmlSchemaPCustomErr(ctxt,
15173 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
15174 NULL, type, NULL,
15175 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015176 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000015177 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
15178 }
15179 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015180 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015181 * uses}
15182 * of the complex type definition itself, that is, for every attribute
15183 * use in the {attribute uses} of the {base type definition}, there
15184 * must be an attribute use in the {attribute uses} of the complex
15185 * type definition itself whose {attribute declaration} has the same
15186 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015187 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000015188 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015189 * NOTE (1.2): This will be already satisfied by the way the attribute
15190 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
15191 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000015192 */
15193
15194 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015195 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
15196 * definition must also have one, and the base type definition's
15197 * {attribute wildcard}'s {namespace constraint} must be a subset
15198 * of the complex type definition's {attribute wildcard}'s {namespace
15199 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000015200 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015201 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015202 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000015203 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015204 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000015205 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015206 if ((type->contentTypeDef != NULL) &&
15207 (type->contentTypeDef == base->contentTypeDef)) {
15208 /*
15209 * SPEC (1.4.1) "The {content type} of the {base type definition}
15210 * and the {content type} of the complex type definition itself
15211 * must be the same simple type definition"
15212 * PASS
15213 */
15214 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
15215 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
15216 /*
15217 * SPEC (1.4.2) "The {content type} of both the {base type
15218 * definition} and the complex type definition itself must
15219 * be empty."
15220 * PASS
15221 */
15222 } else {
15223 /*
15224 * SPEC (1.4.3) "All of the following must be true:"
15225 */
15226 if (type->subtypes == NULL) {
15227 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015228 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015229 * definition itself must specify a particle.
15230 */
15231 xmlSchemaPCustomErr(ctxt,
15232 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
15233 NULL, type, NULL,
15234 "The content type must specify a particle", NULL);
15235 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
15236 }
15237 /*
15238 * SPEC (1.4.3.2) "One of the following must be true:"
15239 */
15240 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
15241 /*
15242 * SPEC (1.4.3.2.1) "The {content type} of the {base type
15243 * definition} must be empty.
15244 * PASS
15245 */
15246 } else {
15247 /*
15248 * SPEC (1.4.3.2.2) "All of the following must be true:"
15249 */
15250 if ((type->contentType != base->contentType) ||
15251 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
15252 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
15253 /*
15254 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
15255 * or both must be element-only."
15256 */
15257 xmlSchemaPCustomErr(ctxt,
15258 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
15259 NULL, type, NULL,
15260 "The content type of both, the type and its base "
15261 "type, must either 'mixed' or 'element-only'", NULL);
15262 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015263 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015264 /*
15265 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
15266 * complex type definition must be a ·valid extension·
15267 * of the {base type definition}'s particle, as defined
15268 * in Particle Valid (Extension) (§3.9.6)."
15269 *
15270 * NOTE that we won't check "Particle Valid (Extension)",
15271 * since it is ensured by the derivation process in
15272 * xmlSchemaTypeFixup(). We need to implement this when heading
15273 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015274 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015275 }
15276 /*
15277 * TODO (1.5)
15278 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015279 }
William M. Brack2f2a6632004-08-20 23:09:47 +000015280 } else {
15281 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015282 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015283 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000015284 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015285 if (type->contentTypeDef != base) {
15286 /*
15287 * SPEC (2.1) "The {content type} must be the same simple type
15288 * definition."
15289 */
15290 xmlSchemaPCustomErr(ctxt,
15291 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
15292 NULL, type, NULL,
15293 "The content type must be the simple base type", NULL);
15294 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
15295 }
15296 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
15297 /*
15298 * SPEC (2.2) "The {final} of the {base type definition} must not
15299 * contain extension"
15300 * NOTE that this is the same as (1.1).
15301 */
15302 xmlSchemaPCustomErr(ctxt,
15303 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
15304 NULL, type, NULL,
15305 "The 'final' of the base type definition "
15306 "contains 'extension'", NULL);
15307 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015308 }
William M. Brack2f2a6632004-08-20 23:09:47 +000015309 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015310 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015311}
15312
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015313/**
15314 * xmlSchemaCheckDerivationOKRestriction:
15315 * @ctxt: the schema parser context
15316 * @type: the complex type definition
15317 *
15318 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015319 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015320 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
15321 *
15322 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015323 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015324 * (5.4.2), (5.2.2.1)
15325 *
15326 * Returns 0 if the constraints are satisfied, a positive
15327 * error code if not and -1 if an internal error occured.
15328 */
15329static int
15330xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
15331 xmlSchemaTypePtr type)
15332{
15333 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015334
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015335 /*
15336 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
15337 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015338 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015339 base = type->baseType;
15340 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
15341 /*
15342 * SPEC (1) "The {base type definition} must be a complex type
15343 * definition whose {final} does not contain restriction."
15344 */
15345 xmlSchemaPCustomErr(ctxt,
15346 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
15347 NULL, type, NULL,
15348 "The 'final' of the base type definition "
15349 "contains 'restriction'", NULL);
15350 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
15351 }
15352 /*
15353 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
15354 *
15355 * SPEC (5) "One of the following must be true:"
15356 */
15357 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
15358 /*
15359 * SPEC (5.1) "The {base type definition} must be the
15360 * ·ur-type definition·."
15361 * PASS
15362 */
15363 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
15364 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
15365 /*
15366 * SPEC (5.2.1) "The {content type} of the complex type definition
15367 * must be a simple type definition"
15368 *
15369 * SPEC (5.2.2) "One of the following must be true:"
15370 */
15371 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
15372 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
15373 /*
15374 * SPEC (5.2.2.1) "The {content type} of the {base type
15375 * definition} must be a simple type definition from which
15376 * the {content type} is validly derived given the empty
15377 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
15378 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015379 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015380 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
15381 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015382 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015383 /*
15384 * SPEC (5.2.2.2) "The {base type definition} must be mixed
15385 * and have a particle which is ·emptiable· as defined in
15386 * Particle Emptiable (§3.9.6)."
15387 * PASS
15388 */
15389 } else {
15390 xmlSchemaPCustomErr(ctxt,
15391 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
15392 NULL, type, NULL,
15393 "The content type of the base type must be either "
15394 "a simple type or 'mixed' and an emptiable particle", NULL);
15395 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
15396 }
15397 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
15398 /*
15399 * SPEC (5.3.1) "The {content type} of the complex type itself must
15400 * be empty"
15401 */
15402 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
15403 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015404 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015405 * definition} must also be empty."
15406 * PASS
15407 */
15408 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
15409 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
15410 xmlSchemaIsParticleEmptiable(
15411 (xmlSchemaParticlePtr) base->subtypes)) {
15412 /*
15413 * SPEC (5.3.2.2) "The {content type} of the {base type
15414 * definition} must be elementOnly or mixed and have a particle
15415 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
15416 * PASS
15417 */
15418 } else {
15419 xmlSchemaPCustomErr(ctxt,
15420 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
15421 NULL, type, NULL,
15422 "The content type of the base type must be either "
15423 "empty or 'mixed' (or 'elements-only') and an emptiable "
15424 "particle", NULL);
15425 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
15426 }
15427 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015428 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015429 /*
15430 * SPEC (5.4.1.1) "The {content type} of the complex type definition
15431 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015432 */
15433 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
15434 /*
15435 * SPEC (5.4.1.2) "The {content type} of the complex type
15436 * definition itself and of the {base type definition} must be
15437 * mixed"
15438 */
15439 xmlSchemaPCustomErr(ctxt,
15440 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
15441 NULL, type, NULL,
15442 "If the content type is 'mixed', then the content type of the "
15443 "base type must also be 'mixed'", NULL);
15444 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
15445 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015446 /*
15447 * SPEC (5.4.2) "The particle of the complex type definition itself
15448 * must be a ·valid restriction· of the particle of the {content
15449 * type} of the {base type definition} as defined in Particle Valid
15450 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015451 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015452 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015453 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015454 } else {
15455 xmlSchemaPCustomErr(ctxt,
15456 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
15457 NULL, type, NULL,
15458 "The type is not a valid restriction of its base type", NULL);
15459 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
15460 }
15461 return (0);
15462}
15463
15464/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015465 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015466 * @ctxt: the schema parser context
15467 * @type: the complex type definition
15468 *
15469 * (3.4.6) Constraints on Complex Type Definition Schema Components
15470 *
15471 * Returns 0 if the constraints are satisfied, a positive
15472 * error code if not and -1 if an internal error occured.
15473 */
15474static int
15475xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
15476 xmlSchemaTypePtr type)
15477{
15478 int ret;
15479 /*
15480 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015481 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015482 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
15483 if (ret != 0)
15484 return (ret);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015485 if (WXS_IS_EXTENSION(type))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015486 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
15487 else
15488 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
15489 return (ret);
15490}
15491
15492/**
15493 * xmlSchemaCheckSRCCT:
15494 * @ctxt: the schema parser context
15495 * @type: the complex type definition
15496 *
15497 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015498 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015499 * Complex Type Definition Representation OK (src-ct)
15500 *
15501 * Returns 0 if the constraints are satisfied, a positive
15502 * error code if not and -1 if an internal error occured.
15503 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015504static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015505xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015506 xmlSchemaTypePtr type)
15507{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015508 xmlSchemaTypePtr base;
15509 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015510
15511 /*
15512 * TODO: Adjust the error codes here, as I used
15513 * XML_SCHEMAP_SRC_CT_1 only yet.
15514 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015515 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015516 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015517 /*
15518 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015519 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015520 * must be a complex type definition;
15521 */
15522 if (! IS_COMPLEX_TYPE(base)) {
15523 xmlChar *str = NULL;
15524 xmlSchemaPCustomErr(ctxt,
15525 XML_SCHEMAP_SRC_CT_1,
15526 NULL, type, type->node,
15527 "If using <complexContent>, the base type is expected to be "
15528 "a complex type. The base type '%s' is a simple type",
15529 xmlSchemaFormatQName(&str, base->targetNamespace,
15530 base->name));
15531 FREE_AND_NULL(str)
15532 return (XML_SCHEMAP_SRC_CT_1);
15533 }
15534 } else {
15535 /*
15536 * SPEC
15537 * 2 If the <simpleContent> alternative is chosen, all of the
15538 * following must be true:
15539 * 2.1 The type definition ·resolved· to by the ·actual value· of the
15540 * base [attribute] must be one of the following:
15541 */
15542 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015543 if (WXS_IS_EXTENSION(type) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015544 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015545 /*
15546 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015547 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015548 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015549 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015550 xmlSchemaPCustomErr(ctxt,
15551 XML_SCHEMAP_SRC_CT_1,
15552 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015553 "If using <simpleContent> and <restriction>, the base "
15554 "type must be a complex type. The base type '%s' is "
15555 "a simple type",
15556 xmlSchemaFormatQName(&str, base->targetNamespace,
15557 base->name));
15558 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015559 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015560 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015561 } else {
15562 /* Base type is a complex type. */
15563 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
15564 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
15565 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015566 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015567 * simple type definition;
15568 * PASS
15569 */
15570 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015571 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015572 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015573 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015574 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015575 type->name);
15576 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015577 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015578 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015579 (WXS_IS_RESTRICTION(type))) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015580
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015581 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015582 * 2.1.2 only if the <restriction> alternative is also
15583 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015584 * is mixed and a particle emptiable.
15585 */
15586 if (! xmlSchemaIsParticleEmptiable(
15587 (xmlSchemaParticlePtr) base->subtypes)) {
15588 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015589 } else
15590 /*
15591 * Attention: at this point the <simpleType> child is in
15592 * ->contentTypeDef (put there during parsing).
15593 */
15594 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015595 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015596 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015597 * 2.2 If clause 2.1.2 above is satisfied, then there
15598 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015599 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015600 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015601 /* TODO: Change error code to ..._SRC_CT_2_2. */
15602 xmlSchemaPCustomErr(ctxt,
15603 XML_SCHEMAP_SRC_CT_1,
15604 NULL, type, NULL,
15605 "A <simpleType> is expected among the children "
15606 "of <restriction>, if <simpleContent> is used and "
15607 "the base type '%s' is a complex type",
15608 xmlSchemaFormatQName(&str, base->targetNamespace,
15609 base->name));
15610 FREE_AND_NULL(str)
15611 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015612 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015613 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015614 ret = XML_SCHEMAP_SRC_CT_1;
15615 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015616 }
15617 if (ret > 0) {
15618 xmlChar *str = NULL;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000015619 if (WXS_IS_RESTRICTION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015620 xmlSchemaPCustomErr(ctxt,
15621 XML_SCHEMAP_SRC_CT_1,
15622 NULL, type, NULL,
15623 "If <simpleContent> and <restriction> is used, the "
15624 "base type must be a simple type or a complex type with "
15625 "mixed content and particle emptiable. The base type "
15626 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015627 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015628 base->name));
15629 } else {
15630 xmlSchemaPCustomErr(ctxt,
15631 XML_SCHEMAP_SRC_CT_1,
15632 NULL, type, NULL,
15633 "If <simpleContent> and <extension> is used, the "
15634 "base type must be a simple type. The base type '%s' "
15635 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015636 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015637 base->name));
15638 }
15639 FREE_AND_NULL(str)
15640 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015641 }
15642 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015643 * SPEC (3) "The corresponding complex type definition component must
15644 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015645 * Definition Schema Components (§3.4.6);"
15646 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015647 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015648 /*
15649 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015650 * above for {attribute wildcard} is satisfied, the intensional
15651 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015652 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015653 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015654 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015655 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015656}
William M. Brack2f2a6632004-08-20 23:09:47 +000015657
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015658#ifdef ENABLE_PARTICLE_RESTRICTION
15659/**
15660 * xmlSchemaCheckParticleRangeOK:
15661 * @ctxt: the schema parser context
15662 * @type: the complex type definition
15663 *
15664 * (3.9.6) Constraints on Particle Schema Components
15665 * Schema Component Constraint:
15666 * Occurrence Range OK (range-ok)
15667 *
15668 * STATUS: complete
15669 *
15670 * Returns 0 if the constraints are satisfied, a positive
15671 * error code if not and -1 if an internal error occured.
15672 */
15673static int
15674xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
15675 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015676{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015677 if (rmin < bmin)
15678 return (1);
15679 if ((bmax != UNBOUNDED) &&
15680 (rmax > bmax))
15681 return (1);
15682 return (0);
15683}
15684
15685/**
15686 * xmlSchemaCheckRCaseNameAndTypeOK:
15687 * @ctxt: the schema parser context
15688 * @r: the restricting element declaration particle
15689 * @b: the base element declaration particle
15690 *
15691 * (3.9.6) Constraints on Particle Schema Components
15692 * Schema Component Constraint:
15693 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
15694 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015695 *
15696 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015697 * MISSING (3.2.3)
15698 * CLARIFY: (3.2.2)
15699 *
15700 * Returns 0 if the constraints are satisfied, a positive
15701 * error code if not and -1 if an internal error occured.
15702 */
15703static int
15704xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
15705 xmlSchemaParticlePtr r,
15706 xmlSchemaParticlePtr b)
15707{
15708 xmlSchemaElementPtr elemR, elemB;
15709
15710 /* TODO: Error codes (rcase-NameAndTypeOK). */
15711 elemR = (xmlSchemaElementPtr) r->children;
15712 elemB = (xmlSchemaElementPtr) b->children;
15713 /*
15714 * SPEC (1) "The declarations' {name}s and {target namespace}s are
15715 * the same."
15716 */
15717 if ((elemR != elemB) &&
15718 ((! xmlStrEqual(elemR->name, elemB->name)) ||
15719 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
15720 return (1);
15721 /*
15722 * SPEC (2) "R's occurrence range is a valid restriction of B's
15723 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15724 */
15725 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15726 b->minOccurs, b->maxOccurs) != 0)
15727 return (1);
15728 /*
15729 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
15730 * {scope} are global."
15731 */
15732 if (elemR == elemB)
15733 return (0);
15734 /*
15735 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
15736 */
15737 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
15738 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
15739 return (1);
15740 /*
15741 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
15742 * or is not fixed, or R's declaration's {value constraint} is fixed
15743 * with the same value."
15744 */
15745 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
15746 ((elemR->value == NULL) ||
15747 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
15748 /* TODO: Equality of the initial value or normalized or canonical? */
15749 (! xmlStrEqual(elemR->value, elemB->value))))
15750 return (1);
15751 /*
15752 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
15753 * definitions} is a subset of B's declaration's {identity-constraint
15754 * definitions}, if any."
15755 */
15756 if (elemB->idcs != NULL) {
15757 /* TODO */
15758 }
15759 /*
15760 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
15761 * superset of B's declaration's {disallowed substitutions}."
15762 */
15763 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
15764 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
15765 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
15766 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
15767 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
15768 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
15769 return (1);
15770 /*
15771 * SPEC (3.2.5) "R's {type definition} is validly derived given
15772 * {extension, list, union} from B's {type definition}"
15773 *
15774 * BADSPEC TODO: What's the point of adding "list" and "union" to the
15775 * set, if the corresponding constraints handle "restriction" and
15776 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015777 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015778 */
15779 {
15780 int set = 0;
15781
15782 set |= SUBSET_EXTENSION;
15783 set |= SUBSET_LIST;
15784 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015785 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015786 elemB->subtypes, set) != 0)
15787 return (1);
15788 }
15789 return (0);
15790}
15791
15792/**
15793 * xmlSchemaCheckRCaseNSCompat:
15794 * @ctxt: the schema parser context
15795 * @r: the restricting element declaration particle
15796 * @b: the base wildcard particle
15797 *
15798 * (3.9.6) Constraints on Particle Schema Components
15799 * Schema Component Constraint:
15800 * Particle Derivation OK (Elt:Any -- NSCompat)
15801 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015802 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015803 * STATUS: complete
15804 *
15805 * Returns 0 if the constraints are satisfied, a positive
15806 * error code if not and -1 if an internal error occured.
15807 */
15808static int
15809xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
15810 xmlSchemaParticlePtr r,
15811 xmlSchemaParticlePtr b)
15812{
15813 /* TODO:Error codes (rcase-NSCompat). */
15814 /*
15815 * SPEC "For an element declaration particle to be a ·valid restriction·
15816 * of a wildcard particle all of the following must be true:"
15817 *
15818 * SPEC (1) "The element declaration's {target namespace} is ·valid·
15819 * with respect to the wildcard's {namespace constraint} as defined by
15820 * Wildcard allows Namespace Name (§3.10.4)."
15821 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015822 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015823 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
15824 return (1);
15825 /*
15826 * SPEC (2) "R's occurrence range is a valid restriction of B's
15827 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15828 */
15829 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15830 b->minOccurs, b->maxOccurs) != 0)
15831 return (1);
15832
15833 return (0);
15834}
15835
15836/**
15837 * xmlSchemaCheckRCaseRecurseAsIfGroup:
15838 * @ctxt: the schema parser context
15839 * @r: the restricting element declaration particle
15840 * @b: the base model group particle
15841 *
15842 * (3.9.6) Constraints on Particle Schema Components
15843 * Schema Component Constraint:
15844 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
15845 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015846 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015847 * STATUS: TODO
15848 *
15849 * Returns 0 if the constraints are satisfied, a positive
15850 * error code if not and -1 if an internal error occured.
15851 */
15852static int
15853xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
15854 xmlSchemaParticlePtr r,
15855 xmlSchemaParticlePtr b)
15856{
15857 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
15858 TODO
15859 return (0);
15860}
15861
15862/**
15863 * xmlSchemaCheckRCaseNSSubset:
15864 * @ctxt: the schema parser context
15865 * @r: the restricting wildcard particle
15866 * @b: the base wildcard particle
15867 *
15868 * (3.9.6) Constraints on Particle Schema Components
15869 * Schema Component Constraint:
15870 * Particle Derivation OK (Any:Any -- NSSubset)
15871 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015872 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015873 * STATUS: complete
15874 *
15875 * Returns 0 if the constraints are satisfied, a positive
15876 * error code if not and -1 if an internal error occured.
15877 */
15878static int
15879xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15880 xmlSchemaParticlePtr r,
15881 xmlSchemaParticlePtr b,
15882 int isAnyTypeBase)
15883{
15884 /* TODO: Error codes (rcase-NSSubset). */
15885 /*
15886 * SPEC (1) "R's occurrence range is a valid restriction of B's
15887 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15888 */
15889 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15890 b->minOccurs, b->maxOccurs))
15891 return (1);
15892 /*
15893 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15894 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15895 */
15896 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15897 (xmlSchemaWildcardPtr) b->children))
15898 return (1);
15899 /*
15900 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15901 * definition·, R's {process contents} must be identical to or stronger
15902 * than B's {process contents}, where strict is stronger than lax is
15903 * stronger than skip."
15904 */
15905 if (! isAnyTypeBase) {
15906 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15907 ((xmlSchemaWildcardPtr) b->children)->processContents)
15908 return (1);
15909 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015910
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015911 return (0);
15912}
15913
15914/**
15915 * xmlSchemaCheckCOSParticleRestrict:
15916 * @ctxt: the schema parser context
15917 * @type: the complex type definition
15918 *
15919 * (3.9.6) Constraints on Particle Schema Components
15920 * Schema Component Constraint:
15921 * Particle Valid (Restriction) (cos-particle-restrict)
15922 *
15923 * STATUS: TODO
15924 *
15925 * Returns 0 if the constraints are satisfied, a positive
15926 * error code if not and -1 if an internal error occured.
15927 */
15928static int
15929xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15930 xmlSchemaParticlePtr r,
15931 xmlSchemaParticlePtr b)
15932{
15933 int ret = 0;
15934
15935 /*part = GET_PARTICLE(type);
15936 basePart = GET_PARTICLE(base);
15937 */
15938
15939 TODO
15940
15941 /*
15942 * SPEC (1) "They are the same particle."
15943 */
15944 if (r == b)
15945 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015946
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015947
15948 return (0);
15949}
15950
15951/**
15952 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15953 * @ctxt: the schema parser context
15954 * @r: the model group particle
15955 * @b: the base wildcard particle
15956 *
15957 * (3.9.6) Constraints on Particle Schema Components
15958 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015959 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015960 * NSRecurseCheckCardinality)
15961 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015962 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015963 * STATUS: TODO: subst-groups
15964 *
15965 * Returns 0 if the constraints are satisfied, a positive
15966 * error code if not and -1 if an internal error occured.
15967 */
15968static int
15969xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15970 xmlSchemaParticlePtr r,
15971 xmlSchemaParticlePtr b)
15972{
15973 xmlSchemaParticlePtr part;
15974 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15975 if ((r->children == NULL) || (r->children->children == NULL))
15976 return (-1);
15977 /*
15978 * SPEC "For a group particle to be a ·valid restriction· of a
15979 * wildcard particle..."
15980 *
15981 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015982 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015983 * Particle Valid (Restriction) (§3.9.6)."
15984 */
15985 part = (xmlSchemaParticlePtr) r->children->children;
15986 do {
15987 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15988 return (1);
15989 part = (xmlSchemaParticlePtr) part->next;
15990 } while (part != NULL);
15991 /*
15992 * SPEC (2) "The effective total range of the group [...] is a
15993 * valid restriction of B's occurrence range as defined by
15994 * Occurrence Range OK (§3.9.6)."
15995 */
15996 if (xmlSchemaCheckParticleRangeOK(
15997 xmlSchemaGetParticleTotalRangeMin(r),
15998 xmlSchemaGetParticleTotalRangeMax(r),
15999 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016000 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016001 return (0);
16002}
16003
16004/**
16005 * xmlSchemaCheckRCaseRecurse:
16006 * @ctxt: the schema parser context
16007 * @r: the <all> or <sequence> model group particle
16008 * @b: the base <all> or <sequence> model group particle
16009 *
16010 * (3.9.6) Constraints on Particle Schema Components
16011 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016012 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016013 Recurse)
16014 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016015 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016016 * STATUS: ?
16017 * TODO: subst-groups
16018 *
16019 * Returns 0 if the constraints are satisfied, a positive
16020 * error code if not and -1 if an internal error occured.
16021 */
16022static int
16023xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
16024 xmlSchemaParticlePtr r,
16025 xmlSchemaParticlePtr b)
16026{
16027 /* xmlSchemaParticlePtr part; */
16028 /* TODO: Error codes (rcase-Recurse). */
16029 if ((r->children == NULL) || (b->children == NULL) ||
16030 (r->children->type != b->children->type))
16031 return (-1);
16032 /*
16033 * SPEC "For an all or sequence group particle to be a ·valid
16034 * restriction· of another group particle with the same {compositor}..."
16035 *
16036 * SPEC (1) "R's occurrence range is a valid restriction of B's
16037 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
16038 */
16039 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16040 b->minOccurs, b->maxOccurs))
16041 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016042
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000016043
16044 return (0);
16045}
16046
16047#endif
16048
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016049#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
16050 xmlSchemaPCustomErrExt(pctxt, \
16051 XML_SCHEMAP_INVALID_FACET_VALUE, \
16052 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
16053 "It is an error for both '%s' and '%s' to be specified on the "\
16054 "same type definition", \
16055 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
16056 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
16057
16058#define FACET_RESTR_ERR(fac1, msg) \
16059 xmlSchemaPCustomErr(pctxt, \
16060 XML_SCHEMAP_INVALID_FACET_VALUE, \
16061 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016062 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016063
16064#define FACET_RESTR_FIXED_ERR(fac) \
16065 xmlSchemaPCustomErr(pctxt, \
16066 XML_SCHEMAP_INVALID_FACET_VALUE, \
16067 NULL, (xmlSchemaTypePtr) fac, fac->node, \
16068 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016069 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016070
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016071static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016072xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
16073 xmlSchemaFacetPtr facet1,
16074 xmlSchemaFacetPtr facet2,
16075 int lessGreater,
16076 int orEqual,
16077 int ofBase)
16078{
16079 xmlChar *msg = NULL;
16080
16081 msg = xmlStrdup(BAD_CAST "'");
16082 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
16083 msg = xmlStrcat(msg, BAD_CAST "' has to be");
16084 if (lessGreater == 0)
16085 msg = xmlStrcat(msg, BAD_CAST " equal to");
16086 if (lessGreater == 1)
16087 msg = xmlStrcat(msg, BAD_CAST " greater than");
16088 else
16089 msg = xmlStrcat(msg, BAD_CAST " less than");
16090
16091 if (orEqual)
16092 msg = xmlStrcat(msg, BAD_CAST " or equal to");
16093 msg = xmlStrcat(msg, BAD_CAST " '");
16094 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
16095 if (ofBase)
16096 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
16097 else
16098 msg = xmlStrcat(msg, BAD_CAST "'");
16099
16100 xmlSchemaPCustomErr(pctxt,
16101 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016102 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016103 (const char *) msg, NULL);
16104
16105 if (msg != NULL)
16106 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016107}
16108
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016109/*
16110* xmlSchemaDeriveAndValidateFacets:
16111*
16112* Schema Component Constraint: Simple Type Restriction (Facets)
16113* (st-restrict-facets)
16114*/
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016115static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016116xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
16117 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016118{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016119 xmlSchemaTypePtr base = type->baseType;
16120 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016121 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016122 flength = NULL, ftotdig = NULL, ffracdig = NULL,
16123 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
16124 fmininc = NULL, fmaxinc = NULL,
16125 fminexc = NULL, fmaxexc = NULL,
16126 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
16127 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
16128 bfmininc = NULL, bfmaxinc = NULL,
16129 bfminexc = NULL, bfmaxexc = NULL;
16130 int res, err = 0, fixedErr;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016131
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016132 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016133 * SPEC st-restrict-facets 1:
16134 * "The {variety} of R is the same as that of B."
16135 */
16136 /*
16137 * SPEC st-restrict-facets 2:
16138 * "If {variety} is atomic, the {primitive type definition}
16139 * of R is the same as that of B."
16140 *
16141 * NOTE: we leave 1 & 2 out for now, since this will be
16142 * satisfied by the derivation process.
16143 * CONSTRUCTION TODO: Maybe needed if using a construction API.
16144 */
16145 /*
16146 * SPEC st-restrict-facets 3:
16147 * "The {facets} of R are the union of S and the {facets}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016148 * of B, eliminating duplicates. To eliminate duplicates,
16149 * when a facet of the same kind occurs in both S and the
16150 * {facets} of B, the one in the {facets} of B is not
16151 * included, with the exception of enumeration and pattern
16152 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016153 * are allowed."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016154 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016155
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016156 if ((type->facetSet == NULL) && (base->facetSet == NULL))
16157 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016158
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016159 last = type->facetSet;
16160 if (last != NULL)
16161 while (last->next != NULL)
16162 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016163
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016164 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
16165 facet = cur->facet;
16166 switch (facet->type) {
16167 case XML_SCHEMA_FACET_LENGTH:
16168 flength = facet; break;
16169 case XML_SCHEMA_FACET_MINLENGTH:
16170 fminlen = facet; break;
16171 case XML_SCHEMA_FACET_MININCLUSIVE:
16172 fmininc = facet; break;
16173 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16174 fminexc = facet; break;
16175 case XML_SCHEMA_FACET_MAXLENGTH:
16176 fmaxlen = facet; break;
16177 case XML_SCHEMA_FACET_MAXINCLUSIVE:
16178 fmaxinc = facet; break;
16179 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16180 fmaxexc = facet; break;
16181 case XML_SCHEMA_FACET_TOTALDIGITS:
16182 ftotdig = facet; break;
16183 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16184 ffracdig = facet; break;
16185 default:
16186 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016187 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016188 }
16189 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
16190 facet = cur->facet;
16191 switch (facet->type) {
16192 case XML_SCHEMA_FACET_LENGTH:
16193 bflength = facet; break;
16194 case XML_SCHEMA_FACET_MINLENGTH:
16195 bfminlen = facet; break;
16196 case XML_SCHEMA_FACET_MININCLUSIVE:
16197 bfmininc = facet; break;
16198 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16199 bfminexc = facet; break;
16200 case XML_SCHEMA_FACET_MAXLENGTH:
16201 bfmaxlen = facet; break;
16202 case XML_SCHEMA_FACET_MAXINCLUSIVE:
16203 bfmaxinc = facet; break;
16204 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16205 bfmaxexc = facet; break;
16206 case XML_SCHEMA_FACET_TOTALDIGITS:
16207 bftotdig = facet; break;
16208 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16209 bffracdig = facet; break;
16210 default:
16211 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016212 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016213 }
16214 err = 0;
16215 /*
16216 * length and minLength or maxLength (2.2) + (3.2)
16217 */
16218 if (flength && (fminlen || fmaxlen)) {
16219 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
16220 "either of 'minLength' or 'maxLength' to be specified on "
16221 "the same type definition")
16222 }
16223 /*
16224 * Mutual exclusions in the same derivation step.
16225 */
16226 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016227 /*
16228 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016229 */
16230 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
16231 }
16232 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016233 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016234 * SCC "minInclusive and minExclusive"
16235 */
16236 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016237 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016238
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016239 if (flength && bflength) {
16240 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016241 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016242 * The values have to be equal.
16243 */
16244 res = xmlSchemaCompareValues(flength->val, bflength->val);
16245 if (res == -2)
16246 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016247 if (res != 0)
16248 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
16249 if ((res != 0) && (bflength->fixed)) {
16250 FACET_RESTR_FIXED_ERR(flength)
16251 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016252
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016253 }
16254 if (fminlen && bfminlen) {
16255 /*
16256 * SCC "minLength valid restriction"
16257 * minLength >= BASE minLength
16258 */
16259 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
16260 if (res == -2)
16261 goto internal_error;
16262 if (res == -1)
16263 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
16264 if ((res != 0) && (bfminlen->fixed)) {
16265 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016266 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016267 }
16268 if (fmaxlen && bfmaxlen) {
16269 /*
16270 * SCC "maxLength valid restriction"
16271 * maxLength <= BASE minLength
16272 */
16273 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
16274 if (res == -2)
16275 goto internal_error;
16276 if (res == 1)
16277 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
16278 if ((res != 0) && (bfmaxlen->fixed)) {
16279 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016280 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016281 }
16282 /*
16283 * SCC "length and minLength or maxLength"
16284 */
16285 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016286 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016287 if (flength) {
16288 if (! fminlen)
16289 flength = bflength;
16290 if (fminlen) {
16291 /* (1.1) length >= minLength */
16292 res = xmlSchemaCompareValues(flength->val, fminlen->val);
16293 if (res == -2)
16294 goto internal_error;
16295 if (res == -1)
16296 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
16297 }
16298 if (! fmaxlen)
16299 fmaxlen = bfmaxlen;
16300 if (fmaxlen) {
16301 /* (2.1) length <= maxLength */
16302 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
16303 if (res == -2)
16304 goto internal_error;
16305 if (res == 1)
16306 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
16307 }
16308 }
16309 if (fmaxinc) {
16310 /*
16311 * "maxInclusive"
16312 */
16313 if (fmininc) {
16314 /* SCC "maxInclusive >= minInclusive" */
16315 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
16316 if (res == -2)
16317 goto internal_error;
16318 if (res == -1) {
16319 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
16320 }
16321 }
16322 /*
16323 * SCC "maxInclusive valid restriction"
16324 */
16325 if (bfmaxinc) {
16326 /* maxInclusive <= BASE maxInclusive */
16327 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
16328 if (res == -2)
16329 goto internal_error;
16330 if (res == 1)
16331 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
16332 if ((res != 0) && (bfmaxinc->fixed)) {
16333 FACET_RESTR_FIXED_ERR(fmaxinc)
16334 }
16335 }
16336 if (bfmaxexc) {
16337 /* maxInclusive < BASE maxExclusive */
16338 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
16339 if (res == -2)
16340 goto internal_error;
16341 if (res != -1) {
16342 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
16343 }
16344 }
16345 if (bfmininc) {
16346 /* maxInclusive >= BASE minInclusive */
16347 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
16348 if (res == -2)
16349 goto internal_error;
16350 if (res == -1) {
16351 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
16352 }
16353 }
16354 if (bfminexc) {
16355 /* maxInclusive > BASE minExclusive */
16356 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
16357 if (res == -2)
16358 goto internal_error;
16359 if (res != 1) {
16360 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
16361 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016362 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016363 }
16364 if (fmaxexc) {
16365 /*
16366 * "maxExclusive >= minExclusive"
16367 */
16368 if (fminexc) {
16369 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
16370 if (res == -2)
16371 goto internal_error;
16372 if (res == -1) {
16373 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
16374 }
16375 }
16376 /*
16377 * "maxExclusive valid restriction"
16378 */
16379 if (bfmaxexc) {
16380 /* maxExclusive <= BASE maxExclusive */
16381 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
16382 if (res == -2)
16383 goto internal_error;
16384 if (res == 1) {
16385 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
16386 }
16387 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016388 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016389 }
16390 }
16391 if (bfmaxinc) {
16392 /* maxExclusive <= BASE maxInclusive */
16393 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
16394 if (res == -2)
16395 goto internal_error;
16396 if (res == 1) {
16397 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
16398 }
16399 }
16400 if (bfmininc) {
16401 /* maxExclusive > BASE minInclusive */
16402 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
16403 if (res == -2)
16404 goto internal_error;
16405 if (res != 1) {
16406 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
16407 }
16408 }
16409 if (bfminexc) {
16410 /* maxExclusive > BASE minExclusive */
16411 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
16412 if (res == -2)
16413 goto internal_error;
16414 if (res != 1) {
16415 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
16416 }
16417 }
16418 }
16419 if (fminexc) {
16420 /*
16421 * "minExclusive < maxInclusive"
16422 */
16423 if (fmaxinc) {
16424 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
16425 if (res == -2)
16426 goto internal_error;
16427 if (res != -1) {
16428 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
16429 }
16430 }
16431 /*
16432 * "minExclusive valid restriction"
16433 */
16434 if (bfminexc) {
16435 /* minExclusive >= BASE minExclusive */
16436 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
16437 if (res == -2)
16438 goto internal_error;
16439 if (res == -1) {
16440 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
16441 }
16442 if ((res != 0) && (bfminexc->fixed)) {
16443 FACET_RESTR_FIXED_ERR(fminexc)
16444 }
16445 }
16446 if (bfmaxinc) {
16447 /* minExclusive <= BASE maxInclusive */
16448 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
16449 if (res == -2)
16450 goto internal_error;
16451 if (res == 1) {
16452 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
16453 }
16454 }
16455 if (bfmininc) {
16456 /* minExclusive >= BASE minInclusive */
16457 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
16458 if (res == -2)
16459 goto internal_error;
16460 if (res == -1) {
16461 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
16462 }
16463 }
16464 if (bfmaxexc) {
16465 /* minExclusive < BASE maxExclusive */
16466 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
16467 if (res == -2)
16468 goto internal_error;
16469 if (res != -1) {
16470 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
16471 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016472 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016473 }
16474 if (fmininc) {
16475 /*
16476 * "minInclusive < maxExclusive"
16477 */
16478 if (fmaxexc) {
16479 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
16480 if (res == -2)
16481 goto internal_error;
16482 if (res != -1) {
16483 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
16484 }
16485 }
16486 /*
16487 * "minExclusive valid restriction"
16488 */
16489 if (bfmininc) {
16490 /* minInclusive >= BASE minInclusive */
16491 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
16492 if (res == -2)
16493 goto internal_error;
16494 if (res == -1) {
16495 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
16496 }
16497 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016498 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016499 }
16500 }
16501 if (bfmaxinc) {
16502 /* minInclusive <= BASE maxInclusive */
16503 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
16504 if (res == -2)
16505 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000016506 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016507 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
16508 }
16509 }
16510 if (bfminexc) {
16511 /* minInclusive > BASE minExclusive */
16512 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
16513 if (res == -2)
16514 goto internal_error;
16515 if (res != 1)
16516 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
16517 }
16518 if (bfmaxexc) {
16519 /* minInclusive < BASE maxExclusive */
16520 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
16521 if (res == -2)
16522 goto internal_error;
16523 if (res != -1)
16524 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
16525 }
16526 }
16527 if (ftotdig && bftotdig) {
16528 /*
16529 * SCC " totalDigits valid restriction"
16530 * totalDigits <= BASE totalDigits
16531 */
16532 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
16533 if (res == -2)
16534 goto internal_error;
16535 if (res == 1)
16536 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
16537 -1, 1, 1);
16538 if ((res != 0) && (bftotdig->fixed)) {
16539 FACET_RESTR_FIXED_ERR(ftotdig)
16540 }
16541 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016542 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016543 /*
16544 * SCC "fractionDigits valid restriction"
16545 * fractionDigits <= BASE fractionDigits
16546 */
16547 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
16548 if (res == -2)
16549 goto internal_error;
16550 if (res == 1)
16551 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
16552 -1, 1, 1);
16553 if ((res != 0) && (bffracdig->fixed)) {
16554 FACET_RESTR_FIXED_ERR(ffracdig)
16555 }
16556 }
16557 /*
16558 * SCC "fractionDigits less than or equal to totalDigits"
16559 */
16560 if (! ftotdig)
16561 ftotdig = bftotdig;
16562 if (! ffracdig)
16563 ffracdig = bffracdig;
16564 if (ftotdig && ffracdig) {
16565 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
16566 if (res == -2)
16567 goto internal_error;
16568 if (res == 1)
16569 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
16570 -1, 1, 0);
16571 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016572 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016573 * *Enumerations* won' be added here, since only the first set
16574 * of enumerations in the ancestor-or-self axis is used
16575 * for validation, plus we need to use the base type of those
16576 * enumerations for whitespace.
16577 *
16578 * *Patterns*: won't be add here, since they are ORed at
16579 * type level and ANDed at ancestor level. This will
16580 * happed during validation by walking the base axis
16581 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016582 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016583 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
16584 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016585 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016586 * Special handling of enumerations and patterns.
16587 * TODO: hmm, they should not appear in the set, so remove this.
16588 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016589 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016590 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016591 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016592 /*
16593 * Search for a duplicate facet in the current type.
16594 */
16595 link = type->facetSet;
16596 err = 0;
16597 fixedErr = 0;
16598 while (link != NULL) {
16599 facet = link->facet;
16600 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016601 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016602 case XML_SCHEMA_FACET_WHITESPACE:
16603 /*
16604 * The whitespace must be stronger.
16605 */
16606 if (facet->whitespace < bfacet->whitespace) {
16607 FACET_RESTR_ERR(flength,
16608 "The 'whitespace' value has to be equal to "
16609 "or stronger than the 'whitespace' value of "
16610 "the base type")
16611 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016612 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016613 (facet->whitespace != bfacet->whitespace)) {
16614 FACET_RESTR_FIXED_ERR(facet)
16615 }
16616 break;
16617 default:
16618 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016619 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016620 /* Duplicate found. */
16621 break;
16622 }
16623 link = link->next;
16624 }
16625 /*
16626 * If no duplicate was found: add the base types's facet
16627 * to the set.
16628 */
16629 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016630 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016631 xmlMalloc(sizeof(xmlSchemaFacetLink));
16632 if (link == NULL) {
16633 xmlSchemaPErrMemory(pctxt,
16634 "deriving facets, creating a facet link", NULL);
16635 return (-1);
16636 }
16637 link->facet = cur->facet;
16638 link->next = NULL;
16639 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016640 type->facetSet = link;
16641 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016642 last->next = link;
16643 last = link;
16644 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016645
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016646 }
16647
16648 return (0);
16649internal_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016650 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
16651 "an error occured");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016652 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016653}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016654
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016655static int
16656xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
16657 xmlSchemaTypePtr type)
16658{
16659 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
16660 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016661 * The actual value is then formed by replacing any union type
16662 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016663 * {member type definitions}, in order.
16664 */
16665 link = type->memberTypes;
16666 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016667
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016668 if (IS_NOT_TYPEFIXED(link->type))
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016669 xmlSchemaTypeFixup(link->type, pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016670
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016671 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016672 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016673 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016674 link->type = subLink->type;
16675 if (subLink->next != NULL) {
16676 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016677 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016678 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016679 while (subLink != NULL) {
16680 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016681 xmlMalloc(sizeof(xmlSchemaTypeLink));
16682 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016683 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016684 NULL);
16685 return (-1);
16686 }
16687 newLink->type = subLink->type;
16688 prevLink->next = newLink;
16689 prevLink = newLink;
16690 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016691
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016692 subLink = subLink->next;
16693 }
16694 }
16695 }
16696 }
16697 link = link->next;
16698 }
16699 return (0);
16700}
16701
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016702static void
16703xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
16704{
16705 int has = 0, needVal = 0, normVal = 0;
16706
16707 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
16708 if (has) {
16709 needVal = (type->baseType->flags &
16710 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
16711 normVal = (type->baseType->flags &
16712 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
16713 }
16714 if (type->facets != NULL) {
16715 xmlSchemaFacetPtr fac;
16716
16717 for (fac = type->facets; fac != NULL; fac = fac->next) {
16718 switch (fac->type) {
16719 case XML_SCHEMA_FACET_WHITESPACE:
16720 break;
16721 case XML_SCHEMA_FACET_PATTERN:
16722 normVal = 1;
16723 has = 1;
16724 break;
16725 case XML_SCHEMA_FACET_ENUMERATION:
16726 needVal = 1;
16727 normVal = 1;
16728 has = 1;
16729 break;
16730 default:
16731 has = 1;
16732 break;
16733 }
16734 }
16735 }
16736 if (normVal)
16737 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
16738 if (needVal)
16739 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
16740 if (has)
16741 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
16742
16743 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
16744 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
16745 /*
16746 * OPTIMIZE VAL TODO: Some facets need a computed value.
16747 */
16748 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
16749 (prim->builtInType != XML_SCHEMAS_STRING)) {
16750 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
16751 }
16752 }
16753}
16754
16755static int
16756xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
16757{
16758
16759
16760 /*
16761 * Evaluate the whitespace-facet value.
16762 */
16763 if (VARIETY_LIST(type)) {
16764 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
16765 return (0);
16766 } else if (VARIETY_UNION(type))
16767 return (0);
16768
16769 if (type->facetSet != NULL) {
16770 xmlSchemaFacetLinkPtr lin;
16771
16772 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
16773 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
16774 switch (lin->facet->whitespace) {
16775 case XML_SCHEMAS_FACET_PRESERVE:
16776 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
16777 break;
16778 case XML_SCHEMAS_FACET_REPLACE:
16779 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
16780 break;
16781 case XML_SCHEMAS_FACET_COLLAPSE:
16782 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
16783 break;
16784 default:
16785 return (-1);
16786 }
16787 return (0);
16788 }
16789 }
16790 }
16791 /*
16792 * For all ·atomic· datatypes other than string (and types ·derived·
16793 * by ·restriction· from it) the value of whiteSpace is fixed to
16794 * collapse
16795 */
16796 {
16797 xmlSchemaTypePtr anc;
16798
16799 for (anc = type->baseType; anc != NULL &&
16800 anc->builtInType != XML_SCHEMAS_ANYTYPE;
16801 anc = anc->baseType) {
16802
16803 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
16804 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
16805 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
16806
16807 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
16808 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
16809 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
16810
16811 } else
16812 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
16813 break;
16814 }
16815 }
16816 return (0);
16817 }
16818 return (0);
16819}
16820
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016821static int
16822xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
16823 xmlSchemaTypePtr type)
Daniel Veillard4255d502002-04-16 15:50:10 +000016824{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016825 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
16826 return(0);
16827 if (! TYPE_IS_NOT_FIXEDUP_1(type))
16828 return(0);
16829 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016830
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016831 if (VARIETY_LIST(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016832 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016833 * Corresponds to <simpleType><list>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016834 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016835 if (type->subtypes == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016836 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016837 * This one is really needed, so get out.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016838 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016839 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016840 "list type has no item-type assigned");
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016841 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016842 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016843 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016844 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016845 * Corresponds to <simpleType><union>...
16846 */
16847 if (type->memberTypes == NULL) {
16848 /*
16849 * This one is really needed, so get out.
16850 */
16851 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
16852 "union type has no member-types assigned");
16853 return(-1);
16854 }
16855 } else {
16856 /*
16857 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016858 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016859 if (type->baseType == NULL) {
16860 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
16861 "type has no base-type assigned");
16862 return(-1);
16863 }
16864 if (TYPE_IS_NOT_FIXEDUP_1(type->baseType))
16865 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
16866 return(-1);
16867 /*
16868 * Variety
16869 * If the <restriction> alternative is chosen, then the
16870 * {variety} of the {base type definition}.
16871 */
16872 if (VARIETY_ATOMIC(type->baseType))
16873 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
16874 else if (VARIETY_LIST(type->baseType)) {
16875 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016876 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016877 * Inherit the itemType.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016878 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016879 type->subtypes = type->baseType->subtypes;
16880 } else if (VARIETY_UNION(type->baseType)) {
16881 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016882 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016883 * NOTE that we won't assign the memberTypes of the base,
16884 * since this will make trouble when freeing them; we will
16885 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016886 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016887 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016888 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016889 return(0);
16890}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016891
Daniel Veillard8651f532002-04-17 09:06:27 +000016892#ifdef DEBUG_TYPE
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016893xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
16894 xmlSchemaTypePtr type)
16895{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016896 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016897 xmlGenericError(xmlGenericErrorContext,
16898 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016899 type->node->doc->URL,
16900 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016901 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016902 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016903 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016904 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16905 switch (type->contentType) {
16906 case XML_SCHEMA_CONTENT_SIMPLE:
16907 xmlGenericError(xmlGenericErrorContext, "simple\n");
16908 break;
16909 case XML_SCHEMA_CONTENT_ELEMENTS:
16910 xmlGenericError(xmlGenericErrorContext, "elements\n");
16911 break;
16912 case XML_SCHEMA_CONTENT_UNKNOWN:
16913 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16914 break;
16915 case XML_SCHEMA_CONTENT_EMPTY:
16916 xmlGenericError(xmlGenericErrorContext, "empty\n");
16917 break;
16918 case XML_SCHEMA_CONTENT_MIXED:
16919 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016920 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016921 xmlGenericError(xmlGenericErrorContext,
16922 "mixed as emptiable particle\n");
16923 else
16924 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16925 break;
16926 /* Removed, since not used. */
16927 /*
16928 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16929 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16930 break;
16931 */
16932 case XML_SCHEMA_CONTENT_BASIC:
16933 xmlGenericError(xmlGenericErrorContext, "basic\n");
16934 break;
16935 default:
16936 xmlGenericError(xmlGenericErrorContext,
16937 "not registered !!!\n");
16938 break;
16939 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016940 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016941}
Daniel Veillard8651f532002-04-17 09:06:27 +000016942#endif
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000016943
16944/*
16945* 3.14.6 Constraints on Simple Type Definition Schema Components
16946*/
16947static int
16948xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
16949 xmlSchemaTypePtr type)
16950{
16951 int res, olderrs = pctxt->nberrors;
16952
16953 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
16954 return(-1);
16955
16956 if (! IS_NOT_TYPEFIXED(type))
16957 return(0);
16958
16959 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
16960 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16961
16962 if (type->baseType == NULL) {
16963 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
16964 "missing baseType");
16965 goto exit_failure;
16966 }
16967 if (IS_NOT_TYPEFIXED(type->baseType))
16968 xmlSchemaTypeFixup(type->baseType, pctxt);
16969 /*
16970 * If a member type of a union is a union itself, we need to substitute
16971 * that member type for its member types.
16972 */
16973 if ((type->memberTypes != NULL) &&
16974 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
16975 return(-1);
16976 /*
16977 * SPEC src-simple-type 1
16978 * "The corresponding simple type definition, if any, must satisfy
16979 * the conditions set out in Constraints on Simple Type Definition
16980 * Schema Components (§3.14.6)."
16981 */
16982 /*
16983 * Schema Component Constraint: Simple Type Definition Properties Correct
16984 * (st-props-correct)
16985 */
16986 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
16987 HFAILURE HERROR
16988 /*
16989 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
16990 * (cos-st-restricts)
16991 */
16992 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
16993 HFAILURE HERROR
16994 /*
16995 * TODO: Removed the error report, since it got annoying to get an
16996 * extra error report, if anything failed until now.
16997 * Enable this if needed.
16998 *
16999 * xmlSchemaPErr(ctxt, type->node,
17000 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
17001 * "Simple type '%s' does not satisfy the constraints "
17002 * "on simple type definitions.\n",
17003 * type->name, NULL);
17004 */
17005 /*
17006 * Schema Component Constraint: Simple Type Restriction (Facets)
17007 * (st-restrict-facets)
17008 */
17009 res = xmlSchemaCheckFacetValues(type, pctxt);
17010 HFAILURE HERROR
17011 if ((type->facetSet != NULL) ||
17012 (type->baseType->facetSet != NULL)) {
17013 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
17014 HFAILURE HERROR
17015 }
17016 /*
17017 * Whitespace value.
17018 */
17019 res = xmlSchemaTypeFixupWhitespace(type);
17020 HFAILURE HERROR
17021 xmlSchemaTypeFixupOptimFacets(type);
17022
17023exit_error:
17024#ifdef DEBUG_TYPE
17025 xmlSchemaDebugFixedType(pctxt, type);
17026#endif
17027 if (olderrs != pctxt->nberrors)
17028 return(pctxt->err);
17029 return(0);
17030
17031exit_failure:
17032#ifdef DEBUG_TYPE
17033 xmlSchemaDebugFixedType(pctxt, type);
17034#endif
17035 return(-1);
17036}
17037
17038static int
17039xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
17040 xmlSchemaTypePtr type)
17041{
17042 int res = 0, olderrs = pctxt->nberrors;
17043 xmlSchemaTypePtr baseType = type->baseType;
17044
17045 if (! IS_NOT_TYPEFIXED(type))
17046 return(0);
17047 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17048 if (baseType == NULL) {
17049 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
17050 "missing baseType");
17051 goto exit_failure;
17052 }
17053 /*
17054 * Fixup the base type.
17055 */
17056 if (IS_NOT_TYPEFIXED(baseType))
17057 xmlSchemaTypeFixup(baseType, pctxt);
17058 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
17059 /*
17060 * Skip fixup if the base type is invalid.
17061 * TODO: Generate a warning!
17062 */
17063 return(0);
17064 }
17065 /*
17066 * This basically checks if the base type can be derived.
17067 */
17068 res = xmlSchemaCheckSRCCT(pctxt, type);
17069 HFAILURE HERROR
17070 /*
17071 * Fixup the content type.
17072 */
17073 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
17074 /*
17075 * Corresponds to <complexType><simpleContent>...
17076 */
17077 if ((IS_COMPLEX_TYPE(baseType)) &&
17078 (baseType->contentTypeDef != NULL) &&
17079 (WXS_IS_RESTRICTION(type))) {
17080 xmlSchemaTypePtr contentBase, content;
17081#ifdef ENABLE_NAMED_LOCALS
17082 char buf[30];
17083 const xmlChar *tmpname;
17084#endif
17085 /*
17086 * SPEC (1) If <restriction> + base type is <complexType>,
17087 * "whose own {content type} is a simple type..."
17088 */
17089 if (type->contentTypeDef != NULL) {
17090 /*
17091 * SPEC (1.1) "the simple type definition corresponding to the
17092 * <simpleType> among the [children] of <restriction> if there
17093 * is one;"
17094 * Note that this "<simpleType> among the [children]" was put
17095 * into ->contentTypeDef during parsing.
17096 */
17097 contentBase = type->contentTypeDef;
17098 type->contentTypeDef = NULL;
17099 } else {
17100 /*
17101 * (1.2) "...otherwise (<restriction> has no <simpleType>
17102 * among its [children]), the simple type definition which
17103 * is the {content type} of the ... base type."
17104 */
17105 contentBase = baseType->contentTypeDef;
17106 }
17107 /*
17108 * SPEC
17109 * "... a simple type definition which restricts the simple
17110 * type definition identified in clause 1.1 or clause 1.2
17111 * with a set of facet components"
17112 *
17113 * Create the anonymous simple type, which will be the content
17114 * type of the complex type.
17115 */
17116#ifdef ENABLE_NAMED_LOCALS
17117 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
17118 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
17119 content = xmlSchemaAddType(pctxt,
17120 pctxt->schema, tmpname, type->targetNamespace,
17121 type->node, 0);
17122#else
17123 content = xmlSchemaAddType(pctxt,
17124 pctxt->schema, NULL, type->targetNamespace,
17125 type->node, 0);
17126#endif
17127 if (content == NULL)
17128 goto exit_failure;
17129 /*
17130 * We will use the same node as for the <complexType>
17131 * to have it somehow anchored in the schema doc.
17132 */
17133 content->type = XML_SCHEMA_TYPE_SIMPLE;
17134 content->baseType = contentBase;
17135 /*
17136 * Move the facets, previously anchored on the
17137 * complexType during parsing.
17138 */
17139 content->facets = type->facets;
17140 type->facets = NULL;
17141 content->facetSet = type->facetSet;
17142 type->facetSet = NULL;
17143
17144 type->contentTypeDef = content;
17145 if (IS_NOT_TYPEFIXED(contentBase))
17146 xmlSchemaTypeFixup(contentBase, pctxt);
17147 /*
17148 * Fixup the newly created type. We don't need to check
17149 * for circularity here.
17150 */
17151 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
17152 HFAILURE HERROR
17153 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
17154 HFAILURE HERROR
17155
17156 } else if ((IS_COMPLEX_TYPE(baseType)) &&
17157 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
17158 (WXS_IS_RESTRICTION(type))) {
17159 /*
17160 * SPEC (2) If <restriction> + base is a mixed <complexType> with
17161 * an emptiable particle, then a simple type definition which
17162 * restricts the <restriction>'s <simpleType> child.
17163 */
17164 if ((type->contentTypeDef == NULL) ||
17165 (type->contentTypeDef->baseType == NULL)) {
17166 /*
17167 * TODO: Check if this ever happens.
17168 */
17169 xmlSchemaPCustomErr(pctxt,
17170 XML_SCHEMAP_INTERNAL,
17171 NULL, type, NULL,
17172 "Internal error: xmlSchemaTypeFixup, "
17173 "complex type '%s': the <simpleContent><restriction> "
17174 "is missing a <simpleType> child, but was not catched "
17175 "by xmlSchemaCheckSRCCT()", type->name);
17176 goto exit_failure;
17177 }
17178 } else if ((IS_COMPLEX_TYPE(baseType)) && WXS_IS_EXTENSION(type)) {
17179 /*
17180 * SPEC (3) If <extension> + base is <complexType> with
17181 * <simpleType> content, "...then the {content type} of that
17182 * complex type definition"
17183 */
17184 if (baseType->contentTypeDef == NULL) {
17185 /*
17186 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
17187 * should have catched this already.
17188 */
17189 xmlSchemaPCustomErr(pctxt,
17190 XML_SCHEMAP_INTERNAL,
17191 NULL, type, NULL,
17192 "Internal error: xmlSchemaTypeFixup, "
17193 "complex type '%s': the <extension>ed base type is "
17194 "a complex type with no simple content type",
17195 type->name);
17196 goto exit_failure;
17197 }
17198 type->contentTypeDef = baseType->contentTypeDef;
17199 } else if ((IS_SIMPLE_TYPE(baseType)) && WXS_IS_EXTENSION(type)) {
17200 /*
17201 * SPEC (4) <extension> + base is <simpleType>
17202 * "... then that simple type definition"
17203 */
17204 type->contentTypeDef = baseType;
17205 } else {
17206 /*
17207 * TODO: Check if this ever happens.
17208 */
17209 xmlSchemaPCustomErr(pctxt,
17210 XML_SCHEMAP_INTERNAL,
17211 NULL, type, NULL,
17212 "Internal error: xmlSchemaTypeFixup, "
17213 "complex type '%s' with <simpleContent>: unhandled "
17214 "derivation case", type->name);
17215 goto exit_failure;
17216 }
17217 } else {
17218 int dummySequence = 0;
17219 xmlSchemaParticlePtr particle =
17220 (xmlSchemaParticlePtr) type->subtypes;
17221 /*
17222 * Corresponds to <complexType><complexContent>...
17223 *
17224 * NOTE that the effective mixed was already set during parsing of
17225 * <complexType> and <complexContent>; its flag value is
17226 * XML_SCHEMAS_TYPE_MIXED.
17227 *
17228 * Compute the "effective content":
17229 * (2.1.1) + (2.1.2) + (2.1.3)
17230 */
17231 if ((particle == NULL) ||
17232 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
17233 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
17234 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
17235 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
17236 (particle->minOccurs == 0))) &&
17237 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
17238 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
17239 /*
17240 * SPEC (2.1.4) "If the ·effective mixed· is true, then
17241 * a particle whose properties are as follows:..."
17242 *
17243 * Empty sequence model group with
17244 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
17245 * NOTE that we sill assign it the <complexType> node to
17246 * somehow anchor it in the doc.
17247 */
17248 if ((particle == NULL) ||
17249 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
17250 /*
17251 * Create the particle.
17252 */
17253 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
17254 type->node, 1, 1);
17255 if (particle == NULL)
17256 goto exit_failure;
17257 /*
17258 * Create the model group.
17259 */
17260 particle->children = (xmlSchemaTreeItemPtr)
17261 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
17262 XML_SCHEMA_TYPE_SEQUENCE, type->node);
17263 if (particle->children == NULL)
17264 goto exit_failure;
17265
17266 type->subtypes = (xmlSchemaTypePtr) particle;
17267 }
17268 dummySequence = 1;
17269 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
17270 } else {
17271 /*
17272 * SPEC (2.1.5) "otherwise empty"
17273 */
17274 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
17275 }
17276 } else {
17277 /*
17278 * SPEC (2.2) "otherwise the particle corresponding to the
17279 * <all>, <choice>, <group> or <sequence> among the
17280 * [children]."
17281 */
17282 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
17283 }
17284 /*
17285 * Compute the "content type".
17286 */
17287 if (WXS_IS_RESTRICTION(type)) {
17288 /*
17289 * SPEC (3.1) "If <restriction>..."
17290 * (3.1.1) + (3.1.2) */
17291 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
17292 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
17293 type->contentType = XML_SCHEMA_CONTENT_MIXED;
17294 }
17295 } else {
17296 /*
17297 * SPEC (3.2) "If <extension>..."
17298 */
17299 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
17300 /*
17301 * SPEC (3.2.1)
17302 */
17303 type->contentType = baseType->contentType;
17304 type->subtypes = baseType->subtypes;
17305 /*
17306 * NOTE that the effective mixed is ignored here.
17307 */
17308 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
17309 /*
17310 * SPEC (3.2.2)
17311 */
17312 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
17313 type->contentType = XML_SCHEMA_CONTENT_MIXED;
17314 } else {
17315 /*
17316 * SPEC (3.2.3)
17317 */
17318 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
17319 type->contentType = XML_SCHEMA_CONTENT_MIXED;
17320 /*
17321 * "A model group whose {compositor} is sequence and whose
17322 * {particles} are..."
17323 */
17324 if (! dummySequence) {
17325 xmlSchemaTreeItemPtr effectiveContent =
17326 (xmlSchemaTreeItemPtr) type->subtypes;
17327 /*
17328 * Create the particle.
17329 */
17330 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
17331 type->node, 1, 1);
17332 if (particle == NULL)
17333 goto exit_failure;
17334 /*
17335 * Create the "sequence" model group.
17336 */
17337 particle->children = (xmlSchemaTreeItemPtr)
17338 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
17339 XML_SCHEMA_TYPE_SEQUENCE, type->node);
17340 if (particle->children == NULL)
17341 goto exit_failure;
17342 type->subtypes = (xmlSchemaTypePtr) particle;
17343 /*
17344 * SPEC "the particle of the {content type} of
17345 * the ... base ..."
17346 * Create a duplicate of the base type's particle
17347 * and assign its "term" to it.
17348 */
17349 particle->children->children =
17350 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
17351 pctxt->schema, type->node,
17352 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
17353 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
17354 if (particle->children->children == NULL)
17355 goto exit_failure;
17356 particle = (xmlSchemaParticlePtr)
17357 particle->children->children;
17358 particle->children =
17359 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
17360 /*
17361 * SPEC "followed by the ·effective content·."
17362 */
17363 particle->next = effectiveContent;
17364 } else {
17365 /*
17366 * This is the case when there is already an empty
17367 * <sequence> with minOccurs==maxOccurs==1.
17368 * Just add the base types's content type.
17369 * NOTE that, although we miss to add an intermediate
17370 * <sequence>, this should produce no difference to
17371 * neither the regex compilation of the content model,
17372 * nor to the complex type contraints.
17373 */
17374 particle->children->children =
17375 (xmlSchemaTreeItemPtr) baseType->subtypes;
17376 }
17377 }
17378 }
17379 }
17380 /*
17381 * Apply the complex type component constraints; this will not
17382 * check attributes, since this is done in
17383 * xmlSchemaBuildAttributeValidation().
17384 */
17385 res = xmlSchemaCheckCTComponent(pctxt, type);
17386 HFAILURE HERROR
17387 /*
17388 * Inherit & check constraints for attributes.
17389 */
17390 res = xmlSchemaBuildAttributeValidation(pctxt, type);
17391 HFAILURE HERROR
17392
17393#ifdef DEBUG_TYPE
17394 xmlSchemaDebugFixedType(pctxt, type);
17395#endif
17396 if (olderrs != pctxt->nberrors)
17397 return(pctxt->err);
17398 else
17399 return(0);
17400
17401exit_error:
17402 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
17403#ifdef DEBUG_TYPE
17404 xmlSchemaDebugFixedType(pctxt, type);
17405#endif
17406 return(pctxt->err);
17407
17408exit_failure:
17409 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
17410#ifdef DEBUG_TYPE
17411 xmlSchemaDebugFixedType(pctxt, type);
17412#endif
17413 return(-1);
17414}
17415
17416
17417/**
17418 * xmlSchemaTypeFixup:
17419 * @typeDecl: the schema type definition
17420 * @ctxt: the schema parser context
17421 *
17422 * Fixes the content model of the type.
17423 * URGENT TODO: We need an int result!
17424 */
17425static int
17426xmlSchemaTypeFixup(xmlSchemaTypePtr type,
17427 xmlSchemaParserCtxtPtr pctxt)
17428{
17429 if (type == NULL)
17430 return(0);
17431 if (! IS_NOT_TYPEFIXED(type))
17432 return(0);
17433 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
17434 return(xmlSchemaFixupComplexType(pctxt, type));
17435 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
17436 return(xmlSchemaFixupSimpleTypeStageTwo(pctxt, type));
17437 return(0);
Daniel Veillard4255d502002-04-16 15:50:10 +000017438}
17439
17440/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000017441 * xmlSchemaCheckFacet:
17442 * @facet: the facet
17443 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000017444 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017445 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000017446 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017447 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000017448 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017449 * Returns 0 if valid, a positive error code if not valid and
17450 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000017451 */
17452int
17453xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017454 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017455 xmlSchemaParserCtxtPtr pctxt,
17456 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000017457{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017458 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017459
Daniel Veillardce682bc2004-11-05 17:22:25 +000017460 if ((facet == NULL) || (typeDecl == NULL))
17461 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017462 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017463 * TODO: will the parser context be given if used from
17464 * the relaxNG module?
17465 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017466 if (pctxt == NULL)
17467 ctxtGiven = 0;
17468 else
17469 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000017470
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000017471 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017472 case XML_SCHEMA_FACET_MININCLUSIVE:
17473 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17474 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000017475 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17476 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017477 /*
17478 * Okay we need to validate the value
17479 * at that point.
17480 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017481 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000017482
17483 /* 4.3.5.5 Constraints on enumeration Schema Components
17484 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017485 * It is an ·error· if any member of {value} is not in the
17486 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000017487 *
17488 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017489 * The value ·must· be in the
17490 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000017491 */
17492 /*
17493 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017494 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017495 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017496 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017497 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000017498 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017499 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000017500 */
17501 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
17502 base = typeDecl->baseType;
17503 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017504 PERROR_INT("xmlSchemaCheckFacet",
17505 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000017506 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017507 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000017508 } else
17509 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017510
17511 if (! ctxtGiven) {
17512 /*
17513 * A context is needed if called from RelaxNG.
17514 */
17515 pctxt = xmlSchemaNewParserCtxt("*");
17516 if (pctxt == NULL)
17517 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000017518 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017519 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017520 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017521 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017522 * facet->node is just the node holding the facet
17523 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017524 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017525 */
17526 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017527 ACTXT_CAST pctxt, facet->node, base,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017528 facet->value, &(facet->val), 1, 1, 0);
17529 if (ret != 0) {
17530 if (ret < 0) {
17531 /* No error message for RelaxNG. */
17532 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017533 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017534 XML_SCHEMAP_INTERNAL, facet->node, NULL,
17535 "Internal error: xmlSchemaCheckFacet, "
17536 "failed to validate the value '%s' of the "
17537 "facet '%s' against the base type",
17538 facet->value, xmlSchemaFacetTypeToString(facet->type));
17539 }
17540 goto internal_error;
17541 }
17542 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
17543 /* No error message for RelaxNG. */
17544 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017545 xmlChar *str = NULL;
17546
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017547 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017548 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017549 "The value '%s' of the facet does not validate "
17550 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017551 facet->value,
17552 xmlSchemaFormatQName(&str,
17553 base->targetNamespace, base->name));
17554 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017555 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017556 goto exit;
17557 } else if (facet->val == NULL) {
17558 if (ctxtGiven) {
17559 PERROR_INT("xmlSchemaCheckFacet",
17560 "value was not computed");
17561 }
17562 TODO
17563 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017564 break;
17565 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017566 case XML_SCHEMA_FACET_PATTERN:
17567 facet->regexp = xmlRegexpCompile(facet->value);
17568 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017569 ret = XML_SCHEMAP_REGEXP_INVALID;
17570 /* No error message for RelaxNG. */
17571 if (ctxtGiven) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017572 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017573 ret, facet->node, typeDecl,
17574 "The value '%s' of the facet 'pattern' is not a "
17575 "valid regular expression",
17576 facet->value, NULL);
17577 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017578 }
17579 break;
17580 case XML_SCHEMA_FACET_TOTALDIGITS:
17581 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17582 case XML_SCHEMA_FACET_LENGTH:
17583 case XML_SCHEMA_FACET_MAXLENGTH:
17584 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017585 ret = xmlSchemaValidatePredefinedType(
17586 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
17587 facet->value, &(facet->val));
17588 if (ret != 0) {
17589 if (ret < 0) {
17590 /* No error message for RelaxNG. */
17591 if (ctxtGiven) {
17592 PERROR_INT("xmlSchemaCheckFacet",
17593 "validating facet value");
17594 }
17595 goto internal_error;
17596 }
17597 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
17598 /* No error message for RelaxNG. */
17599 if (ctxtGiven) {
17600 /* error code */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017601 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017602 ret, facet->node, typeDecl,
17603 "The value '%s' of the facet '%s' is not a valid "
17604 "'nonNegativeInteger'",
17605 facet->value,
17606 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017607 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017608 }
17609 break;
17610 }
17611 case XML_SCHEMA_FACET_WHITESPACE:{
17612 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
17613 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
17614 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
17615 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
17616 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
17617 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
17618 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017619 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
17620 /* No error message for RelaxNG. */
17621 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017622 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017623 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017624 ret, facet->node, typeDecl,
17625 "The value '%s' of the facet 'whitespace' is not "
17626 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017627 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017628 }
17629 }
17630 default:
17631 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000017632 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017633exit:
17634 if ((! ctxtGiven) && (pctxt != NULL))
17635 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017636 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017637internal_error:
17638 if ((! ctxtGiven) && (pctxt != NULL))
17639 xmlSchemaFreeParserCtxt(pctxt);
17640 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000017641}
17642
17643/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017644 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000017645 * @typeDecl: the schema type definition
17646 * @ctxt: the schema parser context
17647 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017648 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000017649 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017650static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017651xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017652 xmlSchemaParserCtxtPtr pctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000017653{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017654 int res, olderrs = pctxt->nberrors;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017655 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000017656 /*
17657 * NOTE: It is intended to use the facets list, instead
17658 * of facetSet.
17659 */
17660 if (typeDecl->facets != NULL) {
17661 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017662
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017663 /*
17664 * Temporarily assign the "schema" to the validation context
17665 * of the parser context. This is needed for NOTATION validation.
17666 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017667 if (pctxt->vctxt == NULL) {
17668 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
17669 return(-1);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017670 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017671 pctxt->vctxt->schema = pctxt->schema;
Daniel Veillard01fa6152004-06-29 17:04:39 +000017672 while (facet != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017673 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
17674 HFAILURE
Daniel Veillard01fa6152004-06-29 17:04:39 +000017675 facet = facet->next;
17676 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017677 pctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017678 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017679 if (olderrs != pctxt->nberrors)
17680 return(pctxt->err);
17681 return(0);
17682exit_failure:
17683 return(-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000017684}
17685
17686/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017687 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017688 * @ctxtMGroup: the searched model group
17689 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017690 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017691 *
17692 * This one is intended to be used by
17693 * xmlSchemaCheckGroupDefCircular only.
17694 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017695 * Returns the particle with the circular model group definition reference,
17696 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017697 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017698static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017699xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017700 xmlSchemaTreeItemPtr particle)
17701{
17702 xmlSchemaTreeItemPtr circ = NULL;
17703 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017704 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017705
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017706 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017707 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017708 if (term == NULL)
17709 continue;
17710 switch (term->type) {
17711 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017712 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017713 if (gdef == groupDef)
17714 return (particle);
17715 /*
17716 * Mark this model group definition to avoid infinite
17717 * recursion on circular references not yet examined.
17718 */
17719 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
17720 continue;
17721 if (gdef->children != NULL) {
17722 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
17723 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
17724 gdef->children->children);
17725 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
17726 if (circ != NULL)
17727 return (circ);
17728 }
17729 break;
17730 case XML_SCHEMA_TYPE_SEQUENCE:
17731 case XML_SCHEMA_TYPE_CHOICE:
17732 case XML_SCHEMA_TYPE_ALL:
17733 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
17734 if (circ != NULL)
17735 return (circ);
17736 break;
17737 default:
17738 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017739 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017740 }
17741 return (NULL);
17742}
17743
17744/**
17745 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017746 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017747 * @ctxt: the parser context
17748 * @name: the name
17749 *
17750 * Checks for circular references to model group definitions.
17751 */
17752static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017753xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017754 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017755{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017756 /*
17757 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017758 * 2 Circular groups are disallowed. That is, within the {particles}
17759 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017760 * is the group itself.
17761 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017762 if ((item == NULL) ||
17763 (item->type != XML_SCHEMA_TYPE_GROUP) ||
17764 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017765 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017766 {
17767 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017768
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017769 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017770 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017771 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017772 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017773 * TODO: The error report is not adequate: this constraint
17774 * is defined for model groups but not definitions, but since
17775 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017776 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017777 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017778 */
17779 xmlSchemaPCustomErr(ctxt,
17780 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017781 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017782 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017783 "defined", xmlSchemaFormatQName(&str,
17784 item->targetNamespace, item->name));
17785 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017786 /*
17787 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017788 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017789 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017790 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017791 }
17792 }
17793}
17794
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017795/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017796 * xmlSchemaGroupDefReferenceTermFixup:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017797 * @item: the particle with a model group definition as term
17798 * @ctxt: the parser context
17799 * @name: the name
17800 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017801 * Checks cos-all-limited.
17802 *
17803 * Assigns the model group of model group definitions to the "term"
17804 * of the referencing particle.
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017805 * In xmlSchemaResolveParticleReferences the model group definitions was assigned
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017806 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017807 */
17808static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017809xmlSchemaGroupDefReferenceTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017810 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017811 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017812{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017813 if ((item == NULL) ||
17814 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
17815 (item->children == NULL) ||
17816 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
17817 (item->children->children == NULL))
17818 return;
17819 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017820 /*
17821 * TODO: Not nice, but we will anchor cos-all-limited here.
17822 */
17823 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
17824 (item->maxOccurs != 1)) {
17825 /*
17826 * SPEC (1.2) "the {term} property of a particle with
17827 * {max occurs}=1which is part of a pair which constitutes the
17828 * {content type} of a complex type definition."
17829 */
17830 xmlSchemaPCustomErr(ctxt,
17831 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
17832 NULL, (xmlSchemaTypePtr) item, item->node,
17833 "The particle's 'maxOccurs' must be 1, since an xs:all model "
17834 "group is its term", NULL);
17835 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017836}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017837
17838/**
17839 * xmlSchemaGetCircAttrGrRef:
17840 * @ctxtGr: the searched attribute group
17841 * @attr: the current attribute list to be processed
17842 *
17843 * This one is intended to be used by
17844 * xmlSchemaCheckSRCAttributeGroupCircular only.
17845 *
17846 * Returns the circular attribute grou reference, otherwise NULL.
17847 */
17848static xmlSchemaAttributeGroupPtr
17849xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
17850 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017851{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017852 xmlSchemaAttributeGroupPtr circ = NULL, gr;
17853 int marked;
17854 /*
17855 * We will search for an attribute group reference which
17856 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017857 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017858 while (attr != NULL) {
17859 marked = 0;
17860 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
17861 gr = (xmlSchemaAttributeGroupPtr) attr;
17862 if (gr->refItem != NULL) {
17863 if (gr->refItem == ctxtGr)
17864 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017865 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017866 XML_SCHEMAS_ATTRGROUP_MARKED) {
17867 attr = attr->next;
17868 continue;
17869 } else {
17870 /*
17871 * Mark as visited to avoid infinite recursion on
17872 * circular references not yet examined.
17873 */
17874 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
17875 marked = 1;
17876 }
17877 }
17878 if (gr->attributes != NULL)
17879 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
17880 /*
17881 * Unmark the visited group's attributes.
17882 */
17883 if (marked)
17884 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
17885 if (circ != NULL)
17886 return (circ);
17887 }
17888 attr = attr->next;
17889 }
17890 return (NULL);
17891}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017892
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017893/**
17894 * xmlSchemaCheckSRCAttributeGroupCircular:
17895 * attrGr: the attribute group definition
17896 * @ctxt: the parser context
17897 * @name: the name
17898 *
17899 * Checks for circular references of attribute groups.
17900 */
17901static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017902xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
17903 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017904{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017905 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017906 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017907 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017908 * 3 Circular group reference is disallowed outside <redefine>.
17909 * That is, unless this element information item's parent is
17910 * <redefine>, then among the [children], if any, there must
17911 * not be an <attributeGroup> with ref [attribute] which resolves
17912 * to the component corresponding to this <attributeGroup>. Indirect
17913 * circularity is also ruled out. That is, when QName resolution
17914 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
17915 * any <attributeGroup>s with a ref [attribute] among the [children],
17916 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017917 * which resolves to the component corresponding to this <attributeGroup>.
17918 */
17919 /*
17920 * Only global components can be referenced.
17921 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017922 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017923 (attrGr->attributes == NULL))
17924 return;
17925 else {
17926 xmlSchemaAttributeGroupPtr circ;
17927
17928 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
17929 if (circ != NULL) {
17930 /*
17931 * TODO: Report the referenced attr group as QName.
17932 */
17933 xmlSchemaPCustomErr(ctxt,
17934 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
17935 NULL, NULL, circ->node,
17936 "Circular reference to the attribute group '%s' "
17937 "defined", attrGr->name);
17938 /*
17939 * NOTE: We will cut the reference to avoid further
17940 * confusion of the processor.
17941 * BADSPEC: The spec should define how to process in this case.
17942 */
17943 circ->attributes = NULL;
17944 circ->refItem = NULL;
17945 }
17946 }
17947}
17948
17949/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017950 * xmlSchemaResolveAttrGroupReferences:
Daniel Veillard13e04c62002-04-23 17:51:29 +000017951 * @attrgrpDecl: the schema attribute definition
17952 * @ctxt: the schema parser context
17953 * @name: the attribute name
17954 *
17955 * Fixes finish doing the computations on the attributes definitions
17956 */
17957static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017958xmlSchemaResolveAttrGroupReferences(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017959 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000017960{
17961 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000017962 name = attrgrp->name;
17963 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017964 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000017965 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017966 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000017967
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017968 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017969 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017970 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017971 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017972 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017973 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
17974 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017975 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017976 return;
17977 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017978 attrgrp->refItem = ref;
17979 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000017980 * URGENT TODO: Do we need to resolve refs of the
17981 * referenced attr. group itself first? I don't think so.
17982 * If we need this, then check for circularity first!
17983 * REMOVED: xmlSchemaResolveAttrGroupReferences(ref, ctxt, NULL);
17984 */
Daniel Veillard3646d642004-06-02 19:19:14 +000017985 attrgrp->attributes = ref->attributes;
17986 attrgrp->attributeWildcard = ref->attributeWildcard;
17987 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000017988}
17989
17990/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017991 * xmlSchemaAttrCheckValConstr:
17992 * @item: an schema attribute declaration/use
17993 * @ctxt: a schema parser context
17994 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017995 *
17996 *
17997 * Schema Component Constraint: Attribute Declaration Properties Correct
17998 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017999 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000018000 *
18001 * Fixes finish doing the computations on the attributes definitions
18002 */
18003static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018004xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018005 xmlSchemaParserCtxtPtr pctxt)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018006{
18007
18008 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018009 * 2 if there is a {value constraint}, the canonical lexical
18010 * representation of its value must be ·valid· with respect
18011 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018012 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018013 if (item->defValue != NULL) {
18014 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018015
18016 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018017 PERROR_INT("xmlSchemaCheckAttrValConstr",
18018 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018019 return;
18020 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018021 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018022 item->node, item->subtypes, item->defValue, &(item->defVal),
18023 1, 1, 0);
18024 if (ret != 0) {
18025 if (ret < 0) {
18026 PERROR_INT("xmlSchemaAttrCheckValConstr",
18027 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018028 return;
18029 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018030 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018031 xmlSchemaCustomErr(ACTXT_CAST pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018032 ret, item->node, (xmlSchemaTypePtr) item,
18033 "The value of the value constraint is not valid", NULL, NULL);
18034 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018035 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018036 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018037}
18038
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018039static xmlSchemaElementPtr
18040xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
18041 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018042{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018043 xmlSchemaElementPtr ret;
18044
18045 if (SUBST_GROUP_AFF(ancestor) == NULL)
18046 return (NULL);
18047 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
18048 return (ancestor);
18049
18050 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
18051 return (NULL);
18052 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
18053 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
18054 SUBST_GROUP_AFF(ancestor));
18055 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
18056
18057 return (ret);
18058}
18059
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018060/**
18061 * xmlSchemaCheckElemPropsCorrect:
18062 * @ctxt: a schema parser context
18063 * @decl: the element declaration
18064 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018065 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018066 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018067 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018068 *
18069 * STATUS:
18070 * missing: (6)
18071 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018072static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018073xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
18074 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018075{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018076 int ret = 0;
18077 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018078 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018079 * SPEC (1) "The values of the properties of an element declaration
18080 * must be as described in the property tableau in The Element
18081 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
18082 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018083 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018084 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018085 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018086
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018087 xmlSchemaCheckElementDeclComponent(head, pctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018088 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018089 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018090 * affiliation}, then {scope} must be global."
18091 */
18092 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
18093 xmlSchemaPCustomErr(pctxt,
18094 XML_SCHEMAP_E_PROPS_CORRECT_3,
18095 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
18096 "Only global element declarations can have a "
18097 "substitution group affiliation", NULL);
18098 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018099 }
18100 /*
18101 * TODO: SPEC (6) "Circular substitution groups are disallowed.
18102 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018103 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018104 * property."
18105 */
18106 if (head == elemDecl)
18107 circ = head;
18108 else if (SUBST_GROUP_AFF(head) != NULL)
18109 circ = xmlSchemaCheckSubstGroupCircular(head, head);
18110 else
18111 circ = NULL;
18112 if (circ != NULL) {
18113 xmlChar *strA = NULL, *strB = NULL;
18114
18115 xmlSchemaPCustomErrExt(pctxt,
18116 XML_SCHEMAP_E_PROPS_CORRECT_6,
18117 NULL, (xmlSchemaTypePtr) circ, circ->node,
18118 "The element declaration '%s' defines a circular "
18119 "substitution group to element declaration '%s'",
18120 xmlSchemaGetComponentQName(&strA, circ),
18121 xmlSchemaGetComponentQName(&strB, head),
18122 NULL);
18123 FREE_AND_NULL(strA)
18124 FREE_AND_NULL(strB)
18125 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
18126 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018127 /*
18128 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018129 * the {type definition}
18130 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018131 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018132 * of the {substitution group exclusions} of the {substitution group
18133 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
18134 * (if the {type definition} is complex) or as defined in
18135 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018136 * simple)."
18137 *
18138 * NOTE: {substitution group exclusions} means the values of the
18139 * attribute "final".
18140 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018141
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018142 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018143 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018144
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018145 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
18146 set |= SUBSET_EXTENSION;
18147 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
18148 set |= SUBSET_RESTRICTION;
18149
18150 if (xmlSchemaCheckCOSDerivedOK(typeDef,
18151 ELEM_TYPE(head), set) != 0) {
18152 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
18153
18154 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018155 xmlSchemaPCustomErrExt(pctxt,
18156 XML_SCHEMAP_E_PROPS_CORRECT_4,
18157 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018158 "The type definition '%s' was "
18159 "either rejected by the substitution group "
18160 "affiliation '%s', or not validly derived from its type "
18161 "definition '%s'",
18162 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018163 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018164 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018165 FREE_AND_NULL(strA)
18166 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018167 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018168 }
18169 }
18170 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018171 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018172 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018173 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018174 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018175 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018176 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018177 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018178 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018179 ((IS_SIMPLE_TYPE(typeDef) &&
18180 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018181 (IS_COMPLEX_TYPE(typeDef) &&
18182 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018183 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
18184 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018185
18186 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
18187 xmlSchemaPCustomErr(pctxt,
18188 XML_SCHEMAP_E_PROPS_CORRECT_5,
18189 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
18190 "The type definition (or type definition's content type) is or "
18191 "is derived from ID; value constraints are not allowed in "
18192 "conjunction with such a type definition", NULL);
18193 } else if (elemDecl->value != NULL) {
18194 int vcret;
18195 xmlNodePtr node = NULL;
18196
18197 /*
18198 * SPEC (2) "If there is a {value constraint}, the canonical lexical
18199 * representation of its value must be ·valid· with respect to the
18200 * {type definition} as defined in Element Default Valid (Immediate)
18201 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018202 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018203 if (typeDef == NULL) {
18204 xmlSchemaPErr(pctxt, elemDecl->node,
18205 XML_SCHEMAP_INTERNAL,
18206 "Internal error: xmlSchemaCheckElemPropsCorrect, "
18207 "type is missing... skipping validation of "
18208 "the value constraint", NULL, NULL);
18209 return (-1);
18210 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018211 if (elemDecl->node != NULL) {
18212 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
18213 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
18214 BAD_CAST "fixed");
18215 else
18216 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
18217 BAD_CAST "default");
18218 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018219 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
18220 typeDef, elemDecl->value, &(elemDecl->defVal));
18221 if (vcret != 0) {
18222 if (vcret < 0) {
18223 PERROR_INT("xmlSchemaElemCheckValConstr",
18224 "failed to validate the value constraint of an "
18225 "element declaration");
18226 return (-1);
18227 }
18228 return (vcret);
18229 }
18230 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018231
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018232 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018233}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018234
18235/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018236 * xmlSchemaCheckElemSubstGroup:
18237 * @ctxt: a schema parser context
18238 * @decl: the element declaration
18239 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018240 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018241 * Schema Component Constraint:
18242 * Substitution Group (cos-equiv-class)
18243 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018244 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018245 * a list will be built for each subst. group head, holding all direct
18246 * referents to this head.
18247 * NOTE that this function needs:
18248 * 1. circular subst. groups to be checked beforehand
18249 * 2. the declaration's type to be derived from the head's type
18250 *
18251 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018252 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018253 */
18254static void
18255xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
18256 xmlSchemaElementPtr elemDecl)
18257{
18258 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
18259 /* SPEC (1) "Its {abstract} is false." */
18260 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
18261 return;
18262 {
18263 xmlSchemaElementPtr head;
18264 xmlSchemaTypePtr headType, type;
18265 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018266 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018267 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
18268 * {disallowed substitutions} as the blocking constraint, as defined in
18269 * Substitution Group OK (Transitive) (§3.3.6)."
18270 */
18271 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
18272 head = SUBST_GROUP_AFF(head)) {
18273 set = 0;
18274 methSet = 0;
18275 /*
18276 * The blocking constraints.
18277 */
18278 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
18279 continue;
18280 headType = head->subtypes;
18281 type = elemDecl->subtypes;
18282 if (headType == type)
18283 goto add_member;
18284 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
18285 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
18286 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
18287 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
18288 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018289 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018290 * "The set of all {derivation method}s involved in the
18291 * derivation of D's {type definition} from C's {type definition}
18292 * does not intersect with the union of the blocking constraint,
18293 * C's {prohibited substitutions} (if C is complex, otherwise the
18294 * empty set) and the {prohibited substitutions} (respectively the
18295 * empty set) of any intermediate {type definition}s in the
18296 * derivation of D's {type definition} from C's {type definition}."
18297 */
18298 /*
18299 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
18300 * subst.head axis, the methSet does not need to be computed for
18301 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018302 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018303 /*
18304 * The set of all {derivation method}s involved in the derivation
18305 */
18306 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018307 if ((WXS_IS_EXTENSION(type)) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018308 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
18309 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018310
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018311 if (WXS_IS_RESTRICTION(type) &&
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018312 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
18313 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
18314
18315 type = type->baseType;
18316 }
18317 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018318 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018319 * the head's type.
18320 */
18321 type = elemDecl->subtypes->baseType;
18322 while (type != NULL) {
18323 if (IS_COMPLEX_TYPE(type)) {
18324 if ((type->flags &
18325 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
18326 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
18327 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
18328 if ((type->flags &
18329 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
18330 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
18331 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
18332 } else
18333 break;
18334 if (type == headType)
18335 break;
18336 type = type->baseType;
18337 }
18338 if ((set != 0) &&
18339 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
18340 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
18341 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
18342 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
18343 continue;
18344 }
18345add_member:
18346 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
18347 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
18348 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
18349 }
18350 }
18351}
18352
18353/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018354 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018355 * @item: an schema element declaration/particle
18356 * @ctxt: a schema parser context
18357 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018358 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018359 * Validates the value constraints of an element declaration.
18360 *
18361 * Fixes finish doing the computations on the element declarations.
18362 */
18363static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018364xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018365 xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018366{
18367 if (elemDecl == NULL)
18368 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018369 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
18370 return;
18371 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018372 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
18373 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018374}
18375
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018376/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018377 * xmlSchemaResolveParticleReferences:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018378 * @item: an schema component
18379 * @ctxt: a schema parser context
18380 * @name: the internal name of the component
18381 *
18382 * Resolves references of misc. schema components.
18383 */
18384static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018385xmlSchemaResolveParticleReferences(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018386 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018387 const xmlChar * name ATTRIBUTE_UNUSED)
18388{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018389 if (item->type != XML_SCHEMA_TYPE_PARTICLE)
18390 return;
18391 if ((item->children != NULL) &&
18392 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
18393 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
18394 xmlSchemaBasicItemPtr refItem;
18395 /*
18396 * Resolve the reference.
18397 */
18398 item->children = NULL;
18399 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
18400 ref->itemType, ref->name, ref->targetNamespace);
18401 if (refItem == NULL) {
18402 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
18403 NULL, GET_NODE(item), "ref", ref->name,
18404 ref->targetNamespace, ref->itemType, NULL);
18405 } else {
18406 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
18407 /*
18408 * NOTE that we will assign the model group definition
18409 * itself to the "term" of the particle. This will ease
18410 * the check for circular model group definitions. After
18411 * that the "term" will be assigned the model group of the
18412 * model group definition.
18413 */
18414 item->children = (xmlSchemaTreeItemPtr) refItem;
18415 } else
18416 item->children = (xmlSchemaTreeItemPtr) refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018417 }
18418 }
18419}
18420
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018421static int
18422xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
18423 xmlSchemaValPtr y)
18424{
18425 xmlSchemaTypePtr tx, ty, ptx, pty;
18426 int ret;
18427
18428 while (x != NULL) {
18429 /* Same types. */
18430 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
18431 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
18432 ptx = xmlSchemaGetPrimitiveType(tx);
18433 pty = xmlSchemaGetPrimitiveType(ty);
18434 /*
18435 * (1) if a datatype T' is ·derived· by ·restriction· from an
18436 * atomic datatype T then the ·value space· of T' is a subset of
18437 * the ·value space· of T. */
18438 /*
18439 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
18440 * from a common atomic ancestor T then the ·value space·s of T'
18441 * and T'' may overlap.
18442 */
18443 if (ptx != pty)
18444 return(0);
18445 /*
18446 * We assume computed values to be normalized, so do a fast
18447 * string comparison for string based types.
18448 */
18449 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
18450 IS_ANY_SIMPLE_TYPE(ptx)) {
18451 if (! xmlStrEqual(
18452 xmlSchemaValueGetAsString(x),
18453 xmlSchemaValueGetAsString(y)))
18454 return (0);
18455 } else {
18456 ret = xmlSchemaCompareValuesWhtsp(
18457 x, XML_SCHEMA_WHITESPACE_PRESERVE,
18458 y, XML_SCHEMA_WHITESPACE_PRESERVE);
18459 if (ret == -2)
18460 return(-1);
18461 if (ret != 0)
18462 return(0);
18463 }
18464 /*
18465 * Lists.
18466 */
18467 x = xmlSchemaValueGetNext(x);
18468 if (x != NULL) {
18469 y = xmlSchemaValueGetNext(y);
18470 if (y == NULL)
18471 return (0);
18472 } else if (xmlSchemaValueGetNext(y) != NULL)
18473 return (0);
18474 else
18475 return (1);
18476 }
18477 return (0);
18478}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018479
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018480/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018481 * xmlSchemaResolveAttrReferences:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018482 * @item: an schema attribute declaration/use.
18483 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018484 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018485 *
18486 * Fixes finish doing the computations on attribute declarations/uses.
18487 */
18488static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018489xmlSchemaResolveAttrReferences(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018490 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018491 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000018492{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018493 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000018494 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018495 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018496 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018497 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018498 * The simple type definition corresponding to the <simpleType> element
18499 * information item in the [children], if present, otherwise the simple
18500 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000018501 * [attribute], if present, otherwise the ·simple ur-type definition·.
18502 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018503 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018504 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018505 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
18506 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018507 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018508 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018509 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000018510
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018511 type = xmlSchemaGetType(ctxt->schema, item->typeName,
18512 item->typeNs);
18513 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018514 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018515 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018516 (xmlSchemaTypePtr) item, item->node,
18517 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018518 XML_SCHEMA_TYPE_SIMPLE, NULL);
18519 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018520 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018521
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018522 } else if (item->ref != NULL) {
18523 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000018524
Daniel Veillardc0826a72004-08-10 14:17:33 +000018525 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018526 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018527 * attribute declaration.
18528 */
18529 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000018530 * TODO: Evaluate, what errors could occur if the declaration is not
18531 * found. It might be possible that the "typefixup" might crash if
18532 * no ref declaration was found.
18533 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018534 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018535 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018536 xmlSchemaPResCompAttrErr(ctxt,
18537 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018538 (xmlSchemaTypePtr) item, item->node,
18539 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018540 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018541 return;
18542 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018543 item->refDecl = decl;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018544 xmlSchemaResolveAttrReferences(decl, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018545 item->subtypes = decl->subtypes;
18546 /*
18547 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018548 * au-props-correct.2: If the {attribute declaration} has a fixed
18549 * {value constraint}, then if the attribute use itself has a
18550 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018551 * that of the {attribute declaration}'s {value constraint}.
18552 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018553 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018554 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018555 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018556 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018557 XML_SCHEMAP_AU_PROPS_CORRECT_2,
18558 NULL, NULL, item->node,
18559 "The attribute declaration has a 'fixed' value constraint "
18560 ", thus it must be 'fixed' in attribute use as well",
18561 NULL);
18562 } else {
18563 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
18564 xmlSchemaPCustomErr(ctxt,
18565 XML_SCHEMAP_AU_PROPS_CORRECT_2,
18566 NULL, NULL, item->node,
18567 "The 'fixed' value constraint of the attribute use "
18568 "must match the attribute declaration's value "
18569 "constraint '%s'",
18570 decl->defValue);
18571 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018572 }
18573 /*
18574 * FUTURE: One should change the values of the attr. use
18575 * if ever validation should be attempted even if the
18576 * schema itself was not fully valid.
18577 */
18578 }
Daniel Veillard3646d642004-06-02 19:19:14 +000018579 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018580 /* The type of this attribute is the xs:anySimpleType. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018581 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
18582 }
Daniel Veillard4255d502002-04-16 15:50:10 +000018583}
18584
18585/**
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018586 * xmlSchemaResolveIDCKeyReferences:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018587 * @idc: the identity-constraint definition
18588 * @ctxt: the schema parser context
18589 * @name: the attribute name
18590 *
18591 * Resolve keyRef references to key/unique IDCs.
18592 */
18593static void
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018594xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018595 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000018596 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018597{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018598 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
18599 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018600 if (idc->ref->name != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018601 idc->ref->item = (xmlSchemaBasicItemPtr)
18602 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
18603 idc->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018604 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018605 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018606 * TODO: It is actually not an error to fail to resolve
18607 * at this stage. BUT we need to be that strict!
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018608 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018609 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018610 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018611 (xmlSchemaTypePtr) idc, idc->node,
18612 "refer", idc->ref->name,
18613 idc->ref->targetNamespace,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018614 XML_SCHEMA_TYPE_IDC_KEY, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018615 return;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018616 } else {
18617 if (idc->nbFields !=
18618 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
18619 xmlChar *str = NULL;
18620 xmlSchemaIDCPtr refer;
18621
18622 refer = (xmlSchemaIDCPtr) idc->ref->item;
18623 /*
18624 * SPEC c-props-correct(2)
18625 * "If the {identity-constraint category} is keyref,
18626 * the cardinality of the {fields} must equal that of
18627 * the {fields} of the {referenced key}.
18628 */
18629 xmlSchemaPCustomErr(pctxt,
18630 XML_SCHEMAP_C_PROPS_CORRECT,
18631 NULL, (xmlSchemaTypePtr) idc, idc->node,
18632 "The cardinality of the keyref differs from the "
18633 "cardinality of the referenced key '%s'",
18634 xmlSchemaFormatQName(&str, refer->targetNamespace,
18635 refer->name)
18636 );
18637 FREE_AND_NULL(str)
18638 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018639 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018640 }
18641}
18642
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018643
18644static int
18645xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt)
18646{
18647 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
18648 xmlSchemaTreeItemPtr item, *items;
18649 int nbItems, i;
18650
18651#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
18652
18653 if ((con->pending == NULL) ||
18654 (con->pending->nbItems == 0))
18655 return(0);
18656
18657 pctxt->ctxtType = NULL;
18658 pctxt->parentItem = NULL;
18659 items = (xmlSchemaTreeItemPtr *) con->pending->items;
18660 nbItems = con->pending->nbItems;
18661 /*
18662 * Now that we have parsed *all* the schema document(s) and converted
18663 * them to schema components, we can resolve references, apply component
18664 * constraints, create the FSA from the content model, etc.
18665 */
18666 /*
18667 * Resolve references of..
18668 *
18669 * 1. element declarations:
18670 * - the type definition
18671 * - the substitution group affiliation
18672 * 2. simple/complex types:
18673 * - the base type definition
18674 * - the memberTypes of union types
18675 * - the itemType of list types
18676 * 3. attributes declarations and attribute uses:
18677 * - the type definition
18678 * - if an attribute use, then the attribute declaration
18679 * 4. attribute group references:
18680 * - the attribute group definition
18681 * 5. particles:
18682 * - the term of the particle (e.g. a model group)
18683 * 6. IDC key-references:
18684 * - the referenced IDC 'key' or 'unique' definition
18685 */
18686 for (i = 0; i < nbItems; i++) {
18687 item = items[i];
18688 switch (item->type) {
18689 case XML_SCHEMA_TYPE_ELEMENT:
18690 xmlSchemaResolveElementReferences(
18691 (xmlSchemaElementPtr) item, pctxt);
18692 FIXHFAILURE;
18693 break;
18694 case XML_SCHEMA_TYPE_COMPLEX:
18695 case XML_SCHEMA_TYPE_SIMPLE:
18696 xmlSchemaResolveTypeReferences(
18697 (xmlSchemaTypePtr) item, pctxt, NULL);
18698 FIXHFAILURE;
18699 break;
18700 case XML_SCHEMA_TYPE_ATTRIBUTE:
18701 xmlSchemaResolveAttrReferences(
18702 (xmlSchemaAttributePtr) item, pctxt, NULL);
18703 FIXHFAILURE;
18704 break;
18705 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18706 xmlSchemaResolveAttrGroupReferences(
18707 (xmlSchemaAttributeGroupPtr) item, pctxt, NULL);
18708 FIXHFAILURE;
18709 break;
18710 case XML_SCHEMA_TYPE_PARTICLE:
18711 xmlSchemaResolveParticleReferences(
18712 (xmlSchemaTreeItemPtr) item, pctxt, NULL);
18713 FIXHFAILURE;
18714 break;
18715 case XML_SCHEMA_TYPE_IDC_KEY:
18716 case XML_SCHEMA_TYPE_IDC_UNIQUE:
18717 case XML_SCHEMA_TYPE_IDC_KEYREF:
18718 xmlSchemaResolveIDCKeyReferences(
18719 (xmlSchemaIDCPtr) item, pctxt, NULL);
18720 FIXHFAILURE;
18721 break;
18722 default:
18723 break;
18724 }
18725 }
18726 if (pctxt->nberrors != 0)
18727 goto exit_error;
18728
18729 /*
18730 * Now that all references are resolved we
18731 * can check for circularity of...
18732 * 1. the base axis of type definitions
18733 * 2. nested model group definitions
18734 * 3. nested attribute group definitions
18735 * TODO: check for circual substitution groups.
18736 */
18737 for (i = 0; i < nbItems; i++) {
18738 item = items[i];
18739 /*
18740 * Let's better stop on the first error here.
18741 */
18742 switch (item->type) {
18743 case XML_SCHEMA_TYPE_COMPLEX:
18744 case XML_SCHEMA_TYPE_SIMPLE:
18745 xmlSchemaCheckTypeDefCircular(
18746 (xmlSchemaTypePtr) item, pctxt);
18747 FIXHFAILURE;
18748 if (pctxt->nberrors != 0)
18749 goto exit_error;
18750 break;
18751 case XML_SCHEMA_TYPE_GROUP:
18752 xmlSchemaCheckGroupDefCircular(
18753 (xmlSchemaModelGroupDefPtr) item, pctxt);
18754 FIXHFAILURE;
18755 if (pctxt->nberrors != 0)
18756 goto exit_error;
18757 break;
18758 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18759 xmlSchemaCheckAttrGroupCircular(
18760 (xmlSchemaAttributeGroupPtr) item, pctxt);
18761 FIXHFAILURE;
18762 if (pctxt->nberrors != 0)
18763 goto exit_error;
18764 break;
18765 default:
18766 break;
18767 }
18768 }
18769 /*
18770 * Model group definition references:
18771 * Such a reference is reflected by a particle at the component
18772 * level. Until now the 'term' of such particles pointed
18773 * to the model group definition; this was done, in order to
18774 * ease circularity checks. Now we need to set the 'term' of
18775 * such particles to the model group of the model group definition.
18776 */
18777 for (i = 0; i < nbItems; i++) {
18778 item = items[i];
18779 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18780 (item->children != NULL) &&
18781 (item->children->type == XML_SCHEMA_TYPE_GROUP)) {
18782 xmlSchemaGroupDefReferenceTermFixup(
18783 (xmlSchemaParticlePtr) item, pctxt, NULL);
18784 FIXHFAILURE;
18785 }
18786 }
18787 if (pctxt->nberrors != 0)
18788 goto exit_error;
18789 /*
18790 * Now that all references are resolved, no circularity occured
18791 * and the 'term's of particles was fixed we can:
18792 * 1. finish computation of properties of types
18793 * 2. restrict type definitions and check those restrictions
18794 * 3. extend type definitions and check those extensions
18795 *
18796 * This is the most complex part during schema construction.
18797 * TODO: Maybe it would be better to stop at the first error here.
18798 */
18799 /*
18800 * First compute the variety of simple types. This is needed as
18801 * a seperate step, since otherwise we won't be able to detect
18802 * circular union types in all cases.
18803 */
18804 for (i = 0; i < nbItems; i++) {
18805 item = items[i];
18806 switch (item->type) {
18807 case XML_SCHEMA_TYPE_SIMPLE:
18808 if (TYPE_IS_NOT_FIXEDUP_1((xmlSchemaTypePtr) item)) {
18809 xmlSchemaFixupSimpleTypeStageOne(pctxt,
18810 (xmlSchemaTypePtr) item);
18811 FIXHFAILURE;
18812 }
18813 break;
18814 default:
18815 break;
18816 }
18817 }
18818 /*
18819 * Detect circular union types. Note that this needs the variety to
18820 * be already computed.
18821 */
18822 for (i = 0; i < nbItems; i++) {
18823 item = items[i];
18824 switch (item->type) {
18825 case XML_SCHEMA_TYPE_SIMPLE:
18826 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
18827 xmlSchemaCheckUnionTypeDefCircular(pctxt,
18828 (xmlSchemaTypePtr) item);
18829 FIXHFAILURE;
18830 }
18831 break;
18832 default:
18833 break;
18834 }
18835 }
18836 if (pctxt->nberrors != 0)
18837 goto exit_error;
18838 /* Now do the complete type fixup. */
18839 for (i = 0; i < nbItems; i++) {
18840 item = items[i];
18841 switch (item->type) {
18842 case XML_SCHEMA_TYPE_SIMPLE:
18843 case XML_SCHEMA_TYPE_COMPLEX:
18844 xmlSchemaTypeFixup((xmlSchemaTypePtr) item, pctxt);
18845 FIXHFAILURE;
18846 break;
18847 default:
18848 break;
18849 }
18850 }
18851 if (pctxt->nberrors != 0)
18852 goto exit_error;
18853
18854 /*
18855 * Now that we are sure the type definitions are finally constructed,
18856 * we can:
18857 * 1. check value contraint values of attribute declarations
18858 * 2. apply various constraints to element declarations
18859 */
18860 for (i = 0; i < nbItems; i++) {
18861 item = items[i];
18862 switch (item->type) {
18863 case XML_SCHEMA_TYPE_ATTRIBUTE:
18864 if (((xmlSchemaAttributePtr)item)->defValue != NULL) {
18865 xmlSchemaCheckAttrValConstr(
18866 (xmlSchemaAttributePtr) item, pctxt);
18867 FIXHFAILURE;
18868 }
18869 break;
18870 case XML_SCHEMA_TYPE_ELEMENT:
18871 if ((((xmlSchemaElementPtr) item)->flags &
18872 XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0) {
18873 xmlSchemaCheckElementDeclComponent(
18874 (xmlSchemaElementPtr) item, pctxt);
18875 FIXHFAILURE;
18876 }
18877 break;
18878 default:
18879 break;
18880 }
18881 }
18882 if (pctxt->nberrors != 0)
18883 goto exit_error;
18884 /*
18885 * Finally we can build the automaton from the content model of
18886 * complex types.
18887 */
18888 for (i = 0; i < nbItems; i++) {
18889 item = items[i];
18890 switch (item->type) {
18891 case XML_SCHEMA_TYPE_COMPLEX:
18892 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
18893 FIXHFAILURE;
18894 break;
18895 default:
18896 break;
18897 }
18898 }
18899 if (pctxt->nberrors != 0)
18900 goto exit_error;
18901
18902 /*
18903 * URGENT TODO: cos-element-consistent, cos-all-limited
18904 */
18905 con->pending->nbItems = 0;
18906 return(0);
18907exit_error:
18908 con->pending->nbItems = 0;
18909 return(pctxt->err);
18910exit_failure:
18911 con->pending->nbItems = 0;
18912 return(-1);
18913}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018914/**
Daniel Veillard4255d502002-04-16 15:50:10 +000018915 * xmlSchemaParse:
18916 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000018917 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000018918 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000018919 * XML Shema struture which can be used to validate instances.
18920 * *WARNING* this interface is highly subject to change
18921 *
18922 * Returns the internal XML Schema structure built from the resource or
18923 * NULL in case of error
18924 */
18925xmlSchemaPtr
18926xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
18927{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018928 xmlSchemaPtr schema = NULL;
18929 xmlSchemaBucketPtr bucket = NULL;
18930 int res;
Daniel Veillard4255d502002-04-16 15:50:10 +000018931
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018932 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018933 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018934 * the API; i.e. not automatically by the validated instance document.
18935 */
18936
Daniel Veillard4255d502002-04-16 15:50:10 +000018937 xmlSchemaInitTypes();
18938
Daniel Veillard6045c902002-10-09 21:13:59 +000018939 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000018940 return (NULL);
18941
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018942 /* TODO: Init the context. Is this all we need?*/
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000018943 ctxt->nberrors = 0;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018944 ctxt->err = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000018945 ctxt->counter = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000018946
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018947 /* Create the *main* schema. */
18948 schema = xmlSchemaNewSchema(ctxt);
18949 if (schema == NULL)
18950 goto exit_failure;
Daniel Veillard4255d502002-04-16 15:50:10 +000018951 /*
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018952 * Create the schema constructor.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018953 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018954 if (ctxt->constructor == NULL) {
18955 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
18956 if (ctxt->constructor == NULL)
18957 return(NULL);
18958 /* Take ownership of the constructor to be able to free it. */
18959 ctxt->ownsConstructor = 1;
18960 }
18961 ctxt->constructor->schema = schema;
18962 /*
18963 * Locate and add the schema document.
18964 */
18965 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
18966 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
18967 NULL, NULL, &bucket);
18968 if (res == -1)
18969 goto exit_failure;
18970 if (res != 0)
18971 goto exit;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018972
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018973 if (bucket == NULL) {
18974 /* TODO: Error code, actually we failed to *locate* the schema. */
18975 if (ctxt->URL)
18976 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
18977 NULL, NULL,
18978 "Failed to locate the main schema resource at '%s'",
18979 ctxt->URL, NULL);
18980 else
18981 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
18982 NULL, NULL,
18983 "Failed to locate the main schema resource",
18984 NULL, NULL);
18985 goto exit;
18986 }
18987 /* Set the main schema bucket. */
18988 ctxt->constructor->bucket = bucket;
18989 ctxt->targetNamespace = bucket->targetNamespace;
18990 schema->targetNamespace = bucket->targetNamespace;
18991
18992 /* Then do the parsing for good. */
18993 if (xmlSchemaParseNewDocWithContext(ctxt, schema, bucket) == -1)
18994 goto exit_failure;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018995 if (ctxt->nberrors != 0)
18996 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018997
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000018998 schema->doc = bucket->doc;
18999 schema->preserve = ctxt->preserve;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019000
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019001 ctxt->schema = schema;
19002
19003 if (xmlSchemaFixupComponents(ctxt) == -1)
19004 goto exit_failure;
19005
19006 /*
19007 * TODO: This is not nice, since we cannot distinguish from the
19008 * result if there was an internal error or not.
19009 */
19010exit:
19011 if (ctxt->nberrors != 0) {
19012 if (schema) {
19013 xmlSchemaFree(schema);
19014 schema = NULL;
19015 }
19016 if (ctxt->constructor) {
19017 xmlSchemaConstructionCtxtFree(ctxt->constructor);
19018 ctxt->constructor = NULL;
19019 ctxt->ownsConstructor = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019020 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019021 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019022 ctxt->schema = NULL;
19023 return(schema);
19024exit_failure:
19025 /*
19026 * Quite verbose, but should catch internal errors, which were
19027 * not communitated.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019028 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019029 if (schema) {
19030 xmlSchemaFree(schema);
19031 schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019032 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019033 if (ctxt->constructor) {
19034 xmlSchemaConstructionCtxtFree(ctxt->constructor);
19035 ctxt->constructor = NULL;
19036 ctxt->ownsConstructor = 0;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000019037 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019038 PERROR_INT2("xmlSchemaParse",
19039 "An internal error occured");
19040 ctxt->schema = NULL;
19041 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000019042}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019043
Daniel Veillard4255d502002-04-16 15:50:10 +000019044/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000019045 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000019046 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000019047 * @err: the error callback
19048 * @warn: the warning callback
19049 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000019050 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000019051 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000019052 */
19053void
19054xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019055 xmlSchemaValidityErrorFunc err,
19056 xmlSchemaValidityWarningFunc warn, void *ctx)
19057{
Daniel Veillard4255d502002-04-16 15:50:10 +000019058 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019059 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000019060 ctxt->error = err;
19061 ctxt->warning = warn;
19062 ctxt->userData = ctx;
19063}
19064
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000019065/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000019066 * xmlSchemaGetParserErrors:
19067 * @ctxt: a XMl-Schema parser context
19068 * @err: the error callback result
19069 * @warn: the warning callback result
19070 * @ctx: contextual data for the callbacks result
19071 *
19072 * Get the callback information used to handle errors for a parser context
19073 *
19074 * Returns -1 in case of failure, 0 otherwise
19075 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019076int
Daniel Veillard259f0df2004-08-18 09:13:18 +000019077xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
19078 xmlSchemaValidityErrorFunc * err,
19079 xmlSchemaValidityWarningFunc * warn, void **ctx)
19080{
19081 if (ctxt == NULL)
19082 return(-1);
19083 if (err != NULL)
19084 *err = ctxt->error;
19085 if (warn != NULL)
19086 *warn = ctxt->warning;
19087 if (ctx != NULL)
19088 *ctx = ctxt->userData;
19089 return(0);
19090}
19091
19092/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000019093 * xmlSchemaFacetTypeToString:
19094 * @type: the facet type
19095 *
19096 * Convert the xmlSchemaTypeType to a char string.
19097 *
19098 * Returns the char string representation of the facet type if the
19099 * type is a facet and an "Internal Error" string otherwise.
19100 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019101static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000019102xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
19103{
19104 switch (type) {
19105 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019106 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019107 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019108 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019109 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019110 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019111 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019112 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019113 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019114 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019115 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019116 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019117 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019118 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019119 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019120 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019121 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019122 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019123 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019124 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019125 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019126 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019127 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019128 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000019129 default:
19130 break;
19131 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019132 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000019133}
19134
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019135static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000019136xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
19137{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019138 /*
19139 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000019140 * from xsd:string.
19141 */
19142 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019143 /*
19144 * Note that we assume a whitespace of preserve for anySimpleType.
19145 */
19146 if ((type->builtInType == XML_SCHEMAS_STRING) ||
19147 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
19148 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000019149 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019150 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019151 else {
19152 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019153 * For all ·atomic· datatypes other than string (and types ·derived·
19154 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000019155 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019156 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000019157 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019158 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019159 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019160 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019161 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019162 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019163 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019164 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
19165 } else if (VARIETY_UNION(type)) {
19166 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
19167 } else if (VARIETY_ATOMIC(type)) {
19168 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
19169 return (XML_SCHEMA_WHITESPACE_PRESERVE);
19170 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
19171 return (XML_SCHEMA_WHITESPACE_REPLACE);
19172 else
19173 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019174 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019175 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000019176}
19177
Daniel Veillard4255d502002-04-16 15:50:10 +000019178/************************************************************************
19179 * *
19180 * Simple type validation *
19181 * *
19182 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000019183
Daniel Veillard4255d502002-04-16 15:50:10 +000019184
19185/************************************************************************
19186 * *
19187 * DOM Validation code *
19188 * *
19189 ************************************************************************/
19190
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019191/**
19192 * xmlSchemaAssembleByLocation:
19193 * @pctxt: a schema parser context
19194 * @vctxt: a schema validation context
19195 * @schema: the existing schema
19196 * @node: the node that fired the assembling
19197 * @nsName: the namespace name of the new schema
19198 * @location: the location of the schema
19199 *
19200 * Expands an existing schema by an additional schema.
19201 *
19202 * Returns 0 if the new schema is correct, a positive error code
19203 * number otherwise and -1 in case of an internal or API error.
19204 */
19205static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019206xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019207 xmlSchemaPtr schema,
19208 xmlNodePtr node,
19209 const xmlChar *nsName,
19210 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019211{
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019212 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019213 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019214 xmlSchemaBucketPtr bucket = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019215
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019216 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019217 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019218
19219 if (vctxt->pctxt == NULL) {
19220 VERROR_INT("xmlSchemaAssembleByLocation",
19221 "no parser context available");
19222 return(-1);
19223 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019224 pctxt = vctxt->pctxt;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019225 if (pctxt->constructor == NULL) {
19226 PERROR_INT("xmlSchemaAssembleByLocation",
19227 "no constructor");
19228 return(-1);
19229 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019230 /*
19231 * Acquire the schema document.
19232 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019233 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
19234 location, node);
19235 /*
19236 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
19237 * the process will automatically change this to
19238 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
19239 */
19240 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
19241 location, NULL, NULL, 0, node, NULL, nsName,
19242 &bucket);
19243 if (ret != 0)
19244 return(ret);
19245 if (bucket == NULL) {
19246 PERROR_INT("xmlSchemaAssembleByLocation",
19247 "no schema bucket aquired");
19248 return(-1);
19249 }
19250 /*
19251 * The first located schema will be handled as if all other
19252 * schemas imported by XSI were imported by this first schema.
19253 */
19254 if ((bucket != NULL) &&
19255 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
19256 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
19257 /*
19258 * TODO: Is this handled like an import? I.e. is it not an error
19259 * if the schema cannot be located?
19260 */
19261 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
19262 return(0);
19263 /*
19264 * We will reuse the parser context for every schema imported
19265 * directly via XSI. So reset the context.
19266 */
19267 pctxt->nberrors = 0;
19268 pctxt->err = 0;
19269 pctxt->doc = bucket->doc;
19270
19271 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
19272 if (ret == -1) {
19273 pctxt->doc = NULL;
19274 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019275 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019276 /* Paranoid error channelling. */
19277 if ((ret == 0) && (pctxt->nberrors != 0))
19278 ret = pctxt->err;
19279 if (pctxt->nberrors == 0) {
19280 /*
19281 * Only bother to fixup pending components, if there was
19282 * no error yet.
19283 */
19284 xmlSchemaFixupComponents(pctxt);
19285 vctxt->nberrors += pctxt->nberrors;
19286 } else {
19287 /* Add to validation error sum. */
19288 vctxt->nberrors += pctxt->nberrors;
19289 }
19290 pctxt->doc = NULL;
19291 return(ret);
19292exit_failure:
19293 pctxt->doc = NULL;
19294 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019295}
19296
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019297static xmlSchemaAttrInfoPtr
19298xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
19299 int metaType)
19300{
19301 if (vctxt->nbAttrInfos == 0)
19302 return (NULL);
19303 {
19304 int i;
19305 xmlSchemaAttrInfoPtr iattr;
19306
19307 for (i = 0; i < vctxt->nbAttrInfos; i++) {
19308 iattr = vctxt->attrInfos[i];
19309 if (iattr->metaType == metaType)
19310 return (iattr);
19311 }
19312
19313 }
19314 return (NULL);
19315}
19316
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019317/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019318 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019319 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019320 *
19321 * Expands an existing schema by an additional schema using
19322 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
19323 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
19324 * must be set to 1.
19325 *
19326 * Returns 0 if the new schema is correct, a positive error code
19327 * number otherwise and -1 in case of an internal or API error.
19328 */
19329static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019330xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019331{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019332 const xmlChar *cur, *end;
19333 const xmlChar *nsname = NULL, *location;
19334 int count = 0;
19335 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019336 xmlSchemaAttrInfoPtr iattr;
19337
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019338 /*
19339 * Parse the value; we will assume an even number of values
19340 * to be given (this is how Xerces and XSV work).
19341 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019342 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
19343 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
19344 if (iattr == NULL)
19345 xmlSchemaGetMetaAttrInfo(vctxt,
19346 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
19347 if (iattr == NULL)
19348 return (0);
19349 cur = iattr->value;
19350 do {
19351 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019352 /*
19353 * Get the namespace name.
19354 */
19355 while (IS_BLANK_CH(*cur))
19356 cur++;
19357 end = cur;
19358 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
19359 end++;
19360 if (end == cur)
19361 break;
19362 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019363 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019364 cur = end;
19365 }
19366 /*
19367 * Get the URI.
19368 */
19369 while (IS_BLANK_CH(*cur))
19370 cur++;
19371 end = cur;
19372 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
19373 end++;
19374 if (end == cur)
19375 break;
19376 count++;
19377 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019378 cur = end;
19379 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
19380 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019381 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019382 VERROR_INT("xmlSchemaAssembleByXSI",
19383 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019384 return (-1);
19385 }
19386 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019387 return (ret);
19388}
19389
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019390static const xmlChar *
19391xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
19392 const xmlChar *prefix)
19393{
19394 if (vctxt->sax != NULL) {
19395 int i, j;
19396 xmlSchemaNodeInfoPtr inode;
19397
19398 for (i = vctxt->depth; i >= 0; i--) {
19399 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
19400 inode = vctxt->elemInfos[i];
19401 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
19402 if (((prefix == NULL) &&
19403 (inode->nsBindings[j] == NULL)) ||
19404 ((prefix != NULL) && xmlStrEqual(prefix,
19405 inode->nsBindings[j]))) {
19406
19407 /*
19408 * Note that the namespace bindings are already
19409 * in a string dict.
19410 */
19411 return (inode->nsBindings[j+1]);
19412 }
19413 }
19414 }
19415 }
19416 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000019417#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019418 } else if (vctxt->reader != NULL) {
19419 xmlChar *nsName;
19420
19421 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
19422 if (nsName != NULL) {
19423 const xmlChar *ret;
19424
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019425 ret = xmlDictLookup(vctxt->dict, nsName, -1);
19426 xmlFree(nsName);
19427 return (ret);
19428 } else
19429 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000019430#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019431 } else {
19432 xmlNsPtr ns;
19433
19434 if ((vctxt->inode->node == NULL) ||
19435 (vctxt->inode->node->doc == NULL)) {
19436 VERROR_INT("xmlSchemaLookupNamespace",
19437 "no node or node's doc avaliable");
19438 return (NULL);
19439 }
19440 ns = xmlSearchNs(vctxt->inode->node->doc,
19441 vctxt->inode->node, prefix);
19442 if (ns != NULL)
19443 return (ns->href);
19444 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019445 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019446}
19447
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019448/*
19449* This one works on the schema of the validation context.
19450*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019451static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019452xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
19453 xmlSchemaPtr schema,
19454 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019455 const xmlChar *value,
19456 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019457 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019458{
19459 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019460
19461 if (vctxt && (vctxt->schema == NULL)) {
19462 VERROR_INT("xmlSchemaValidateNotation",
19463 "a schema is needed on the validation context");
19464 return (-1);
19465 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019466 ret = xmlValidateQName(value, 1);
19467 if (ret != 0)
19468 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019469 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019470 xmlChar *localName = NULL;
19471 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019472
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019473 localName = xmlSplitQName2(value, &prefix);
19474 if (prefix != NULL) {
19475 const xmlChar *nsName = NULL;
19476
19477 if (vctxt != NULL)
19478 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
19479 else if (node != NULL) {
19480 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
19481 if (ns != NULL)
19482 nsName = ns->href;
19483 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019484 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019485 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019486 return (1);
19487 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019488 if (nsName == NULL) {
19489 xmlFree(prefix);
19490 xmlFree(localName);
19491 return (1);
19492 }
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019493 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019494 if (valNeeded && (val != NULL)) {
19495 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
19496 BAD_CAST xmlStrdup(nsName));
19497 if (*val == NULL)
19498 ret = -1;
19499 }
19500 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000019501 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019502 xmlFree(prefix);
19503 xmlFree(localName);
19504 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000019505 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019506 if (valNeeded && (val != NULL)) {
19507 (*val) = xmlSchemaNewNOTATIONValue(
19508 BAD_CAST xmlStrdup(value), NULL);
19509 if (*val == NULL)
19510 ret = -1;
19511 }
19512 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019513 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019514 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019515 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019516 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019517}
19518
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000019519static int
19520xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
19521 const xmlChar* lname,
19522 const xmlChar* nsname)
19523{
19524 int i;
19525
19526 lname = xmlDictLookup(vctxt->dict, lname, -1);
19527 if (lname == NULL)
19528 return(-1);
19529 if (nsname != NULL) {
19530 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
19531 if (nsname == NULL)
19532 return(-1);
19533 }
19534 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
19535 if ((vctxt->nodeQNames->items [i] == lname) &&
19536 (vctxt->nodeQNames->items[i +1] == nsname))
19537 /* Already there */
19538 return(i);
19539 }
19540 /* Add new entry. */
19541 i = vctxt->nodeQNames->nbItems;
19542 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
19543 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
19544 return(i);
19545}
19546
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019547/************************************************************************
19548 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019549 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019550 * *
19551 ************************************************************************/
19552
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019553/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019554 * xmlSchemaAugmentIDC:
19555 * @idcDef: the IDC definition
19556 *
19557 * Creates an augmented IDC definition item.
19558 *
19559 * Returns the item, or NULL on internal errors.
19560 */
19561static void
19562xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
19563 xmlSchemaValidCtxtPtr vctxt)
19564{
19565 xmlSchemaIDCAugPtr aidc;
19566
19567 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
19568 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019569 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019570 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
19571 NULL);
19572 return;
19573 }
19574 aidc->bubbleDepth = -1;
19575 aidc->def = idcDef;
19576 aidc->next = NULL;
19577 if (vctxt->aidcs == NULL)
19578 vctxt->aidcs = aidc;
19579 else {
19580 aidc->next = vctxt->aidcs;
19581 vctxt->aidcs = aidc;
19582 }
19583}
19584
19585/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019586 * xmlSchemaIDCNewBinding:
19587 * @idcDef: the IDC definition of this binding
19588 *
19589 * Creates a new IDC binding.
19590 *
19591 * Returns the new binding in case of succeeded, NULL on internal errors.
19592 */
19593static xmlSchemaPSVIIDCBindingPtr
19594xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
19595{
19596 xmlSchemaPSVIIDCBindingPtr ret;
19597
19598 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
19599 sizeof(xmlSchemaPSVIIDCBinding));
19600 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019601 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019602 "allocating a PSVI IDC binding item", NULL);
19603 return (NULL);
19604 }
19605 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
19606 ret->definition = idcDef;
19607 return (ret);
19608}
19609
19610/**
19611 * xmlSchemaIDCStoreNodeTableItem:
19612 * @vctxt: the WXS validation context
19613 * @item: the IDC node table item
19614 *
19615 * The validation context is used to store an IDC node table items.
19616 * They are stored to avoid copying them if IDC node-tables are merged
19617 * with corresponding parent IDC node-tables (bubbling).
19618 *
19619 * Returns 0 if succeeded, -1 on internal errors.
19620 */
19621static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019622xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019623 xmlSchemaPSVIIDCNodePtr item)
19624{
19625 /*
19626 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019627 */
19628 if (vctxt->idcNodes == NULL) {
19629 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019630 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
19631 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019632 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019633 "allocating the IDC node table item list", NULL);
19634 return (-1);
19635 }
19636 vctxt->sizeIdcNodes = 20;
19637 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
19638 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019639 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
19640 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019641 sizeof(xmlSchemaPSVIIDCNodePtr));
19642 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019643 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019644 "re-allocating the IDC node table item list", NULL);
19645 return (-1);
19646 }
19647 }
19648 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019649
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019650 return (0);
19651}
19652
19653/**
19654 * xmlSchemaIDCStoreKey:
19655 * @vctxt: the WXS validation context
19656 * @item: the IDC key
19657 *
19658 * The validation context is used to store an IDC key.
19659 *
19660 * Returns 0 if succeeded, -1 on internal errors.
19661 */
19662static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019663xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019664 xmlSchemaPSVIIDCKeyPtr key)
19665{
19666 /*
19667 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019668 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019669 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019670 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019671 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
19672 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019673 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019674 "allocating the IDC key storage list", NULL);
19675 return (-1);
19676 }
19677 vctxt->sizeIdcKeys = 40;
19678 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
19679 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019680 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
19681 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019682 sizeof(xmlSchemaPSVIIDCKeyPtr));
19683 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019684 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019685 "re-allocating the IDC key storage list", NULL);
19686 return (-1);
19687 }
19688 }
19689 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019690
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019691 return (0);
19692}
19693
19694/**
19695 * xmlSchemaIDCAppendNodeTableItem:
19696 * @bind: the IDC binding
19697 * @ntItem: the node-table item
19698 *
19699 * Appends the IDC node-table item to the binding.
19700 *
19701 * Returns 0 on success and -1 on internal errors.
19702 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019703static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019704xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
19705 xmlSchemaPSVIIDCNodePtr ntItem)
19706{
19707 if (bind->nodeTable == NULL) {
19708 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019709 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019710 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
19711 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019712 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019713 "allocating an array of IDC node-table items", NULL);
19714 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019715 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019716 } else if (bind->sizeNodes <= bind->nbNodes) {
19717 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019718 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19719 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019720 sizeof(xmlSchemaPSVIIDCNodePtr));
19721 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019722 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019723 "re-allocating an array of IDC node-table items", NULL);
19724 return(-1);
19725 }
19726 }
19727 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019728 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019729}
19730
19731/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019732 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019733 * @vctxt: the WXS validation context
19734 * @matcher: the IDC matcher
19735 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019736 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019737 * of the given matcher. If none found, a new one is created
19738 * and added to the IDC table.
19739 *
19740 * Returns an IDC binding or NULL on internal errors.
19741 */
19742static xmlSchemaPSVIIDCBindingPtr
19743xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
19744 xmlSchemaIDCMatcherPtr matcher)
19745{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019746 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019747
19748 info = vctxt->elemInfos[matcher->depth];
19749
19750 if (info->idcTable == NULL) {
19751 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
19752 if (info->idcTable == NULL)
19753 return (NULL);
19754 return(info->idcTable);
19755 } else {
19756 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019757
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019758 bind = info->idcTable;
19759 do {
19760 if (bind->definition == matcher->aidc->def)
19761 return(bind);
19762 if (bind->next == NULL) {
19763 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
19764 if (bind->next == NULL)
19765 return (NULL);
19766 return(bind->next);
19767 }
19768 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019769 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019770 }
19771 return (NULL);
19772}
19773
19774/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019775 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019776 * @key: the IDC key
19777 *
19778 * Frees an IDC key together with its compiled value.
19779 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019780static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019781xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
19782{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019783 if (key->val != NULL)
19784 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019785 xmlFree(key);
19786}
19787
19788/**
19789 * xmlSchemaIDCFreeBinding:
19790 *
19791 * Frees an IDC binding. Note that the node table-items
19792 * are not freed.
19793 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019794static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019795xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
19796{
19797 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019798 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19799 int i;
19800 /*
19801 * Node-table items for keyrefs are not stored globally
19802 * to the validation context, since they are not bubbled.
19803 * We need to free them here.
19804 */
19805 for (i = 0; i < bind->nbNodes; i++) {
19806 xmlFree(bind->nodeTable[i]->keys);
19807 xmlFree(bind->nodeTable[i]);
19808 }
19809 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019810 xmlFree(bind->nodeTable);
19811 }
19812 xmlFree(bind);
19813}
19814
19815/**
19816 * xmlSchemaIDCFreeIDCTable:
19817 * @bind: the first IDC binding in the list
19818 *
19819 * Frees an IDC table, i.e. all the IDC bindings in the list.
19820 */
19821static void
19822xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
19823{
19824 xmlSchemaPSVIIDCBindingPtr prev;
19825
19826 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019827 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019828 bind = bind->next;
19829 xmlSchemaIDCFreeBinding(prev);
19830 }
19831}
19832
19833/**
19834 * xmlSchemaIDCFreeMatcherList:
19835 * @matcher: the first IDC matcher in the list
19836 *
19837 * Frees a list of IDC matchers.
19838 */
19839static void
19840xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
19841{
19842 xmlSchemaIDCMatcherPtr next;
19843
19844 while (matcher != NULL) {
19845 next = matcher->next;
19846 if (matcher->keySeqs != NULL) {
19847 int i;
19848 for (i = 0; i < matcher->sizeKeySeqs; i++)
19849 if (matcher->keySeqs[i] != NULL)
19850 xmlFree(matcher->keySeqs[i]);
19851 xmlFree(matcher->keySeqs);
19852 }
19853 xmlFree(matcher);
19854 matcher = next;
19855 }
19856}
19857
19858/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019859 * xmlSchemaIDCAddStateObject:
19860 * @vctxt: the WXS validation context
19861 * @matcher: the IDC matcher
19862 * @sel: the XPath information
19863 * @parent: the parent "selector" state object if any
19864 * @type: "selector" or "field"
19865 *
19866 * Creates/reuses and activates state objects for the given
19867 * XPath information; if the XPath expression consists of unions,
19868 * multiple state objects are created for every unioned expression.
19869 *
19870 * Returns 0 on success and -1 on internal errors.
19871 */
19872static int
19873xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
19874 xmlSchemaIDCMatcherPtr matcher,
19875 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019876 int type)
19877{
19878 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019879
19880 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019881 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019882 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019883 if (vctxt->xpathStatePool != NULL) {
19884 sto = vctxt->xpathStatePool;
19885 vctxt->xpathStatePool = sto->next;
19886 sto->next = NULL;
19887 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019888 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019889 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019890 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019891 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
19892 if (sto == NULL) {
19893 xmlSchemaVErrMemory(NULL,
19894 "allocating an IDC state object", NULL);
19895 return (-1);
19896 }
19897 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
19898 }
19899 /*
19900 * Add to global list.
19901 */
19902 if (vctxt->xpathStates != NULL)
19903 sto->next = vctxt->xpathStates;
19904 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019905
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019906 /*
19907 * Free the old xpath validation context.
19908 */
19909 if (sto->xpathCtxt != NULL)
19910 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
19911
19912 /*
19913 * Create a new XPath (pattern) validation context.
19914 */
19915 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
19916 (xmlPatternPtr) sel->xpathComp);
19917 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019918 VERROR_INT("xmlSchemaIDCAddStateObject",
19919 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019920 return (-1);
19921 }
19922 sto->type = type;
19923 sto->depth = vctxt->depth;
19924 sto->matcher = matcher;
19925 sto->sel = sel;
19926 sto->nbHistory = 0;
19927
19928#if DEBUG_IDC
19929 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
19930 sto->sel->xpath);
19931#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019932 return (0);
19933}
19934
19935/**
19936 * xmlSchemaXPathEvaluate:
19937 * @vctxt: the WXS validation context
19938 * @nodeType: the nodeType of the current node
19939 *
19940 * Evaluates all active XPath state objects.
19941 *
19942 * Returns the number of IC "field" state objects which resolved to
19943 * this node, 0 if none resolved and -1 on internal errors.
19944 */
19945static int
19946xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019947 xmlElementType nodeType)
19948{
19949 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019950 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019951
19952 if (vctxt->xpathStates == NULL)
19953 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019954
19955 if (nodeType == XML_ATTRIBUTE_NODE)
19956 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019957#if DEBUG_IDC
19958 {
19959 xmlChar *str = NULL;
19960 xmlGenericError(xmlGenericErrorContext,
19961 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019962 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19963 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019964 FREE_AND_NULL(str)
19965 }
19966#endif
19967 /*
19968 * Process all active XPath state objects.
19969 */
19970 first = vctxt->xpathStates;
19971 sto = first;
19972 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019973#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019974 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019975 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
19976 sto->matcher->aidc->def->name, sto->sel->xpath);
19977 else
19978 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
19979 sto->matcher->aidc->def->name, sto->sel->xpath);
19980#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019981 if (nodeType == XML_ELEMENT_NODE)
19982 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019983 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019984 else
19985 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019986 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019987
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019988 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019989 VERROR_INT("xmlSchemaXPathEvaluate",
19990 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019991 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019992 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019993 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019994 goto next_sto;
19995 /*
19996 * Full match.
19997 */
19998#if DEBUG_IDC
19999 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020000 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020001#endif
20002 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020003 * Register a match in the state object history.
20004 */
20005 if (sto->history == NULL) {
20006 sto->history = (int *) xmlMalloc(5 * sizeof(int));
20007 if (sto->history == NULL) {
20008 xmlSchemaVErrMemory(NULL,
20009 "allocating the state object history", NULL);
20010 return(-1);
20011 }
20012 sto->sizeHistory = 10;
20013 } else if (sto->sizeHistory <= sto->nbHistory) {
20014 sto->sizeHistory *= 2;
20015 sto->history = (int *) xmlRealloc(sto->history,
20016 sto->sizeHistory * sizeof(int));
20017 if (sto->history == NULL) {
20018 xmlSchemaVErrMemory(NULL,
20019 "re-allocating the state object history", NULL);
20020 return(-1);
20021 }
20022 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020023 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020024
20025#ifdef DEBUG_IDC
20026 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
20027 vctxt->depth);
20028#endif
20029
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020030 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
20031 xmlSchemaIDCSelectPtr sel;
20032 /*
20033 * Activate state objects for the IDC fields of
20034 * the IDC selector.
20035 */
20036#if DEBUG_IDC
20037 xmlGenericError(xmlGenericErrorContext, "IDC: "
20038 "activating field states\n");
20039#endif
20040 sel = sto->matcher->aidc->def->fields;
20041 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020042 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
20043 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
20044 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020045 sel = sel->next;
20046 }
20047 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
20048 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000020049 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020050 */
20051#if DEBUG_IDC
20052 xmlGenericError(xmlGenericErrorContext,
20053 "IDC: key found\n");
20054#endif
20055 /*
20056 * Notify that the character value of this node is
20057 * needed.
20058 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020059 if (resolved == 0) {
20060 if ((vctxt->inode->flags &
20061 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
20062 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
20063 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020064 resolved++;
20065 }
20066next_sto:
20067 if (sto->next == NULL) {
20068 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020069 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020070 */
20071 head = first;
20072 sto = vctxt->xpathStates;
20073 } else
20074 sto = sto->next;
20075 }
20076 return (resolved);
20077}
20078
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020079static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020080xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020081 xmlChar **buf,
20082 xmlSchemaPSVIIDCKeyPtr *seq,
20083 int count)
20084{
20085 int i, res;
20086 const xmlChar *value = NULL;
20087
20088 *buf = xmlStrdup(BAD_CAST "[");
20089 for (i = 0; i < count; i++) {
20090 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020091 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
20092 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020093 if (res == 0)
20094 *buf = xmlStrcat(*buf, value);
20095 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020096 VERROR_INT("xmlSchemaFormatIDCKeySequence",
20097 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020098 *buf = xmlStrcat(*buf, BAD_CAST "???");
20099 }
20100 if (i < count -1)
20101 *buf = xmlStrcat(*buf, BAD_CAST "', ");
20102 else
20103 *buf = xmlStrcat(*buf, BAD_CAST "'");
20104 if (value != NULL) {
20105 xmlFree((xmlChar *) value);
20106 value = NULL;
20107 }
20108 }
20109 *buf = xmlStrcat(*buf, BAD_CAST "]");
20110
20111 return (BAD_CAST *buf);
20112}
20113
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020114/**
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000020115 * xmlSchemaXPathPop:
20116 * @vctxt: the WXS validation context
20117 *
20118 * Pops all XPath states.
20119 *
20120 * Returns 0 on success and -1 on internal errors.
20121 */
20122static int
20123xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
20124{
20125 xmlSchemaIDCStateObjPtr sto;
20126 int res;
20127
20128 if (vctxt->xpathStates == NULL)
20129 return(0);
20130 sto = vctxt->xpathStates;
20131 do {
20132 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
20133 if (res == -1)
20134 return (-1);
20135 sto = sto->next;
20136 } while (sto != NULL);
20137 return(0);
20138}
20139
20140/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020141 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020142 * @vctxt: the WXS validation context
20143 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020144 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020145 *
20146 * Processes and pops the history items of the IDC state objects.
20147 * IDC key-sequences are validated/created on IDC bindings.
20148 *
20149 * Returns 0 on success and -1 on internal errors.
20150 */
20151static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020152xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020153 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020154{
20155 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020156 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020157 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020158 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020159
20160 if (vctxt->xpathStates == NULL)
20161 return (0);
20162 sto = vctxt->xpathStates;
20163
20164#if DEBUG_IDC
20165 {
20166 xmlChar *str = NULL;
20167 xmlGenericError(xmlGenericErrorContext,
20168 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020169 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
20170 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020171 FREE_AND_NULL(str)
20172 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020173#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020174 /*
20175 * Evaluate the state objects.
20176 */
20177 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000020178 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
20179 if (res == -1) {
20180 VERROR_INT("xmlSchemaXPathProcessHistory",
20181 "calling xmlStreamPop()");
20182 return (-1);
20183 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020184#if DEBUG_IDC
20185 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
20186 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020187#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020188 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020189 goto deregister_check;
20190
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020191 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020192
20193 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020194 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020195 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020196 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020197 sto = sto->next;
20198 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020199 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020200 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
20201 if (! IS_SIMPLE_TYPE(type)) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020202 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020203 /*
20204 * Not qualified if the field resolves to a node of non
20205 * simple type.
20206 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020207 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020208 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020209 (xmlSchemaTypePtr) sto->matcher->aidc->def,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020210 "The field '%s' of %s does evaluate to a node of "
20211 "non-simple type",
20212 sto->sel->xpath,
20213 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
20214 FREE_AND_NULL(str);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020215 sto->nbHistory--;
20216 goto deregister_check;
20217 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020218 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020219 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020220 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020221 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020222 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020223 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000020224 (xmlSchemaTypePtr) sto->matcher->aidc->def,
20225 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020226 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020227 sto->nbHistory--;
20228 goto deregister_check;
20229 } else {
20230 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
20231 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020232 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020233
20234 /*
20235 * The key will be anchored on the matcher's list of
20236 * key-sequences. The position in this list is determined
20237 * by the target node's depth relative to the matcher's
20238 * depth of creation (i.e. the depth of the scope element).
20239 */
20240 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020241 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020242
20243 /*
20244 * Create/grow the array of key-sequences.
20245 */
20246 if (matcher->keySeqs == NULL) {
20247 if (pos > 9)
20248 matcher->sizeKeySeqs = pos * 2;
20249 else
20250 matcher->sizeKeySeqs = 10;
20251 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
20252 xmlMalloc(matcher->sizeKeySeqs *
20253 sizeof(xmlSchemaPSVIIDCKeyPtr *));
20254 if (matcher->keySeqs == NULL) {
20255 xmlSchemaVErrMemory(NULL,
20256 "allocating an array of key-sequences",
20257 NULL);
20258 return(-1);
20259 }
20260 memset(matcher->keySeqs, 0,
20261 matcher->sizeKeySeqs *
20262 sizeof(xmlSchemaPSVIIDCKeyPtr *));
20263 } else if (pos >= matcher->sizeKeySeqs) {
20264 int i = matcher->sizeKeySeqs;
20265
20266 matcher->sizeKeySeqs *= 2;
20267 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
20268 xmlRealloc(matcher->keySeqs,
20269 matcher->sizeKeySeqs *
20270 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020271 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020272 xmlSchemaVErrMemory(NULL,
20273 "reallocating an array of key-sequences",
20274 NULL);
20275 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020276 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020277 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020278 * The array needs to be NULLed.
20279 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020280 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020281 for (; i < matcher->sizeKeySeqs; i++)
20282 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020283 }
20284
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020285 /*
20286 * Get/create the key-sequence.
20287 */
20288 keySeq = matcher->keySeqs[pos];
20289 if (keySeq == NULL) {
20290 goto create_sequence;
20291 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020292 if (keySeq[idx] != NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020293 xmlChar *str = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020294 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020295 * cvc-identity-constraint:
20296 * 3 For each node in the ·target node set· all
20297 * of the {fields}, with that node as the context
20298 * node, evaluate to either an empty node-set or
20299 * a node-set with exactly one member, which must
20300 * have a simple type.
20301 *
20302 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020303 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020304 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020305 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020306 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020307 "The field '%s' of %s evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020308 "with more than one member",
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020309 sto->sel->xpath,
20310 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
20311 FREE_AND_NULL(str);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020312 sto->nbHistory--;
20313 goto deregister_check;
20314 } else {
20315 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020316 }
20317 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020318
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020319create_sequence:
20320 /*
20321 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020322 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020323 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
20324 matcher->aidc->def->nbFields *
20325 sizeof(xmlSchemaPSVIIDCKeyPtr));
20326 if (keySeq == NULL) {
20327 xmlSchemaVErrMemory(NULL,
20328 "allocating an IDC key-sequence", NULL);
20329 return(-1);
20330 }
20331 memset(keySeq, 0, matcher->aidc->def->nbFields *
20332 sizeof(xmlSchemaPSVIIDCKeyPtr));
20333 matcher->keySeqs[pos] = keySeq;
20334create_key:
20335 /*
20336 * Created a key once per node only.
20337 */
20338 if (key == NULL) {
20339 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
20340 sizeof(xmlSchemaPSVIIDCKey));
20341 if (key == NULL) {
20342 xmlSchemaVErrMemory(NULL,
20343 "allocating a IDC key", NULL);
20344 xmlFree(keySeq);
20345 matcher->keySeqs[pos] = NULL;
20346 return(-1);
20347 }
20348 /*
20349 * Consume the compiled value.
20350 */
20351 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020352 key->val = vctxt->inode->val;
20353 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020354 /*
20355 * Store the key in a global list.
20356 */
20357 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
20358 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020359 return (-1);
20360 }
20361 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020362 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020363 }
20364 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020365
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020366 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
20367 xmlSchemaPSVIIDCBindingPtr bind;
20368 xmlSchemaPSVIIDCNodePtr ntItem;
20369 xmlSchemaIDCMatcherPtr matcher;
20370 xmlSchemaIDCPtr idc;
20371 int pos, i, j, nbKeys;
20372 /*
20373 * Here we have the following scenario:
20374 * An IDC 'selector' state object resolved to a target node,
20375 * during the time this target node was in the
20376 * ancestor-or-self axis, the 'field' state object(s) looked
20377 * out for matching nodes to create a key-sequence for this
20378 * target node. Now we are back to this target node and need
20379 * to put the key-sequence, together with the target node
20380 * itself, into the node-table of the corresponding IDC
20381 * binding.
20382 */
20383 matcher = sto->matcher;
20384 idc = matcher->aidc->def;
20385 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020386 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020387 /*
20388 * Check if the matcher has any key-sequences at all, plus
20389 * if it has a key-sequence for the current target node.
20390 */
20391 if ((matcher->keySeqs == NULL) ||
20392 (matcher->sizeKeySeqs <= pos)) {
20393 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
20394 goto selector_key_error;
20395 else
20396 goto selector_leave;
20397 }
20398
20399 keySeq = &(matcher->keySeqs[pos]);
20400 if (*keySeq == NULL) {
20401 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
20402 goto selector_key_error;
20403 else
20404 goto selector_leave;
20405 }
20406
20407 for (i = 0; i < nbKeys; i++) {
20408 if ((*keySeq)[i] == NULL) {
20409 /*
20410 * Not qualified, if not all fields did resolve.
20411 */
20412 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
20413 /*
20414 * All fields of a "key" IDC must resolve.
20415 */
20416 goto selector_key_error;
20417 }
20418 goto selector_leave;
20419 }
20420 }
20421 /*
20422 * All fields did resolve.
20423 */
20424
20425 /*
20426 * 4.1 If the {identity-constraint category} is unique(/key),
20427 * then no two members of the ·qualified node set· have
20428 * ·key-sequences· whose members are pairwise equal, as
20429 * defined by Equal in [XML Schemas: Datatypes].
20430 *
20431 * Get the IDC binding from the matcher and check for
20432 * duplicate key-sequences.
20433 */
20434 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
20435 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
20436 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020437 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020438
20439 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020440 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020441 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020442 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020443 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020444 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020445 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020446 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020447 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020448 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020449 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020450 if (res == -1) {
20451 return (-1);
20452 } else if (res == 0)
20453 break;
20454 }
20455 if (res == 1) {
20456 /*
20457 * Duplicate found.
20458 */
20459 break;
20460 }
20461 i++;
20462 } while (i < bind->nbNodes);
20463 if (i != bind->nbNodes) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020464 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020465 /*
20466 * TODO: Try to report the key-sequence.
20467 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020468 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020469 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020470 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020471 "Duplicate key-sequence %s in %s",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020472 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020473 (*keySeq), nbKeys),
20474 xmlSchemaGetIDCDesignation(&strB, idc));
20475 FREE_AND_NULL(str);
20476 FREE_AND_NULL(strB);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020477 goto selector_leave;
20478 }
20479 }
20480 /*
20481 * Add a node-table item to the IDC binding.
20482 */
20483 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
20484 sizeof(xmlSchemaPSVIIDCNode));
20485 if (ntItem == NULL) {
20486 xmlSchemaVErrMemory(NULL,
20487 "allocating an IDC node-table item", NULL);
20488 xmlFree(*keySeq);
20489 *keySeq = NULL;
20490 return(-1);
20491 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000020492 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020493
20494 /*
20495 * Store the node-table item on global list.
20496 */
20497 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
20498 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
20499 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020500 xmlFree(*keySeq);
20501 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020502 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020503 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000020504 ntItem->nodeQNameID = -1;
20505 } else {
20506 /*
20507 * Save a cached QName for this node on the IDC node, to be
20508 * able to report it, even if the node is not saved.
20509 */
20510 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
20511 vctxt->inode->localName, vctxt->inode->nsName);
20512 if (ntItem->nodeQNameID == -1) {
20513 xmlFree(ntItem);
20514 xmlFree(*keySeq);
20515 *keySeq = NULL;
20516 return (-1);
20517 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020518 }
20519 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000020520 * Init the node-table item: Save the node, position and
20521 * consume the key-sequence.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020522 */
20523 ntItem->node = vctxt->node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000020524 ntItem->nodeLine = vctxt->inode->nodeLine;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020525 ntItem->keys = *keySeq;
20526 *keySeq = NULL;
20527 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
20528 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20529 /*
20530 * Free the item, since keyref items won't be
20531 * put on a global list.
20532 */
20533 xmlFree(ntItem->keys);
20534 xmlFree(ntItem);
20535 }
20536 return (-1);
20537 }
20538
20539 goto selector_leave;
20540selector_key_error:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000020541 {
20542 xmlChar *str = NULL;
20543 /*
20544 * 4.2.1 (KEY) The ·target node set· and the
20545 * ·qualified node set· are equal, that is, every
20546 * member of the ·target node set· is also a member
20547 * of the ·qualified node set· and vice versa.
20548 */
20549 xmlSchemaCustomErr(ACTXT_CAST vctxt,
20550 XML_SCHEMAV_CVC_IDC, NULL,
20551 (xmlSchemaTypePtr) idc,
20552 "Not all fields of %s evaluate to a node",
20553 xmlSchemaGetIDCDesignation(&str, idc), NULL);
20554 FREE_AND_NULL(str);
20555 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020556selector_leave:
20557 /*
20558 * Free the key-sequence if not added to the IDC table.
20559 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020560 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020561 xmlFree(*keySeq);
20562 *keySeq = NULL;
20563 }
20564 } /* if selector */
20565
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020566 sto->nbHistory--;
20567
20568deregister_check:
20569 /*
20570 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020571 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020572 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020573#if DEBUG_IDC
20574 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
20575 sto->sel->xpath);
20576#endif
20577 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020578 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020579 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020580 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020581 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020582 nextsto = sto->next;
20583 /*
20584 * Unlink from the list of active XPath state objects.
20585 */
20586 vctxt->xpathStates = sto->next;
20587 sto->next = vctxt->xpathStatePool;
20588 /*
20589 * Link it to the pool of reusable state objects.
20590 */
20591 vctxt->xpathStatePool = sto;
20592 sto = nextsto;
20593 } else
20594 sto = sto->next;
20595 } /* while (sto != NULL) */
20596 return (0);
20597}
20598
20599/**
20600 * xmlSchemaIDCRegisterMatchers:
20601 * @vctxt: the WXS validation context
20602 * @elemDecl: the element declaration
20603 *
20604 * Creates helper objects to evaluate IDC selectors/fields
20605 * successively.
20606 *
20607 * Returns 0 if OK and -1 on internal errors.
20608 */
20609static int
20610xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
20611 xmlSchemaElementPtr elemDecl)
20612{
20613 xmlSchemaIDCMatcherPtr matcher, last = NULL;
20614 xmlSchemaIDCPtr idc, refIdc;
20615 xmlSchemaIDCAugPtr aidc;
20616
20617 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
20618 if (idc == NULL)
20619 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020620
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020621#if DEBUG_IDC
20622 {
20623 xmlChar *str = NULL;
20624 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020625 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020626 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
20627 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020628 FREE_AND_NULL(str)
20629 }
20630#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020631 if (vctxt->inode->idcMatchers != NULL) {
20632 VERROR_INT("xmlSchemaIDCRegisterMatchers",
20633 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020634 return (-1);
20635 }
20636 do {
20637 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20638 /*
20639 * Since IDCs bubbles are expensive we need to know the
20640 * depth at which the bubbles should stop; this will be
20641 * the depth of the top-most keyref IDC. If no keyref
20642 * references a key/unique IDC, the bubbleDepth will
20643 * be -1, indicating that no bubbles are needed.
20644 */
20645 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
20646 if (refIdc != NULL) {
20647 /*
20648 * Lookup the augmented IDC.
20649 */
20650 aidc = vctxt->aidcs;
20651 while (aidc != NULL) {
20652 if (aidc->def == refIdc)
20653 break;
20654 aidc = aidc->next;
20655 }
20656 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020657 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020658 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020659 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020660 return (-1);
20661 }
20662 if ((aidc->bubbleDepth == -1) ||
20663 (vctxt->depth < aidc->bubbleDepth))
20664 aidc->bubbleDepth = vctxt->depth;
20665 }
20666 }
20667 /*
20668 * Lookup the augmented IDC item for the IDC definition.
20669 */
20670 aidc = vctxt->aidcs;
20671 while (aidc != NULL) {
20672 if (aidc->def == idc)
20673 break;
20674 aidc = aidc->next;
20675 }
20676 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020677 VERROR_INT("xmlSchemaIDCRegisterMatchers",
20678 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020679 return (-1);
20680 }
20681 /*
20682 * Create an IDC matcher for every IDC definition.
20683 */
20684 matcher = (xmlSchemaIDCMatcherPtr)
20685 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
20686 if (matcher == NULL) {
20687 xmlSchemaVErrMemory(vctxt,
20688 "allocating an IDC matcher", NULL);
20689 return (-1);
20690 }
20691 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
20692 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020693 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020694 else
20695 last->next = matcher;
20696 last = matcher;
20697
20698 matcher->type = IDC_MATCHER;
20699 matcher->depth = vctxt->depth;
20700 matcher->aidc = aidc;
20701#if DEBUG_IDC
20702 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
20703#endif
20704 /*
20705 * Init the automaton state object.
20706 */
20707 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020708 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020709 return (-1);
20710
20711 idc = idc->next;
20712 } while (idc != NULL);
20713 return (0);
20714}
20715
20716/**
20717 * xmlSchemaBubbleIDCNodeTables:
20718 * @depth: the current tree depth
20719 *
20720 * Merges IDC bindings of an element at @depth into the corresponding IDC
20721 * bindings of its parent element. If a duplicate note-table entry is found,
20722 * both, the parent node-table entry and child entry are discarded from the
20723 * node-table of the parent.
20724 *
20725 * Returns 0 if OK and -1 on internal errors.
20726 */
20727static int
20728xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
20729{
20730 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020731 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
20732 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020733 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
20734 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020735 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020736 int duplTop;
20737
20738 /*
20739 * The node table has the following sections:
20740 *
20741 * O --> old node-table entries (first)
20742 * O
20743 * + --> new node-table entries
20744 * +
20745 * % --> new duplicate node-table entries
20746 * %
20747 * # --> old duplicate node-table entries
20748 * # (last)
20749 *
20750 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020751 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020752 if (bind == NULL) {
20753 /* Fine, no table, no bubbles. */
20754 return (0);
20755 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020756
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020757 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
20758 /*
20759 * Walk all bindings; create new or add to existing bindings.
20760 * Remove duplicate key-sequences.
20761 */
20762start_binding:
20763 while (bind != NULL) {
20764 /*
20765 * Skip keyref IDCs.
20766 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020767 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20768 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020769 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020770 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020771 /*
20772 * Check if the key/unique IDC table needs to be bubbled.
20773 */
20774 aidc = vctxt->aidcs;
20775 do {
20776 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020777 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020778 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020779 bind = bind->next;
20780 goto start_binding;
20781 }
20782 break;
20783 }
20784 aidc = aidc->next;
20785 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020786
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020787 if (parTable != NULL)
20788 parBind = *parTable;
20789 while (parBind != NULL) {
20790 /*
20791 * Search a matching parent binding for the
20792 * IDC definition.
20793 */
20794 if (parBind->definition == bind->definition) {
20795
20796 /*
20797 * Compare every node-table entry of the child node,
20798 * i.e. the key-sequence within, ...
20799 */
20800 oldNum = parBind->nbNodes; /* Skip newly added items. */
20801 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020802 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020803
20804 for (i = 0; i < bind->nbNodes; i++) {
20805 node = bind->nodeTable[i];
20806 if (node == NULL)
20807 continue;
20808 /*
20809 * ...with every key-sequence of the parent node, already
20810 * evaluated to be a duplicate key-sequence.
20811 */
20812 if (parBind->nbDupls != 0) {
20813 j = bind->nbNodes + newDupls;
20814 while (j < duplTop) {
20815 parNode = parBind->nodeTable[j];
20816 for (k = 0; k < bind->definition->nbFields; k++) {
20817 key = node->keys[k];
20818 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020819 ret = xmlSchemaAreValuesEqual(key->val,
20820 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020821 if (ret == -1) {
20822 /* TODO: Internal error */
20823 return(-1);
20824 } else if (ret == 0)
20825 break;
20826
20827 }
20828 if (ret == 1)
20829 /* Duplicate found. */
20830 break;
20831 j++;
20832 }
20833 if (j != duplTop) {
20834 /* Duplicate found. */
20835 continue;
20836 }
20837 }
20838 /*
20839 * ... and with every key-sequence of the parent node.
20840 */
20841 j = 0;
20842 while (j < oldNum) {
20843 parNode = parBind->nodeTable[j];
20844 /*
20845 * Compare key by key.
20846 */
20847 for (k = 0; k < parBind->definition->nbFields; k++) {
20848 key = node->keys[k];
20849 parKey = parNode->keys[k];
20850
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020851 ret = xmlSchemaAreValuesEqual(key->val,
20852 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020853 if (ret == -1) {
20854 /* TODO: Internal error */
20855 } else if (ret == 0)
20856 break;
20857
20858 }
20859 if (ret == 1)
20860 /*
20861 * The key-sequences are equal.
20862 */
20863 break;
20864 j++;
20865 }
20866 if (j != oldNum) {
20867 /*
20868 * Handle duplicates.
20869 */
20870 newDupls++;
20871 oldNum--;
20872 parBind->nbNodes--;
20873 /*
20874 * Move last old item to pos of duplicate.
20875 */
20876 parBind->nodeTable[j] =
20877 parBind->nodeTable[oldNum];
20878
20879 if (parBind->nbNodes != oldNum) {
20880 /*
20881 * If new items exist, move last new item to
20882 * last of old items.
20883 */
20884 parBind->nodeTable[oldNum] =
20885 parBind->nodeTable[parBind->nbNodes];
20886 }
20887 /*
20888 * Move duplicate to last pos of new/old items.
20889 */
20890 parBind->nodeTable[parBind->nbNodes] = parNode;
20891
20892 } else {
20893 /*
20894 * Add the node-table entry (node and key-sequence) of
20895 * the child node to the node table of the parent node.
20896 */
20897 if (parBind->nodeTable == NULL) {
20898 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020899 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020900 if (parBind->nodeTable == NULL) {
20901 xmlSchemaVErrMemory(NULL,
20902 "allocating IDC list of node-table items", NULL);
20903 return(-1);
20904 }
20905 parBind->sizeNodes = 1;
20906 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020907 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020908 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
20909 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
20910 sizeof(xmlSchemaPSVIIDCNodePtr));
20911 if (parBind->nodeTable == NULL) {
20912 xmlSchemaVErrMemory(NULL,
20913 "re-allocating IDC list of node-table items", NULL);
20914 return(-1);
20915 }
20916 }
20917
20918 /*
20919 * Move first old duplicate to last position
20920 * of old duplicates +1.
20921 */
20922 if (parBind->nbDupls != 0) {
20923 parBind->nodeTable[duplTop] =
20924 parBind->nodeTable[parBind->nbNodes + newDupls];
20925 }
20926 /*
20927 * Move first new duplicate to last position of
20928 * new duplicates +1.
20929 */
20930 if (newDupls != 0) {
20931 parBind->nodeTable[parBind->nbNodes + newDupls] =
20932 parBind->nodeTable[parBind->nbNodes];
20933 }
20934 /*
20935 * Append the new node-table entry to the 'new node-table
20936 * entries' section.
20937 */
20938 parBind->nodeTable[parBind->nbNodes] = node;
20939 parBind->nbNodes++;
20940 duplTop++;
20941 }
20942 }
20943 parBind->nbDupls += newDupls;
20944 break;
20945 }
20946 if (parBind->next == NULL)
20947 lastParBind = parBind;
20948 parBind = parBind->next;
20949 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020950 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020951 /*
20952 * No binding for the IDC was found: create a new one and
20953 * copy all node-tables.
20954 */
20955 parBind = xmlSchemaIDCNewBinding(bind->definition);
20956 if (parBind == NULL)
20957 return(-1);
20958
20959 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
20960 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
20961 if (parBind->nodeTable == NULL) {
20962 xmlSchemaVErrMemory(NULL,
20963 "allocating an array of IDC node-table items", NULL);
20964 xmlSchemaIDCFreeBinding(parBind);
20965 return(-1);
20966 }
20967 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020968 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020969 memcpy(parBind->nodeTable, bind->nodeTable,
20970 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020971 if (*parTable == NULL)
20972 *parTable = parBind;
20973 else
20974 lastParBind->next = parBind;
20975 }
20976 bind = bind->next;
20977 }
20978 return (0);
20979}
20980
20981/**
20982 * xmlSchemaCheckCVCIDCKeyRef:
20983 * @vctxt: the WXS validation context
20984 * @elemDecl: the element declaration
20985 *
20986 * Check the cvc-idc-keyref constraints.
20987 */
20988static int
20989xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
20990{
20991 xmlSchemaPSVIIDCBindingPtr refbind, bind;
20992
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020993 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020994 /*
20995 * Find a keyref.
20996 */
20997 while (refbind != NULL) {
20998 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20999 int i, j, k, res;
21000 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
21001 xmlSchemaPSVIIDCKeyPtr refKey, key;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021002 xmlSchemaPSVIIDCNodePtr refNode = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021003
21004 /*
21005 * Find the referred key/unique.
21006 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021007 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021008 do {
21009 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
21010 bind->definition)
21011 break;
21012 bind = bind->next;
21013 } while (bind != NULL);
21014
21015 /*
21016 * Search for a matching key-sequences.
21017 */
21018 for (i = 0; i < refbind->nbNodes; i++) {
21019 res = 0;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021020 refNode = refbind->nodeTable[i];
21021 if (bind != NULL) {
21022 refKeys = refNode->keys;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021023 for (j = 0; j < bind->nbNodes; j++) {
21024 keys = bind->nodeTable[j]->keys;
21025 for (k = 0; k < bind->definition->nbFields; k++) {
21026 refKey = refKeys[k];
21027 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021028 res = xmlSchemaAreValuesEqual(key->val,
21029 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021030 if (res == 0)
21031 break;
21032 else if (res == -1) {
21033 return (-1);
21034 }
21035 }
21036 if (res == 1) {
21037 /*
21038 * Match found.
21039 */
21040 break;
21041 }
21042 }
21043 }
21044 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021045 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021046 xmlSchemaKeyrefErr(vctxt,
21047 XML_SCHEMAV_CVC_IDC, refNode,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021048 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021049 "No match found for key-sequence %s of key "
21050 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000021051 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021052 refbind->nodeTable[i]->keys,
21053 refbind->definition->nbFields),
21054 xmlSchemaFormatQName(&strB,
21055 refbind->definition->targetNamespace,
21056 refbind->definition->name));
21057 FREE_AND_NULL(str);
21058 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021059 }
21060 }
21061 }
21062 refbind = refbind->next;
21063 }
21064 return (0);
21065}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021066
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021067/************************************************************************
21068 * *
21069 * XML Reader validation code *
21070 * *
21071 ************************************************************************/
21072
21073static xmlSchemaAttrInfoPtr
21074xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021075{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021076 xmlSchemaAttrInfoPtr iattr;
21077 /*
21078 * Grow/create list of attribute infos.
21079 */
21080 if (vctxt->attrInfos == NULL) {
21081 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
21082 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
21083 vctxt->sizeAttrInfos = 1;
21084 if (vctxt->attrInfos == NULL) {
21085 xmlSchemaVErrMemory(vctxt,
21086 "allocating attribute info list", NULL);
21087 return (NULL);
21088 }
21089 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
21090 vctxt->sizeAttrInfos++;
21091 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
21092 xmlRealloc(vctxt->attrInfos,
21093 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
21094 if (vctxt->attrInfos == NULL) {
21095 xmlSchemaVErrMemory(vctxt,
21096 "re-allocating attribute info list", NULL);
21097 return (NULL);
21098 }
21099 } else {
21100 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
21101 if (iattr->localName != NULL) {
21102 VERROR_INT("xmlSchemaGetFreshAttrInfo",
21103 "attr info not cleared");
21104 return (NULL);
21105 }
21106 iattr->nodeType = XML_ATTRIBUTE_NODE;
21107 return (iattr);
21108 }
21109 /*
21110 * Create an attribute info.
21111 */
21112 iattr = (xmlSchemaAttrInfoPtr)
21113 xmlMalloc(sizeof(xmlSchemaAttrInfo));
21114 if (iattr == NULL) {
21115 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
21116 return (NULL);
21117 }
21118 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
21119 iattr->nodeType = XML_ATTRIBUTE_NODE;
21120 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
21121
21122 return (iattr);
21123}
21124
21125static int
21126xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
21127 xmlNodePtr attrNode,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021128 int nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021129 const xmlChar *localName,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021130 const xmlChar *nsName,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021131 int ownedNames,
21132 xmlChar *value,
21133 int ownedValue)
21134{
21135 xmlSchemaAttrInfoPtr attr;
21136
21137 attr = xmlSchemaGetFreshAttrInfo(vctxt);
21138 if (attr == NULL) {
21139 VERROR_INT("xmlSchemaPushAttribute",
21140 "calling xmlSchemaGetFreshAttrInfo()");
21141 return (-1);
21142 }
21143 attr->node = attrNode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000021144 attr->nodeLine = nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021145 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
21146 attr->localName = localName;
21147 attr->nsName = nsName;
21148 if (ownedNames)
21149 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
21150 /*
21151 * Evaluate if it's an XSI attribute.
21152 */
21153 if (nsName != NULL) {
21154 if (xmlStrEqual(localName, BAD_CAST "nil")) {
21155 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
21156 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
21157 }
21158 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
21159 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
21160 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
21161 }
21162 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
21163 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
21164 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
21165 }
21166 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
21167 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
21168 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
21169 }
21170 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
21171 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
21172 }
21173 }
21174 attr->value = value;
21175 if (ownedValue)
21176 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
21177 if (attr->metaType != 0)
21178 attr->state = XML_SCHEMAS_ATTR_META;
21179 return (0);
21180}
21181
21182static void
21183xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
21184{
21185 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21186 FREE_AND_NULL(ielem->localName);
21187 FREE_AND_NULL(ielem->nsName);
21188 } else {
21189 ielem->localName = NULL;
21190 ielem->nsName = NULL;
21191 }
21192 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21193 FREE_AND_NULL(ielem->value);
21194 } else {
21195 ielem->value = NULL;
21196 }
21197 if (ielem->val != NULL) {
21198 xmlSchemaFreeValue(ielem->val);
21199 ielem->val = NULL;
21200 }
21201 if (ielem->idcMatchers != NULL) {
21202 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
21203 ielem->idcMatchers = NULL;
21204 }
21205 if (ielem->idcTable != NULL) {
21206 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
21207 ielem->idcTable = NULL;
21208 }
21209 if (ielem->regexCtxt != NULL) {
21210 xmlRegFreeExecCtxt(ielem->regexCtxt);
21211 ielem->regexCtxt = NULL;
21212 }
21213 if (ielem->nsBindings != NULL) {
21214 xmlFree((xmlChar **)ielem->nsBindings);
21215 ielem->nsBindings = NULL;
21216 ielem->nbNsBindings = 0;
21217 ielem->sizeNsBindings = 0;
21218 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021219}
21220
21221/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021222 * xmlSchemaGetFreshElemInfo:
21223 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021224 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021225 * Creates/reuses and initializes the element info item for
21226 * the currect tree depth.
21227 *
21228 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021229 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021230static xmlSchemaNodeInfoPtr
21231xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021232{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021233 xmlSchemaNodeInfoPtr info = NULL;
21234
21235 if (vctxt->depth > vctxt->sizeElemInfos) {
21236 VERROR_INT("xmlSchemaGetFreshElemInfo",
21237 "inconsistent depth encountered");
21238 return (NULL);
21239 }
21240 if (vctxt->elemInfos == NULL) {
21241 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
21242 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
21243 if (vctxt->elemInfos == NULL) {
21244 xmlSchemaVErrMemory(vctxt,
21245 "allocating the element info array", NULL);
21246 return (NULL);
21247 }
21248 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
21249 vctxt->sizeElemInfos = 10;
21250 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
21251 int i = vctxt->sizeElemInfos;
21252
21253 vctxt->sizeElemInfos *= 2;
21254 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
21255 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
21256 sizeof(xmlSchemaNodeInfoPtr));
21257 if (vctxt->elemInfos == NULL) {
21258 xmlSchemaVErrMemory(vctxt,
21259 "re-allocating the element info array", NULL);
21260 return (NULL);
21261 }
21262 /*
21263 * We need the new memory to be NULLed.
21264 * TODO: Use memset instead?
21265 */
21266 for (; i < vctxt->sizeElemInfos; i++)
21267 vctxt->elemInfos[i] = NULL;
21268 } else
21269 info = vctxt->elemInfos[vctxt->depth];
21270
21271 if (info == NULL) {
21272 info = (xmlSchemaNodeInfoPtr)
21273 xmlMalloc(sizeof(xmlSchemaNodeInfo));
21274 if (info == NULL) {
21275 xmlSchemaVErrMemory(vctxt,
21276 "allocating an element info", NULL);
21277 return (NULL);
21278 }
21279 vctxt->elemInfos[vctxt->depth] = info;
21280 } else {
21281 if (info->localName != NULL) {
21282 VERROR_INT("xmlSchemaGetFreshElemInfo",
21283 "elem info has not been cleared");
21284 return (NULL);
21285 }
21286 }
21287 memset(info, 0, sizeof(xmlSchemaNodeInfo));
21288 info->nodeType = XML_ELEMENT_NODE;
21289 info->depth = vctxt->depth;
21290
21291 return (info);
21292}
21293
21294#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
21295#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
21296#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
21297
21298static int
21299xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
21300 xmlNodePtr node,
21301 xmlSchemaTypePtr type,
21302 xmlSchemaValType valType,
21303 const xmlChar * value,
21304 xmlSchemaValPtr val,
21305 unsigned long length,
21306 int fireErrors)
21307{
21308 int ret, error = 0;
21309
21310 xmlSchemaTypePtr tmpType;
21311 xmlSchemaFacetLinkPtr facetLink;
21312 xmlSchemaFacetPtr facet;
21313 unsigned long len = 0;
21314 xmlSchemaWhitespaceValueType ws;
21315
21316 /*
21317 * In Libxml2, derived built-in types have currently no explicit facets.
21318 */
21319 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021320 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021321
21322 /*
21323 * NOTE: Do not jump away, if the facetSet of the given type is
21324 * empty: until now, "pattern" and "enumeration" facets of the
21325 * *base types* need to be checked as well.
21326 */
21327 if (type->facetSet == NULL)
21328 goto pattern_and_enum;
21329
21330 if (! VARIETY_ATOMIC(type)) {
21331 if (VARIETY_LIST(type))
21332 goto variety_list;
21333 else
21334 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021335 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021336 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021337 * Whitespace handling is only of importance for string-based
21338 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021339 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021340 tmpType = xmlSchemaGetPrimitiveType(type);
21341 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
21342 IS_ANY_SIMPLE_TYPE(tmpType)) {
21343 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
21344 } else
21345 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
21346 /*
21347 * If the value was not computed (for string or
21348 * anySimpleType based types), then use the provided
21349 * type.
21350 */
21351 if (val == NULL)
21352 valType = valType;
21353 else
21354 valType = xmlSchemaGetValType(val);
21355
21356 ret = 0;
21357 for (facetLink = type->facetSet; facetLink != NULL;
21358 facetLink = facetLink->next) {
21359 /*
21360 * Skip the pattern "whiteSpace": it is used to
21361 * format the character content beforehand.
21362 */
21363 switch (facetLink->facet->type) {
21364 case XML_SCHEMA_FACET_WHITESPACE:
21365 case XML_SCHEMA_FACET_PATTERN:
21366 case XML_SCHEMA_FACET_ENUMERATION:
21367 continue;
21368 case XML_SCHEMA_FACET_LENGTH:
21369 case XML_SCHEMA_FACET_MINLENGTH:
21370 case XML_SCHEMA_FACET_MAXLENGTH:
21371 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
21372 valType, value, val, &len, ws);
21373 break;
21374 default:
21375 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
21376 valType, value, val, ws);
21377 break;
21378 }
21379 if (ret < 0) {
21380 AERROR_INT("xmlSchemaValidateFacets",
21381 "validating against a atomic type facet");
21382 return (-1);
21383 } else if (ret > 0) {
21384 if (fireErrors)
21385 xmlSchemaFacetErr(actxt, ret, node,
21386 value, len, type, facetLink->facet, NULL, NULL, NULL);
21387 else
21388 return (ret);
21389 if (error == 0)
21390 error = ret;
21391 }
21392 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021393 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021394
21395variety_list:
21396 if (! VARIETY_LIST(type))
21397 goto pattern_and_enum;
21398 /*
21399 * "length", "minLength" and "maxLength" of list types.
21400 */
21401 ret = 0;
21402 for (facetLink = type->facetSet; facetLink != NULL;
21403 facetLink = facetLink->next) {
21404
21405 switch (facetLink->facet->type) {
21406 case XML_SCHEMA_FACET_LENGTH:
21407 case XML_SCHEMA_FACET_MINLENGTH:
21408 case XML_SCHEMA_FACET_MAXLENGTH:
21409 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
21410 value, length, NULL);
21411 break;
21412 default:
21413 continue;
21414 }
21415 if (ret < 0) {
21416 AERROR_INT("xmlSchemaValidateFacets",
21417 "validating against a list type facet");
21418 return (-1);
21419 } else if (ret > 0) {
21420 if (fireErrors)
21421 xmlSchemaFacetErr(actxt, ret, node,
21422 value, length, type, facetLink->facet, NULL, NULL, NULL);
21423 else
21424 return (ret);
21425 if (error == 0)
21426 error = ret;
21427 }
21428 ret = 0;
21429 }
21430
21431pattern_and_enum:
21432 if (error >= 0) {
21433 int found = 0;
21434 /*
21435 * Process enumerations. Facet values are in the value space
21436 * of the defining type's base type. This seems to be a bug in the
21437 * XML Schema 1.0 spec. Use the whitespace type of the base type.
21438 * Only the first set of enumerations in the ancestor-or-self axis
21439 * is used for validation.
21440 */
21441 ret = 0;
21442 tmpType = type;
21443 do {
21444 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
21445 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
21446 continue;
21447 found = 1;
21448 ret = xmlSchemaAreValuesEqual(facet->val, val);
21449 if (ret == 1)
21450 break;
21451 else if (ret < 0) {
21452 AERROR_INT("xmlSchemaValidateFacets",
21453 "validating against an enumeration facet");
21454 return (-1);
21455 }
21456 }
21457 if (ret != 0)
21458 break;
21459 tmpType = tmpType->baseType;
21460 } while ((tmpType != NULL) &&
21461 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
21462 if (found && (ret == 0)) {
21463 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
21464 if (fireErrors) {
21465 xmlSchemaFacetErr(actxt, ret, node,
21466 value, 0, type, NULL, NULL, NULL, NULL);
21467 } else
21468 return (ret);
21469 if (error == 0)
21470 error = ret;
21471 }
21472 }
21473
21474 if (error >= 0) {
21475 int found;
21476 /*
21477 * Process patters. Pattern facets are ORed at type level
21478 * and ANDed if derived. Walk the base type axis.
21479 */
21480 tmpType = type;
21481 facet = NULL;
21482 do {
21483 found = 0;
21484 for (facetLink = tmpType->facetSet; facetLink != NULL;
21485 facetLink = facetLink->next) {
21486 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
21487 continue;
21488 found = 1;
21489 /*
21490 * NOTE that for patterns, @value needs to be the
21491 * normalized vaule.
21492 */
21493 ret = xmlRegexpExec(facetLink->facet->regexp, value);
21494 if (ret == 1)
21495 break;
21496 else if (ret < 0) {
21497 AERROR_INT("xmlSchemaValidateFacets",
21498 "validating against a pattern facet");
21499 return (-1);
21500 } else {
21501 /*
21502 * Save the last non-validating facet.
21503 */
21504 facet = facetLink->facet;
21505 }
21506 }
21507 if (found && (ret != 1)) {
21508 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
21509 if (fireErrors) {
21510 xmlSchemaFacetErr(actxt, ret, node,
21511 value, 0, type, facet, NULL, NULL, NULL);
21512 } else
21513 return (ret);
21514 if (error == 0)
21515 error = ret;
21516 break;
21517 }
21518 tmpType = tmpType->baseType;
21519 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
21520 }
21521
21522 return (error);
21523}
21524
21525static xmlChar *
21526xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
21527 const xmlChar *value)
21528{
21529 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
21530 case XML_SCHEMA_WHITESPACE_COLLAPSE:
21531 return (xmlSchemaCollapseString(value));
21532 case XML_SCHEMA_WHITESPACE_REPLACE:
21533 return (xmlSchemaWhiteSpaceReplace(value));
21534 default:
21535 return (NULL);
21536 }
21537}
21538
21539static int
21540xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
21541 const xmlChar *value,
21542 xmlSchemaValPtr *val,
21543 int valNeeded)
21544{
21545 int ret;
21546 const xmlChar *nsName;
21547 xmlChar *local, *prefix = NULL;
21548
21549 ret = xmlValidateQName(value, 1);
21550 if (ret != 0) {
21551 if (ret == -1) {
21552 VERROR_INT("xmlSchemaValidateQName",
21553 "calling xmlValidateQName()");
21554 return (-1);
21555 }
21556 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
21557 }
21558 /*
21559 * NOTE: xmlSplitQName2 will always return a duplicated
21560 * strings.
21561 */
21562 local = xmlSplitQName2(value, &prefix);
21563 if (local == NULL)
21564 local = xmlStrdup(value);
21565 /*
21566 * OPTIMIZE TODO: Use flags for:
21567 * - is there any namespace binding?
21568 * - is there a default namespace?
21569 */
21570 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
21571
21572 if (prefix != NULL) {
21573 xmlFree(prefix);
21574 /*
21575 * A namespace must be found if the prefix is
21576 * NOT NULL.
21577 */
21578 if (nsName == NULL) {
21579 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021580 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021581 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
21582 "The QName value '%s' has no "
21583 "corresponding namespace declaration in "
21584 "scope", value, NULL);
21585 if (local != NULL)
21586 xmlFree(local);
21587 return (ret);
21588 }
21589 }
21590 if (valNeeded && val) {
21591 if (nsName != NULL)
21592 *val = xmlSchemaNewQNameValue(
21593 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
21594 else
21595 *val = xmlSchemaNewQNameValue(NULL,
21596 BAD_CAST local);
21597 } else
21598 xmlFree(local);
21599 return (0);
21600}
21601
21602/*
21603* cvc-simple-type
21604*/
21605static int
21606xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
21607 xmlNodePtr node,
21608 xmlSchemaTypePtr type,
21609 const xmlChar *value,
21610 xmlSchemaValPtr *retVal,
21611 int fireErrors,
21612 int normalize,
21613 int isNormalized)
21614{
21615 int ret = 0, valNeeded = (retVal) ? 1 : 0;
21616 xmlSchemaValPtr val = NULL;
21617 xmlSchemaWhitespaceValueType ws;
21618 xmlChar *normValue = NULL;
21619
21620#define NORMALIZE(atype) \
21621 if ((! isNormalized) && \
21622 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
21623 normValue = xmlSchemaNormalizeValue(atype, value); \
21624 if (normValue != NULL) \
21625 value = normValue; \
21626 isNormalized = 1; \
21627 }
21628
21629 if ((retVal != NULL) && (*retVal != NULL)) {
21630 xmlSchemaFreeValue(*retVal);
21631 *retVal = NULL;
21632 }
21633 /*
21634 * 3.14.4 Simple Type Definition Validation Rules
21635 * Validation Rule: String Valid
21636 */
21637 /*
21638 * 1 It is schema-valid with respect to that definition as defined
21639 * by Datatype Valid in [XML Schemas: Datatypes].
21640 */
21641 /*
21642 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
21643 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
21644 * the string must be a ·declared entity name·.
21645 */
21646 /*
21647 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
21648 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
21649 * then every whitespace-delimited substring of the string must be a ·declared
21650 * entity name·.
21651 */
21652 /*
21653 * 2.3 otherwise no further condition applies.
21654 */
21655 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
21656 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000021657 if (value == NULL)
21658 value = BAD_CAST "";
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021659 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
21660 xmlSchemaTypePtr biType; /* The built-in type. */
21661 /*
21662 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
21663 * a literal in the ·lexical space· of {base type definition}"
21664 */
21665 /*
21666 * Whitespace-normalize.
21667 */
21668 NORMALIZE(type);
21669 if (type->type != XML_SCHEMA_TYPE_BASIC) {
21670 /*
21671 * Get the built-in type.
21672 */
21673 biType = type->baseType;
21674 while ((biType != NULL) &&
21675 (biType->type != XML_SCHEMA_TYPE_BASIC))
21676 biType = biType->baseType;
21677
21678 if (biType == NULL) {
21679 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21680 "could not get the built-in type");
21681 goto internal_error;
21682 }
21683 } else
21684 biType = type;
21685 /*
21686 * NOTATIONs need to be processed here, since they need
21687 * to lookup in the hashtable of NOTATION declarations of the schema.
21688 */
21689 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
21690 switch (biType->builtInType) {
21691 case XML_SCHEMAS_NOTATION:
21692 ret = xmlSchemaValidateNotation(
21693 (xmlSchemaValidCtxtPtr) actxt,
21694 ((xmlSchemaValidCtxtPtr) actxt)->schema,
21695 NULL, value, &val, valNeeded);
21696 break;
21697 case XML_SCHEMAS_QNAME:
21698 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
21699 value, &val, valNeeded);
21700 break;
21701 default:
21702 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
21703 if (valNeeded)
21704 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
21705 value, &val, NULL);
21706 else
21707 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
21708 value, NULL, NULL);
21709 break;
21710 }
21711 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
21712 switch (biType->builtInType) {
21713 case XML_SCHEMAS_NOTATION:
21714 ret = xmlSchemaValidateNotation(NULL,
21715 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
21716 value, &val, valNeeded);
21717 break;
21718 default:
21719 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
21720 if (valNeeded)
21721 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
21722 value, &val, node);
21723 else
21724 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
21725 value, NULL, node);
21726 break;
21727 }
21728 } else {
21729 /*
21730 * Validation via a public API is not implemented yet.
21731 */
21732 TODO
21733 goto internal_error;
21734 }
21735 if (ret != 0) {
21736 if (ret < 0) {
21737 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21738 "validating against a built-in type");
21739 goto internal_error;
21740 }
21741 if (VARIETY_LIST(type))
21742 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
21743 else
21744 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
21745 }
21746 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
21747 /*
21748 * Check facets.
21749 */
21750 ret = xmlSchemaValidateFacets(actxt, node, type,
21751 (xmlSchemaValType) biType->builtInType, value, val,
21752 0, fireErrors);
21753 if (ret != 0) {
21754 if (ret < 0) {
21755 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21756 "validating facets of atomic simple type");
21757 goto internal_error;
21758 }
21759 if (VARIETY_LIST(type))
21760 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
21761 else
21762 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
21763 }
21764 }
21765 if (fireErrors && (ret > 0))
21766 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
21767 } else if (VARIETY_LIST(type)) {
21768
21769 xmlSchemaTypePtr itemType;
21770 const xmlChar *cur, *end;
21771 xmlChar *tmpValue = NULL;
21772 unsigned long len = 0;
21773 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
21774 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
21775 * of white space separated tokens, each of which ·match·es a literal
21776 * in the ·lexical space· of {item type definition}
21777 */
21778 /*
21779 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
21780 * the list type has an enum or pattern facet.
21781 */
21782 NORMALIZE(type);
21783 /*
21784 * VAL TODO: Optimize validation of empty values.
21785 * VAL TODO: We do not have computed values for lists.
21786 */
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000021787 itemType = GET_LIST_ITEM_TYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021788 cur = value;
21789 do {
21790 while (IS_BLANK_CH(*cur))
21791 cur++;
21792 end = cur;
21793 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21794 end++;
21795 if (end == cur)
21796 break;
21797 tmpValue = xmlStrndup(cur, end - cur);
21798 len++;
21799
21800 if (valNeeded)
21801 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
21802 tmpValue, &curVal, fireErrors, 0, 1);
21803 else
21804 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
21805 tmpValue, NULL, fireErrors, 0, 1);
21806 FREE_AND_NULL(tmpValue);
21807 if (curVal != NULL) {
21808 /*
21809 * Add to list of computed values.
21810 */
21811 if (val == NULL)
21812 val = curVal;
21813 else
21814 xmlSchemaValueAppend(prevVal, curVal);
21815 prevVal = curVal;
21816 curVal = NULL;
21817 }
21818 if (ret != 0) {
21819 if (ret < 0) {
21820 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21821 "validating an item of list simple type");
21822 goto internal_error;
21823 }
21824 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
21825 break;
21826 }
21827 cur = end;
21828 } while (*cur != 0);
21829 FREE_AND_NULL(tmpValue);
21830 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
21831 /*
21832 * Apply facets (pattern, enumeration).
21833 */
21834 ret = xmlSchemaValidateFacets(actxt, node, type,
21835 XML_SCHEMAS_UNKNOWN, value, val,
21836 len, fireErrors);
21837 if (ret != 0) {
21838 if (ret < 0) {
21839 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21840 "validating facets of list simple type");
21841 goto internal_error;
21842 }
21843 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
21844 }
21845 }
21846 if (fireErrors && (ret > 0)) {
21847 /*
21848 * Report the normalized value.
21849 */
21850 normalize = 1;
21851 NORMALIZE(type);
21852 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
21853 }
21854 } else if (VARIETY_UNION(type)) {
21855 xmlSchemaTypeLinkPtr memberLink;
21856 /*
21857 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
21858 * not apply directly; however, the normalization behavior of ·union·
21859 * types is controlled by the value of whiteSpace on that one of the
21860 * ·memberTypes· against which the ·union· is successfully validated.
21861 *
21862 * This means that the value is normalized by the first validating
21863 * member type, then the facets of the union type are applied. This
21864 * needs changing of the value!
21865 */
21866
21867 /*
21868 * 1.2.3 if {variety} is ·union· then the string must ·match· a
21869 * literal in the ·lexical space· of at least one member of
21870 * {member type definitions}
21871 */
21872 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
21873 if (memberLink == NULL) {
21874 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21875 "union simple type has no member types");
21876 goto internal_error;
21877 }
21878 /*
21879 * Always normalize union type values, since we currently
21880 * cannot store the whitespace information with the value
21881 * itself; otherwise a later value-comparison would be
21882 * not possible.
21883 */
21884 while (memberLink != NULL) {
21885 if (valNeeded)
21886 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
21887 memberLink->type, value, &val, 0, 1, 0);
21888 else
21889 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
21890 memberLink->type, value, NULL, 0, 1, 0);
21891 if (ret <= 0)
21892 break;
21893 memberLink = memberLink->next;
21894 }
21895 if (ret != 0) {
21896 if (ret < 0) {
21897 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21898 "validating members of union simple type");
21899 goto internal_error;
21900 }
21901 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
21902 }
21903 /*
21904 * Apply facets (pattern, enumeration).
21905 */
21906 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
21907 /*
21908 * The normalization behavior of ·union· types is controlled by
21909 * the value of whiteSpace on that one of the ·memberTypes·
21910 * against which the ·union· is successfully validated.
21911 */
21912 NORMALIZE(memberLink->type);
21913 ret = xmlSchemaValidateFacets(actxt, node, type,
21914 XML_SCHEMAS_UNKNOWN, value, val,
21915 0, fireErrors);
21916 if (ret != 0) {
21917 if (ret < 0) {
21918 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21919 "validating facets of union simple type");
21920 goto internal_error;
21921 }
21922 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
21923 }
21924 }
21925 if (fireErrors && (ret > 0))
21926 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
21927 }
21928
21929 if (normValue != NULL)
21930 xmlFree(normValue);
21931 if (ret == 0) {
21932 if (retVal != NULL)
21933 *retVal = val;
21934 else if (val != NULL)
21935 xmlSchemaFreeValue(val);
21936 } else if (val != NULL)
21937 xmlSchemaFreeValue(val);
21938 return (ret);
21939internal_error:
21940 if (normValue != NULL)
21941 xmlFree(normValue);
21942 if (val != NULL)
21943 xmlSchemaFreeValue(val);
21944 return (-1);
21945}
21946
21947static int
21948xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
21949 const xmlChar *value,
21950 const xmlChar **nsName,
21951 const xmlChar **localName)
21952{
21953 int ret = 0;
21954
21955 if ((nsName == NULL) || (localName == NULL))
21956 return (-1);
21957 *nsName = NULL;
21958 *localName = NULL;
21959
21960 ret = xmlValidateQName(value, 1);
21961 if (ret == -1)
21962 return (-1);
21963 if (ret > 0) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021964 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021965 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
21966 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
21967 return (1);
21968 }
21969 {
21970 xmlChar *local = NULL;
21971 xmlChar *prefix;
21972
21973 /*
21974 * NOTE: xmlSplitQName2 will return a duplicated
21975 * string.
21976 */
21977 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021978 if (local == NULL)
21979 *localName = xmlDictLookup(vctxt->dict, value, -1);
21980 else {
21981 *localName = xmlDictLookup(vctxt->dict, local, -1);
21982 xmlFree(local);
21983 }
21984
21985 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
21986
21987 if (prefix != NULL) {
21988 xmlFree(prefix);
21989 /*
21990 * A namespace must be found if the prefix is NOT NULL.
21991 */
21992 if (*nsName == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000021993 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021994 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
21995 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
21996 "The QName value '%s' has no "
21997 "corresponding namespace declaration in scope",
21998 value, NULL);
21999 return (2);
22000 }
22001 }
22002 }
22003 return (0);
22004}
22005
22006static int
22007xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
22008 xmlSchemaAttrInfoPtr iattr,
22009 xmlSchemaTypePtr *localType,
22010 xmlSchemaElementPtr elemDecl)
22011{
22012 int ret = 0;
22013 /*
22014 * cvc-elt (3.3.4) : (4)
22015 * AND
22016 * Schema-Validity Assessment (Element) (cvc-assess-elt)
22017 * (1.2.1.2.1) - (1.2.1.2.4)
22018 * Handle 'xsi:type'.
22019 */
22020 if (localType == NULL)
22021 return (-1);
22022 *localType = NULL;
22023 if (iattr == NULL)
22024 return (0);
22025 else {
22026 const xmlChar *nsName = NULL, *local = NULL;
22027 /*
22028 * TODO: We should report a *warning* that the type was overriden
22029 * by the instance.
22030 */
22031 ACTIVATE_ATTRIBUTE(iattr);
22032 /*
22033 * (cvc-elt) (3.3.4) : (4.1)
22034 * (cvc-assess-elt) (1.2.1.2.2)
22035 */
22036 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
22037 &nsName, &local);
22038 if (ret != 0) {
22039 if (ret < 0) {
22040 VERROR_INT("xmlSchemaValidateElementByDeclaration",
22041 "calling xmlSchemaQNameExpand() to validate the "
22042 "attribute 'xsi:type'");
22043 goto internal_error;
22044 }
22045 goto exit;
22046 }
22047 /*
22048 * (cvc-elt) (3.3.4) : (4.2)
22049 * (cvc-assess-elt) (1.2.1.2.3)
22050 */
22051 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
22052 if (*localType == NULL) {
22053 xmlChar *str = NULL;
22054
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022055 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022056 XML_SCHEMAV_CVC_ELT_4_2, NULL,
22057 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
22058 "The QName value '%s' of the xsi:type attribute does not "
22059 "resolve to a type definition",
22060 xmlSchemaFormatQName(&str, nsName, local), NULL);
22061 FREE_AND_NULL(str);
22062 ret = vctxt->err;
22063 goto exit;
22064 }
22065 if (elemDecl != NULL) {
22066 int set = 0;
22067
22068 /*
22069 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
22070 * "The ·local type definition· must be validly
22071 * derived from the {type definition} given the union of
22072 * the {disallowed substitutions} and the {type definition}'s
22073 * {prohibited substitutions}, as defined in
22074 * Type Derivation OK (Complex) (§3.4.6)
22075 * (if it is a complex type definition),
22076 * or given {disallowed substitutions} as defined in Type
22077 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
22078 * definition)."
22079 *
22080 * {disallowed substitutions}: the "block" on the element decl.
22081 * {prohibited substitutions}: the "block" on the type def.
22082 */
22083 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
22084 (elemDecl->subtypes->flags &
22085 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
22086 set |= SUBSET_EXTENSION;
22087
22088 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
22089 (elemDecl->subtypes->flags &
22090 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
22091 set |= SUBSET_RESTRICTION;
22092
22093 if (xmlSchemaCheckCOSDerivedOK(*localType,
22094 elemDecl->subtypes, set) != 0) {
22095 xmlChar *str = NULL;
22096
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022097 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022098 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
22099 "The type definition '%s', specified by xsi:type, is "
22100 "blocked or not validly derived from the type definition "
22101 "of the element declaration",
22102 xmlSchemaFormatQName(&str,
22103 (*localType)->targetNamespace,
22104 (*localType)->name),
22105 NULL);
22106 FREE_AND_NULL(str);
22107 ret = vctxt->err;
22108 *localType = NULL;
22109 }
22110 }
22111 }
22112exit:
22113 ACTIVATE_ELEM;
22114 return (ret);
22115internal_error:
22116 ACTIVATE_ELEM;
22117 return (-1);
22118}
22119
22120static int
22121xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
22122{
22123 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
22124 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
22125
22126 /*
22127 * cvc-elt (3.3.4) : 1
22128 */
22129 if (elemDecl == NULL) {
22130 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
22131 "No matching declaration available");
22132 return (vctxt->err);
22133 }
22134 /*
22135 * cvc-elt (3.3.4) : 2
22136 */
22137 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
22138 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
22139 "The element declaration is abstract");
22140 return (vctxt->err);
22141 }
22142 if (actualType == NULL) {
22143 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
22144 "The type definition is absent");
22145 return (XML_SCHEMAV_CVC_TYPE_1);
22146 }
22147 if (vctxt->nbAttrInfos != 0) {
22148 int ret;
22149 xmlSchemaAttrInfoPtr iattr;
22150 /*
22151 * cvc-elt (3.3.4) : 3
22152 * Handle 'xsi:nil'.
22153 */
22154 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22155 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
22156 if (iattr) {
22157 ACTIVATE_ATTRIBUTE(iattr);
22158 /*
22159 * Validate the value.
22160 */
22161 ret = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022162 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022163 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
22164 iattr->value, &(iattr->val), 1, 0, 0);
22165 ACTIVATE_ELEM;
22166 if (ret < 0) {
22167 VERROR_INT("xmlSchemaValidateElemDecl",
22168 "calling xmlSchemaVCheckCVCSimpleType() to "
22169 "validate the attribute 'xsi:nil'");
22170 return (-1);
22171 }
22172 if (ret == 0) {
22173 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
22174 /*
22175 * cvc-elt (3.3.4) : 3.1
22176 */
22177 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
22178 "The element is not 'nillable'");
22179 /* Does not return an error on purpose. */
22180 } else {
22181 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
22182 /*
22183 * cvc-elt (3.3.4) : 3.2.2
22184 */
22185 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
22186 (elemDecl->value != NULL)) {
22187 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
22188 "The element cannot be 'nilled' because "
22189 "there is a fixed value constraint defined "
22190 "for it");
22191 /* Does not return an error on purpose. */
22192 } else
22193 vctxt->inode->flags |=
22194 XML_SCHEMA_ELEM_INFO_NILLED;
22195 }
22196 }
22197 }
22198 }
22199 /*
22200 * cvc-elt (3.3.4) : 4
22201 * Handle 'xsi:type'.
22202 */
22203 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22204 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22205 if (iattr) {
22206 xmlSchemaTypePtr localType = NULL;
22207
22208 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
22209 elemDecl);
22210 if (ret != 0) {
22211 if (ret == -1) {
22212 VERROR_INT("xmlSchemaValidateElemDecl",
22213 "calling xmlSchemaProcessXSIType() to "
22214 "process the attribute 'xsi:type'");
22215 return (-1);
22216 }
22217 /* Does not return an error on purpose. */
22218 }
22219 if (localType != NULL) {
22220 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
22221 actualType = localType;
22222 }
22223 }
22224 }
22225 /*
22226 * IDC: Register identity-constraint XPath matchers.
22227 */
22228 if ((elemDecl->idcs != NULL) &&
22229 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
22230 return (-1);
22231 /*
22232 * No actual type definition.
22233 */
22234 if (actualType == NULL) {
22235 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
22236 "The type definition is absent");
22237 return (XML_SCHEMAV_CVC_TYPE_1);
22238 }
22239 /*
22240 * Remember the actual type definition.
22241 */
22242 vctxt->inode->typeDef = actualType;
22243
22244 return (0);
22245}
22246
22247static int
22248xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
22249{
22250 xmlSchemaAttrInfoPtr iattr;
22251 int ret = 0, i;
22252
22253 /*
22254 * SPEC cvc-type (3.1.1)
22255 * "The attributes of must be empty, excepting those whose namespace
22256 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
22257 * whose local name is one of type, nil, schemaLocation or
22258 * noNamespaceSchemaLocation."
22259 */
22260 if (vctxt->nbAttrInfos == 0)
22261 return (0);
22262 for (i = 0; i < vctxt->nbAttrInfos; i++) {
22263 iattr = vctxt->attrInfos[i];
22264 if (! iattr->metaType) {
22265 ACTIVATE_ATTRIBUTE(iattr)
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022266 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022267 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
22268 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
22269 }
22270 }
22271 ACTIVATE_ELEM
22272 return (ret);
22273}
22274
22275/*
22276* Cleanup currently used attribute infos.
22277*/
22278static void
22279xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
22280{
22281 int i;
22282 xmlSchemaAttrInfoPtr attr;
22283
22284 if (vctxt->nbAttrInfos == 0)
22285 return;
22286 for (i = 0; i < vctxt->nbAttrInfos; i++) {
22287 attr = vctxt->attrInfos[i];
22288 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
22289 if (attr->localName != NULL)
22290 xmlFree((xmlChar *) attr->localName);
22291 if (attr->nsName != NULL)
22292 xmlFree((xmlChar *) attr->nsName);
22293 }
22294 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
22295 if (attr->value != NULL)
22296 xmlFree((xmlChar *) attr->value);
22297 }
22298 if (attr->val != NULL) {
22299 xmlSchemaFreeValue(attr->val);
22300 attr->val = NULL;
22301 }
22302 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
22303 }
22304 vctxt->nbAttrInfos = 0;
22305}
22306
22307/*
22308* 3.4.4 Complex Type Definition Validation Rules
22309* Element Locally Valid (Complex Type) (cvc-complex-type)
22310* 3.2.4 Attribute Declaration Validation Rules
22311* Validation Rule: Attribute Locally Valid (cvc-attribute)
22312* Attribute Locally Valid (Use) (cvc-au)
22313*
22314* Only "assessed" attribute information items will be visible to
22315* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
22316*/
22317static int
22318xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
22319{
22320 xmlSchemaTypePtr type = vctxt->inode->typeDef;
22321 xmlSchemaAttributeLinkPtr attrUseLink;
22322 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
22323 xmlSchemaAttrInfoPtr attr, tmpAttr;
22324 int i, found, nbAttrs;
22325 int xpathRes = 0, res, wildIDs = 0, fixed;
22326
22327 /*
22328 * SPEC (cvc-attribute)
22329 * (1) "The declaration must not be ·absent· (see Missing
22330 * Sub-components (§5.3) for how this can fail to be
22331 * the case)."
22332 * (2) "Its {type definition} must not be absent."
22333 *
22334 * NOTE (1) + (2): This is not handled here, since we currently do not
22335 * allow validation against schemas which have missing sub-components.
22336 *
22337 * SPEC (cvc-complex-type)
22338 * (3) "For each attribute information item in the element information
22339 * item's [attributes] excepting those whose [namespace name] is
22340 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
22341 * [local name] is one of type, nil, schemaLocation or
22342 * noNamespaceSchemaLocation, the appropriate case among the following
22343 * must be true:
22344 *
22345 */
22346 nbAttrs = vctxt->nbAttrInfos;
22347 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
22348 attrUseLink = attrUseLink->next) {
22349
22350 found = 0;
22351 attrUse = attrUseLink->attr;
22352 /*
22353 * VAL TODO: Implement a real "attribute use" component.
22354 */
22355 if (attrUse->refDecl != NULL)
22356 attrDecl = attrUse->refDecl;
22357 else
22358 attrDecl = attrUse;
22359 for (i = 0; i < nbAttrs; i++) {
22360 attr = vctxt->attrInfos[i];
22361 /*
22362 * SPEC (cvc-complex-type) (3)
22363 * Skip meta attributes.
22364 */
22365 if (attr->metaType)
22366 continue;
22367 if (attr->localName[0] != attrDecl->name[0])
22368 continue;
22369 if (!xmlStrEqual(attr->localName, attrDecl->name))
22370 continue;
22371 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
22372 continue;
22373 found = 1;
22374 /*
22375 * SPEC (cvc-complex-type)
22376 * (3.1) "If there is among the {attribute uses} an attribute
22377 * use with an {attribute declaration} whose {name} matches
22378 * the attribute information item's [local name] and whose
22379 * {target namespace} is identical to the attribute information
22380 * item's [namespace name] (where an ·absent· {target namespace}
22381 * is taken to be identical to a [namespace name] with no value),
22382 * then the attribute information must be ·valid· with respect
22383 * to that attribute use as per Attribute Locally Valid (Use)
22384 * (§3.5.4). In this case the {attribute declaration} of that
22385 * attribute use is the ·context-determined declaration· for the
22386 * attribute information item with respect to Schema-Validity
22387 * Assessment (Attribute) (§3.2.4) and
22388 * Assessment Outcome (Attribute) (§3.2.5).
22389 */
22390 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
22391 attr->use = attrUse;
22392 /*
22393 * Context-determined declaration.
22394 */
22395 attr->decl = attrDecl;
22396 attr->typeDef = attrDecl->subtypes;
22397 break;
22398 }
22399
22400 if (found)
22401 continue;
22402
22403 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
22404 /*
22405 * Handle non-existent, required attributes.
22406 *
22407 * SPEC (cvc-complex-type)
22408 * (4) "The {attribute declaration} of each attribute use in
22409 * the {attribute uses} whose {required} is true matches one
22410 * of the attribute information items in the element information
22411 * item's [attributes] as per clause 3.1 above."
22412 */
22413 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
22414 if (tmpAttr == NULL) {
22415 VERROR_INT(
22416 "xmlSchemaVAttributesComplex",
22417 "calling xmlSchemaGetFreshAttrInfo()");
22418 return (-1);
22419 }
22420 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
22421 tmpAttr->use = attrUse;
22422 tmpAttr->decl = attrDecl;
22423 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
22424 ((attrUse->defValue != NULL) ||
22425 (attrDecl->defValue != NULL))) {
22426 /*
22427 * Handle non-existent, optional, default/fixed attributes.
22428 */
22429 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
22430 if (tmpAttr == NULL) {
22431 VERROR_INT(
22432 "xmlSchemaVAttributesComplex",
22433 "calling xmlSchemaGetFreshAttrInfo()");
22434 return (-1);
22435 }
22436 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
22437 tmpAttr->use = attrUse;
22438 tmpAttr->decl = attrDecl;
22439 tmpAttr->typeDef = attrDecl->subtypes;
22440 tmpAttr->localName = attrDecl->name;
22441 tmpAttr->nsName = attrDecl->targetNamespace;
22442 }
22443 }
22444 if (vctxt->nbAttrInfos == 0)
22445 return (0);
22446 /*
22447 * Validate against the wildcard.
22448 */
22449 if (type->attributeWildcard != NULL) {
22450 /*
22451 * SPEC (cvc-complex-type)
22452 * (3.2.1) "There must be an {attribute wildcard}."
22453 */
22454 for (i = 0; i < nbAttrs; i++) {
22455 attr = vctxt->attrInfos[i];
22456 /*
22457 * SPEC (cvc-complex-type) (3)
22458 * Skip meta attributes.
22459 */
22460 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
22461 continue;
22462 /*
22463 * SPEC (cvc-complex-type)
22464 * (3.2.2) "The attribute information item must be ·valid· with
22465 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
22466 *
22467 * SPEC Item Valid (Wildcard) (cvc-wildcard)
22468 * "... its [namespace name] must be ·valid· with respect to
22469 * the wildcard constraint, as defined in Wildcard allows
22470 * Namespace Name (§3.10.4)."
22471 */
22472 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
22473 attr->nsName)) {
22474 /*
22475 * Handle processContents.
22476 *
22477 * SPEC (cvc-wildcard):
22478 * processContents | context-determined declaration:
22479 * "strict" "mustFind"
22480 * "lax" "none"
22481 * "skip" "skip"
22482 */
22483 if (type->attributeWildcard->processContents ==
22484 XML_SCHEMAS_ANY_SKIP) {
22485 /*
22486 * context-determined declaration = "skip"
22487 *
22488 * SPEC PSVI Assessment Outcome (Attribute)
22489 * [validity] = "notKnown"
22490 * [validation attempted] = "none"
22491 */
22492 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
22493 continue;
22494 }
22495 /*
22496 * Find an attribute declaration.
22497 */
22498 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
22499 attr->localName, attr->nsName);
22500 if (attr->decl != NULL) {
22501 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
22502 /*
22503 * SPEC (cvc-complex-type)
22504 * (5) "Let [Definition:] the wild IDs be the set of
22505 * all attribute information item to which clause 3.2
22506 * applied and whose ·validation· resulted in a
22507 * ·context-determined declaration· of mustFind or no
22508 * ·context-determined declaration· at all, and whose
22509 * [local name] and [namespace name] resolve (as
22510 * defined by QName resolution (Instance) (§3.15.4)) to
22511 * an attribute declaration whose {type definition} is
22512 * or is derived from ID. Then all of the following
22513 * must be true:"
22514 */
22515 attr->typeDef = attr->decl->subtypes;
22516 if (xmlSchemaIsDerivedFromBuiltInType(
22517 attr->typeDef, XML_SCHEMAS_ID)) {
22518 /*
22519 * SPEC (5.1) "There must be no more than one
22520 * item in ·wild IDs·."
22521 */
22522 if (wildIDs != 0) {
22523 /* VAL TODO */
22524 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
22525 TODO
22526 continue;
22527 }
22528 wildIDs++;
22529 /*
22530 * SPEC (cvc-complex-type)
22531 * (5.2) "If ·wild IDs· is non-empty, there must not
22532 * be any attribute uses among the {attribute uses}
22533 * whose {attribute declaration}'s {type definition}
22534 * is or is derived from ID."
22535 */
22536 for (attrUseLink = type->attributeUses;
22537 attrUseLink != NULL;
22538 attrUseLink = attrUseLink->next) {
22539 if (xmlSchemaIsDerivedFromBuiltInType(
22540 attrUseLink->attr->subtypes,
22541 XML_SCHEMAS_ID)) {
22542 /* VAL TODO */
22543 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
22544 TODO
22545 }
22546 }
22547 }
22548 } else if (type->attributeWildcard->processContents ==
22549 XML_SCHEMAS_ANY_LAX) {
22550 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
22551 /*
22552 * SPEC PSVI Assessment Outcome (Attribute)
22553 * [validity] = "notKnown"
22554 * [validation attempted] = "none"
22555 */
22556 } else {
22557 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
22558 }
22559 }
22560 }
22561 }
22562
22563
22564 if (vctxt->nbAttrInfos == 0)
22565 return (0);
22566
22567 /*
22568 * Validate values, create default attributes, evaluate IDCs.
22569 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022570 for (i = 0; i < vctxt->nbAttrInfos; i++) {
22571 attr = vctxt->attrInfos[i];
22572 /*
22573 * VAL TODO: Note that we won't try to resolve IDCs to
22574 * "lax" and "skip" validated attributes. Check what to
22575 * do in this case.
22576 */
22577 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
22578 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
22579 continue;
22580 /*
22581 * VAL TODO: What to do if the type definition is missing?
22582 */
22583 if (attr->typeDef == NULL) {
22584 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
22585 continue;
22586 }
22587
22588 ACTIVATE_ATTRIBUTE(attr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000022589 fixed = 0;
22590 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022591
22592 if (vctxt->xpathStates != NULL) {
22593 /*
22594 * Evaluate IDCs.
22595 */
22596 xpathRes = xmlSchemaXPathEvaluate(vctxt,
22597 XML_ATTRIBUTE_NODE);
22598 if (xpathRes == -1) {
22599 VERROR_INT("xmlSchemaVAttributesComplex",
22600 "calling xmlSchemaXPathEvaluate()");
22601 goto internal_error;
22602 }
22603 }
22604
22605 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
22606 /*
22607 * Default/fixed attributes.
22608 */
22609 if (xpathRes) {
22610 if (attr->use->defValue == NULL) {
22611 attr->value = (xmlChar *) attr->use->defValue;
22612 attr->val = attr->use->defVal;
22613 } else {
22614 attr->value = (xmlChar *) attr->decl->defValue;
22615 attr->val = attr->decl->defVal;
22616 }
22617 /*
22618 * IDCs will consume the precomputed default value,
22619 * so we need to clone it.
22620 */
22621 if (attr->val == NULL) {
22622 VERROR_INT("xmlSchemaVAttributesComplex",
22623 "default/fixed value on an attribute use was "
22624 "not precomputed");
22625 goto internal_error;
22626 }
22627 attr->val = xmlSchemaCopyValue(attr->val);
22628 if (attr->val == NULL) {
22629 VERROR_INT("xmlSchemaVAttributesComplex",
22630 "calling xmlSchemaCopyValue()");
22631 goto internal_error;
22632 }
22633 }
22634 /*
22635 * PSVI: Add the default attribute to the current element.
22636 * VAL TODO: Should we use the *normalized* value? This currently
22637 * uses the *initial* value.
22638 */
22639 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22640 (attr->node != NULL) && (attr->node->doc != NULL)) {
22641 xmlChar *normValue;
22642 const xmlChar *value;
22643
22644 value = attr->value;
22645 /*
22646 * Normalize the value.
22647 */
22648 normValue = xmlSchemaNormalizeValue(attr->typeDef,
22649 attr->value);
22650 if (normValue != NULL)
22651 value = BAD_CAST normValue;
22652
22653 if (attr->nsName == NULL) {
22654 if (xmlNewProp(attr->node->parent,
22655 attr->localName, value) == NULL) {
22656 VERROR_INT("xmlSchemaVAttributesComplex",
22657 "callling xmlNewProp()");
22658 if (normValue != NULL)
22659 xmlFree(normValue);
22660 goto internal_error;
22661 }
22662 } else {
22663 xmlNsPtr ns;
22664
22665 ns = xmlSearchNsByHref(attr->node->doc,
22666 attr->node->parent, attr->nsName);
22667 if (ns == NULL) {
22668 xmlChar prefix[12];
22669 int counter = 0;
22670
22671 /*
22672 * Create a namespace declaration on the validation
22673 * root node if no namespace declaration is in scope.
22674 */
22675 do {
22676 snprintf((char *) prefix, 12, "p%d", counter++);
22677 ns = xmlSearchNs(attr->node->doc,
22678 attr->node->parent, BAD_CAST prefix);
22679 if (counter > 1000) {
22680 VERROR_INT(
22681 "xmlSchemaVAttributesComplex",
22682 "could not compute a ns prefix for a "
22683 "default/fixed attribute");
22684 if (normValue != NULL)
22685 xmlFree(normValue);
22686 goto internal_error;
22687 }
22688 } while (ns != NULL);
22689 ns = xmlNewNs(vctxt->validationRoot,
22690 attr->nsName, BAD_CAST prefix);
22691 }
22692 xmlNewNsProp(attr->node->parent, ns,
22693 attr->localName, value);
22694 }
22695 if (normValue != NULL)
22696 xmlFree(normValue);
22697 }
22698 /*
22699 * Go directly to IDC evaluation.
22700 */
22701 goto eval_idcs;
22702 }
22703 /*
22704 * Validate the value.
22705 */
22706 if (vctxt->value != NULL) {
22707 /*
22708 * Free last computed value; just for safety reasons.
22709 */
22710 xmlSchemaFreeValue(vctxt->value);
22711 vctxt->value = NULL;
22712 }
22713 /*
22714 * Note that the attribute *use* can be unavailable, if
22715 * the attribute was a wild attribute.
22716 */
22717 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
22718 ((attr->use != NULL) &&
22719 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
22720 fixed = 1;
22721 else
22722 fixed = 0;
22723 /*
22724 * SPEC (cvc-attribute)
22725 * (3) "The item's ·normalized value· must be locally ·valid·
22726 * with respect to that {type definition} as per
22727 * String Valid (§3.14.4)."
22728 *
22729 * VAL TODO: Do we already have the
22730 * "normalized attribute value" here?
22731 */
22732 if (xpathRes || fixed) {
22733 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22734 /*
22735 * Request a computed value.
22736 */
22737 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022738 ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022739 attr->node, attr->typeDef, attr->value, &(attr->val),
22740 1, 1, 0);
22741 } else {
22742 res = xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022743 ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022744 attr->node, attr->typeDef, attr->value, NULL,
22745 1, 0, 0);
22746 }
22747
22748 if (res != 0) {
22749 if (res == -1) {
22750 VERROR_INT("xmlSchemaVAttributesComplex",
22751 "calling xmlSchemaStreamValidateSimpleTypeValue()");
22752 goto internal_error;
22753 }
22754 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
22755 /*
22756 * SPEC PSVI Assessment Outcome (Attribute)
22757 * [validity] = "invalid"
22758 */
22759 goto eval_idcs;
22760 }
22761
22762 if (fixed) {
22763 int ws;
22764 /*
22765 * SPEC Attribute Locally Valid (Use) (cvc-au)
22766 * "For an attribute information item to be·valid·
22767 * with respect to an attribute use its *normalized*
22768 * value· must match the *canonical* lexical
22769 * representation of the attribute use's {value
22770 * constraint}value, if it is present and fixed."
22771 *
22772 * VAL TODO: The requirement for the *canonical* value
22773 * will be removed in XML Schema 1.1.
22774 */
22775 /*
22776 * SPEC Attribute Locally Valid (cvc-attribute)
22777 * (4) "The item's *actual* value· must match the *value* of
22778 * the {value constraint}, if it is present and fixed."
22779 */
22780 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
22781 if (attr->val == NULL) {
22782 /* VAL TODO: A value was not precomputed. */
22783 TODO
22784 goto eval_idcs;
22785 }
22786 if ((attr->use != NULL) &&
22787 (attr->use->defValue != NULL)) {
22788 if (attr->use->defVal == NULL) {
22789 /* VAL TODO: A default value was not precomputed. */
22790 TODO
22791 goto eval_idcs;
22792 }
22793 attr->vcValue = attr->use->defValue;
22794 /*
22795 if (xmlSchemaCompareValuesWhtsp(attr->val,
22796 (xmlSchemaWhitespaceValueType) ws,
22797 attr->use->defVal,
22798 (xmlSchemaWhitespaceValueType) ws) != 0) {
22799 */
22800 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
22801 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
22802 } else {
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000022803 if (attr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022804 /* VAL TODO: A default value was not precomputed. */
22805 TODO
22806 goto eval_idcs;
22807 }
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000022808 attr->vcValue = attr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022809 /*
22810 if (xmlSchemaCompareValuesWhtsp(attr->val,
22811 (xmlSchemaWhitespaceValueType) ws,
22812 attrDecl->defVal,
22813 (xmlSchemaWhitespaceValueType) ws) != 0) {
22814 */
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000022815 if (! xmlSchemaAreValuesEqual(attr->val, attr->decl->defVal))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022816 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
22817 }
22818 /*
22819 * [validity] = "valid"
22820 */
22821 }
22822eval_idcs:
22823 /*
22824 * Evaluate IDCs.
22825 */
22826 if (xpathRes) {
22827 if (xmlSchemaXPathProcessHistory(vctxt,
22828 vctxt->depth +1) == -1) {
22829 VERROR_INT("xmlSchemaVAttributesComplex",
22830 "calling xmlSchemaXPathEvaluate()");
22831 goto internal_error;
22832 }
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000022833 } else if (vctxt->xpathStates != NULL)
22834 xmlSchemaXPathPop(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022835 }
22836
22837 /*
22838 * Report errors.
22839 */
22840 for (i = 0; i < vctxt->nbAttrInfos; i++) {
22841 attr = vctxt->attrInfos[i];
22842 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
22843 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
22844 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
22845 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
22846 continue;
22847 ACTIVATE_ATTRIBUTE(attr);
22848 switch (attr->state) {
22849 case XML_SCHEMAS_ATTR_ERR_MISSING: {
22850 xmlChar *str = NULL;
22851 ACTIVATE_ELEM;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022852 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022853 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
22854 "The attribute '%s' is required but missing",
22855 xmlSchemaFormatQName(&str,
22856 attr->decl->targetNamespace,
22857 attr->decl->name),
22858 NULL);
22859 FREE_AND_NULL(str)
22860 break;
22861 }
22862 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
22863 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
22864 "The type definition is absent");
22865 break;
22866 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022867 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022868 XML_SCHEMAV_CVC_AU, NULL, NULL,
22869 "The value '%s' does not match the fixed "
22870 "value constraint '%s'",
22871 attr->value, attr->vcValue);
22872 break;
22873 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
22874 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
22875 "No matching global attribute declaration available, but "
22876 "demanded by the strict wildcard");
22877 break;
22878 case XML_SCHEMAS_ATTR_UNKNOWN:
22879 if (attr->metaType)
22880 break;
22881 /*
22882 * MAYBE VAL TODO: One might report different error messages
22883 * for the following errors.
22884 */
22885 if (type->attributeWildcard == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022886 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022887 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
22888 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022889 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022890 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
22891 }
22892 break;
22893 default:
22894 break;
22895 }
22896 }
22897
22898 ACTIVATE_ELEM;
22899 return (0);
22900internal_error:
22901 ACTIVATE_ELEM;
22902 return (-1);
22903}
22904
22905static int
22906xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
22907 int *skip)
22908{
22909 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
22910 /*
22911 * The namespace of the element was already identified to be
22912 * matching the wildcard.
22913 */
22914 if ((skip == NULL) || (wild == NULL) ||
22915 (wild->type != XML_SCHEMA_TYPE_ANY)) {
22916 VERROR_INT("xmlSchemaValidateElemWildcard",
22917 "bad arguments");
22918 return (-1);
22919 }
22920 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022921 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
22922 /*
22923 * URGENT VAL TODO: Either we need to position the stream to the
22924 * next sibling, or walk the whole subtree.
22925 */
22926 *skip = 1;
22927 return (0);
22928 }
22929 {
22930 xmlSchemaElementPtr decl = NULL;
22931
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000022932 decl = xmlSchemaGetElem(vctxt->schema,
22933 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022934 if (decl != NULL) {
22935 vctxt->inode->decl = decl;
22936 return (0);
22937 }
22938 }
22939 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
22940 /* VAL TODO: Change to proper error code. */
22941 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
22942 "No matching global element declaration available, but "
22943 "demanded by the strict wildcard");
22944 return (vctxt->err);
22945 }
22946 if (vctxt->nbAttrInfos != 0) {
22947 xmlSchemaAttrInfoPtr iattr;
22948 /*
22949 * SPEC Validation Rule: Schema-Validity Assessment (Element)
22950 * (1.2.1.2.1) - (1.2.1.2.3 )
22951 *
22952 * Use the xsi:type attribute for the type definition.
22953 */
22954 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22955 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22956 if (iattr != NULL) {
22957 if (xmlSchemaProcessXSIType(vctxt, iattr,
22958 &(vctxt->inode->typeDef), NULL) == -1) {
22959 VERROR_INT("xmlSchemaValidateElemWildcard",
22960 "calling xmlSchemaProcessXSIType() to "
22961 "process the attribute 'xsi:nil'");
22962 return (-1);
22963 }
22964 /*
22965 * Don't return an error on purpose.
22966 */
22967 return (0);
22968 }
22969 }
22970 /*
22971 * SPEC Validation Rule: Schema-Validity Assessment (Element)
22972 *
22973 * Fallback to "anyType".
22974 */
22975 vctxt->inode->typeDef =
22976 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
22977 return (0);
22978}
22979
22980/*
22981* xmlSchemaCheckCOSValidDefault:
22982*
22983* This will be called if: not nilled, no content and a default/fixed
22984* value is provided.
22985*/
22986
22987static int
22988xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
22989 const xmlChar *value,
22990 xmlSchemaValPtr *val)
22991{
22992 int ret = 0;
22993 xmlSchemaNodeInfoPtr inode = vctxt->inode;
22994
22995 /*
22996 * cos-valid-default:
22997 * Schema Component Constraint: Element Default Valid (Immediate)
22998 * For a string to be a valid default with respect to a type
22999 * definition the appropriate case among the following must be true:
23000 */
23001 if IS_COMPLEX_TYPE(inode->typeDef) {
23002 /*
23003 * Complex type.
23004 *
23005 * SPEC (2.1) "its {content type} must be a simple type definition
23006 * or mixed."
23007 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
23008 * type}'s particle must be ·emptiable· as defined by
23009 * Particle Emptiable (§3.9.6)."
23010 */
23011 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
23012 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
23013 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
23014 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
23015 /* NOTE that this covers (2.2.2) as well. */
23016 VERROR(ret, NULL,
23017 "For a string to be a valid default, the type definition "
23018 "must be a simple type or a complex type with simple content "
23019 "or mixed content and a particle emptiable");
23020 return(ret);
23021 }
23022 }
23023 /*
23024 * 1 If the type definition is a simple type definition, then the string
23025 * must be ·valid· with respect to that definition as defined by String
23026 * Valid (§3.14.4).
23027 *
23028 * AND
23029 *
23030 * 2.2.1 If the {content type} is a simple type definition, then the
23031 * string must be ·valid· with respect to that simple type definition
23032 * as defined by String Valid (§3.14.4).
23033 */
23034 if (IS_SIMPLE_TYPE(inode->typeDef)) {
23035
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023036 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023037 NULL, inode->typeDef, value, val, 1, 1, 0);
23038
23039 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
23040
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023041 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023042 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
23043 }
23044 if (ret < 0) {
23045 VERROR_INT("xmlSchemaCheckCOSValidDefault",
23046 "calling xmlSchemaVCheckCVCSimpleType()");
23047 }
23048 return (ret);
23049}
23050
23051static void
23052xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
23053 const xmlChar * name ATTRIBUTE_UNUSED,
23054 xmlSchemaElementPtr item,
23055 xmlSchemaNodeInfoPtr inode)
23056{
23057 inode->decl = item;
23058#ifdef DEBUG_CONTENT
23059 {
23060 xmlChar *str = NULL;
23061
23062 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
23063 xmlGenericError(xmlGenericErrorContext,
23064 "AUTOMATON callback for '%s' [declaration]\n",
23065 xmlSchemaFormatQName(&str,
23066 inode->localName, inode->nsName));
23067 } else {
23068 xmlGenericError(xmlGenericErrorContext,
23069 "AUTOMATON callback for '%s' [wildcard]\n",
23070 xmlSchemaFormatQName(&str,
23071 inode->localName, inode->nsName));
23072
23073 }
23074 FREE_AND_NULL(str)
23075 }
23076#endif
23077}
23078
23079static int
23080xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023081{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023082 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
23083 if (vctxt->inode == NULL) {
23084 VERROR_INT("xmlSchemaValidatorPushElem",
23085 "calling xmlSchemaGetFreshElemInfo()");
23086 return (-1);
23087 }
23088 vctxt->nbAttrInfos = 0;
23089 return (0);
23090}
23091
23092static int
23093xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
23094 xmlSchemaNodeInfoPtr inode,
23095 xmlSchemaTypePtr type,
23096 const xmlChar *value)
23097{
23098 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
23099 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023100 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023101 type, value, &(inode->val), 1, 1, 0));
23102 else
23103 return (xmlSchemaVCheckCVCSimpleType(
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023104 ACTXT_CAST vctxt, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023105 type, value, NULL, 1, 0, 0));
23106}
23107
23108
23109
23110/*
23111* Process END of element.
23112*/
23113static int
23114xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
23115{
23116 int ret = 0;
23117 xmlSchemaNodeInfoPtr inode = vctxt->inode;
23118
23119 if (vctxt->nbAttrInfos != 0)
23120 xmlSchemaClearAttrInfos(vctxt);
23121 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
23122 /*
23123 * This element was not expected;
23124 * we will not validate child elements of broken parents.
23125 * Skip validation of all content of the parent.
23126 */
23127 vctxt->skipDepth = vctxt->depth -1;
23128 goto end_elem;
23129 }
23130 if ((inode->typeDef == NULL) ||
23131 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
23132 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023133 * 1. the type definition might be missing if the element was
23134 * error prone
23135 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023136 */
23137 goto end_elem;
23138 }
23139 /*
23140 * Check the content model.
23141 */
23142 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
23143 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
23144
23145 /*
23146 * Workaround for "anyType".
23147 */
23148 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
23149 goto character_content;
23150
23151 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
23152 xmlChar *values[10];
23153 int terminal, nbval = 10, nbneg;
23154
23155 if (inode->regexCtxt == NULL) {
23156 /*
23157 * Create the regex context.
23158 */
23159 inode->regexCtxt =
23160 xmlRegNewExecCtxt(inode->typeDef->contModel,
23161 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
23162 vctxt);
23163 if (inode->regexCtxt == NULL) {
23164 VERROR_INT("xmlSchemaValidatorPopElem",
23165 "failed to create a regex context");
23166 goto internal_error;
23167 }
23168#ifdef DEBUG_AUTOMATA
23169 xmlGenericError(xmlGenericErrorContext,
23170 "AUTOMATON create on '%s'\n", inode->localName);
23171#endif
23172 }
23173 /*
23174 * Get hold of the still expected content, since a further
23175 * call to xmlRegExecPushString() will loose this information.
23176 */
23177 xmlRegExecNextValues(inode->regexCtxt,
23178 &nbval, &nbneg, &values[0], &terminal);
23179 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
23180 if (ret <= 0) {
23181 /*
23182 * Still missing something.
23183 */
23184 ret = 1;
23185 inode->flags |=
23186 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023187 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023188 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
23189 "Missing child element(s)",
23190 nbval, nbneg, values);
23191#ifdef DEBUG_AUTOMATA
23192 xmlGenericError(xmlGenericErrorContext,
23193 "AUTOMATON missing ERROR on '%s'\n",
23194 inode->localName);
23195#endif
23196 } else {
23197 /*
23198 * Content model is satisfied.
23199 */
23200 ret = 0;
23201#ifdef DEBUG_AUTOMATA
23202 xmlGenericError(xmlGenericErrorContext,
23203 "AUTOMATON succeeded on '%s'\n",
23204 inode->localName);
23205#endif
23206 }
23207
23208 }
23209 }
23210 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
23211 goto end_elem;
23212
23213character_content:
23214
23215 if (vctxt->value != NULL) {
23216 xmlSchemaFreeValue(vctxt->value);
23217 vctxt->value = NULL;
23218 }
23219 /*
23220 * Check character content.
23221 */
23222 if (inode->decl == NULL) {
23223 /*
23224 * Speedup if no declaration exists.
23225 */
23226 if (IS_SIMPLE_TYPE(inode->typeDef)) {
23227 ret = xmlSchemaVCheckINodeDataType(vctxt,
23228 inode, inode->typeDef, inode->value);
23229 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
23230 ret = xmlSchemaVCheckINodeDataType(vctxt,
23231 inode, inode->typeDef->contentTypeDef,
23232 inode->value);
23233 }
23234 if (ret < 0) {
23235 VERROR_INT("xmlSchemaValidatorPopElem",
23236 "calling xmlSchemaVCheckCVCSimpleType()");
23237 goto internal_error;
23238 }
23239 goto end_elem;
23240 }
23241 /*
23242 * cvc-elt (3.3.4) : 5
23243 * The appropriate case among the following must be true:
23244 */
23245 /*
23246 * cvc-elt (3.3.4) : 5.1
23247 * If the declaration has a {value constraint},
23248 * the item has neither element nor character [children] and
23249 * clause 3.2 has not applied, then all of the following must be true:
23250 */
23251 if ((inode->decl->value != NULL) &&
23252 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
23253 (! INODE_NILLED(inode))) {
23254 /*
23255 * cvc-elt (3.3.4) : 5.1.1
23256 * If the ·actual type definition· is a ·local type definition·
23257 * then the canonical lexical representation of the {value constraint}
23258 * value must be a valid default for the ·actual type definition· as
23259 * defined in Element Default Valid (Immediate) (§3.3.6).
23260 */
23261 /*
23262 * NOTE: 'local' above means types aquired by xsi:type.
23263 * NOTE: Although the *canonical* value is stated, it is not
23264 * relevant if canonical or not. Additionally XML Schema 1.1
23265 * will removed this requirement as well.
23266 */
23267 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
23268
23269 ret = xmlSchemaCheckCOSValidDefault(vctxt,
23270 inode->decl->value, &(inode->val));
23271 if (ret != 0) {
23272 if (ret < 0) {
23273 VERROR_INT("xmlSchemaValidatorPopElem",
23274 "calling xmlSchemaCheckCOSValidDefault()");
23275 goto internal_error;
23276 }
23277 goto end_elem;
23278 }
23279 /*
23280 * Stop here, to avoid redundant validation of the value
23281 * (see following).
23282 */
23283 goto default_psvi;
23284 }
23285 /*
23286 * cvc-elt (3.3.4) : 5.1.2
23287 * The element information item with the canonical lexical
23288 * representation of the {value constraint} value used as its
23289 * ·normalized value· must be ·valid· with respect to the
23290 * ·actual type definition· as defined by Element Locally Valid (Type)
23291 * (§3.3.4).
23292 */
23293 if (IS_SIMPLE_TYPE(inode->typeDef)) {
23294 ret = xmlSchemaVCheckINodeDataType(vctxt,
23295 inode, inode->typeDef, inode->decl->value);
23296 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
23297 ret = xmlSchemaVCheckINodeDataType(vctxt,
23298 inode, inode->typeDef->contentTypeDef,
23299 inode->decl->value);
23300 }
23301 if (ret != 0) {
23302 if (ret < 0) {
23303 VERROR_INT("xmlSchemaValidatorPopElem",
23304 "calling xmlSchemaVCheckCVCSimpleType()");
23305 goto internal_error;
23306 }
23307 goto end_elem;
23308 }
23309
23310default_psvi:
23311 /*
23312 * PSVI: Create a text node on the instance element.
23313 */
23314 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
23315 (inode->node != NULL)) {
23316 xmlNodePtr textChild;
23317 xmlChar *normValue;
23318 /*
23319 * VAL TODO: Normalize the value.
23320 */
23321 normValue = xmlSchemaNormalizeValue(inode->typeDef,
23322 inode->decl->value);
23323 if (normValue != NULL) {
23324 textChild = xmlNewText(BAD_CAST normValue);
23325 xmlFree(normValue);
23326 } else
23327 textChild = xmlNewText(inode->decl->value);
23328 if (textChild == NULL) {
23329 VERROR_INT("xmlSchemaValidatorPopElem",
23330 "calling xmlNewText()");
23331 goto internal_error;
23332 } else
23333 xmlAddChild(inode->node, textChild);
23334 }
23335
23336 } else if (! INODE_NILLED(inode)) {
23337 /*
23338 * 5.2.1 The element information item must be ·valid· with respect
23339 * to the ·actual type definition· as defined by Element Locally
23340 * Valid (Type) (§3.3.4).
23341 */
23342 if (IS_SIMPLE_TYPE(inode->typeDef)) {
23343 /*
23344 * SPEC (cvc-type) (3.1)
23345 * "If the type definition is a simple type definition, ..."
23346 * (3.1.3) "If clause 3.2 of Element Locally Valid
23347 * (Element) (§3.3.4) did not apply, then the ·normalized value·
23348 * must be ·valid· with respect to the type definition as defined
23349 * by String Valid (§3.14.4).
23350 */
23351 ret = xmlSchemaVCheckINodeDataType(vctxt,
23352 inode, inode->typeDef, inode->value);
23353 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
23354 /*
23355 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
23356 * definition, then the element information item must be
23357 * ·valid· with respect to the type definition as per
23358 * Element Locally Valid (Complex Type) (§3.4.4);"
23359 *
23360 * SPEC (cvc-complex-type) (2.2)
23361 * "If the {content type} is a simple type definition, ...
23362 * the ·normalized value· of the element information item is
23363 * ·valid· with respect to that simple type definition as
23364 * defined by String Valid (§3.14.4)."
23365 */
23366 ret = xmlSchemaVCheckINodeDataType(vctxt,
23367 inode, inode->typeDef->contentTypeDef, inode->value);
23368 }
23369 if (ret != 0) {
23370 if (ret < 0) {
23371 VERROR_INT("xmlSchemaValidatorPopElem",
23372 "calling xmlSchemaVCheckCVCSimpleType()");
23373 goto internal_error;
23374 }
23375 goto end_elem;
23376 }
23377 /*
23378 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
23379 * not applied, all of the following must be true:
23380 */
23381 if ((inode->decl->value != NULL) &&
23382 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
23383
23384 /*
23385 * TODO: We will need a computed value, when comparison is
23386 * done on computed values.
23387 */
23388 /*
23389 * 5.2.2.1 The element information item must have no element
23390 * information item [children].
23391 */
23392 if (inode->flags &
23393 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
23394 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
23395 VERROR(ret, NULL,
23396 "The content must not containt element nodes since "
23397 "there is a fixed value constraint");
23398 goto end_elem;
23399 } else {
23400 /*
23401 * 5.2.2.2 The appropriate case among the following must
23402 * be true:
23403 */
23404 if (HAS_MIXED_CONTENT(inode->typeDef)) {
23405 /*
23406 * 5.2.2.2.1 If the {content type} of the ·actual type
23407 * definition· is mixed, then the *initial value* of the
23408 * item must match the canonical lexical representation
23409 * of the {value constraint} value.
23410 *
23411 * ... the *initial value* of an element information
23412 * item is the string composed of, in order, the
23413 * [character code] of each character information item in
23414 * the [children] of that element information item.
23415 */
23416 if (! xmlStrEqual(inode->value, inode->decl->value)){
23417 /*
23418 * VAL TODO: Report invalid & expected values as well.
23419 * VAL TODO: Implement the canonical stuff.
23420 */
23421 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023422 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023423 ret, NULL, NULL,
23424 "The initial value '%s' does not match the fixed "
23425 "value constraint '%s'",
23426 inode->value, inode->decl->value);
23427 goto end_elem;
23428 }
23429 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
23430 /*
23431 * 5.2.2.2.2 If the {content type} of the ·actual type
23432 * definition· is a simple type definition, then the
23433 * *actual value* of the item must match the canonical
23434 * lexical representation of the {value constraint} value.
23435 */
23436 /*
23437 * VAL TODO: *actual value* is the normalized value, impl.
23438 * this.
23439 * VAL TODO: Report invalid & expected values as well.
23440 * VAL TODO: Implement a comparison with the computed values.
23441 */
23442 if (! xmlStrEqual(inode->value,
23443 inode->decl->value)) {
23444 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023445 xmlSchemaCustomErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023446 ret, NULL, NULL,
23447 "The actual value '%s' does not match the fixed "
23448 "value constraint '%s'",
23449 inode->value,
23450 inode->decl->value);
23451 goto end_elem;
23452 }
23453 }
23454 }
23455 }
23456 }
23457
23458end_elem:
23459 if (vctxt->depth < 0) {
23460 /* TODO: raise error? */
23461 return (0);
23462 }
23463 if (vctxt->depth == vctxt->skipDepth)
23464 vctxt->skipDepth = -1;
23465 /*
23466 * Evaluate the history of XPath state objects.
23467 */
23468 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
23469 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023470 /*
23471 * TODO: 6 The element information item must be ·valid· with respect to each of
23472 * the {identity-constraint definitions} as per Identity-constraint
23473 * Satisfied (§3.11.4).
23474 */
23475 /*
23476 * Validate IDC keyrefs.
23477 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023478 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
23479 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023480 /*
23481 * Merge/free the IDC table.
23482 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023483 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023484#ifdef DEBUG_IDC
23485 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023486 inode->nsName,
23487 inode->localName,
23488 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023489#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023490 if (vctxt->depth > 0) {
23491 /*
23492 * Merge the IDC node table with the table of the parent node.
23493 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023494 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
23495 goto internal_error;
23496 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023497 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023498 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023499 * Clear the current ielem.
23500 * VAL TODO: Don't free the PSVI IDC tables if they are
23501 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023502 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023503 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023504 /*
23505 * Skip further processing if we are on the validation root.
23506 */
23507 if (vctxt->depth == 0) {
23508 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023509 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023510 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023511 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023512 /*
23513 * Reset the bubbleDepth if needed.
23514 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023515 if (vctxt->aidcs != NULL) {
23516 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
23517 do {
23518 if (aidc->bubbleDepth == vctxt->depth) {
23519 /*
23520 * A bubbleDepth of a key/unique IDC matches the current
23521 * depth, this means that we are leaving the scope of the
23522 * top-most keyref IDC.
23523 */
23524 aidc->bubbleDepth = -1;
23525 }
23526 aidc = aidc->next;
23527 } while (aidc != NULL);
23528 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023529 vctxt->depth--;
23530 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000023531 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023532 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023533 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
23534 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023535 return (ret);
23536
23537internal_error:
23538 vctxt->err = -1;
23539 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023540}
23541
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023542/*
23543* 3.4.4 Complex Type Definition Validation Rules
23544* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
23545*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000023546static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023547xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000023548{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023549 xmlSchemaNodeInfoPtr pielem;
23550 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000023551 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000023552
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023553 if (vctxt->depth <= 0) {
23554 VERROR_INT("xmlSchemaValidateChildElem",
23555 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023556 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023557 }
23558 pielem = vctxt->elemInfos[vctxt->depth -1];
23559 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23560 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023561 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023562 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023563 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023564 if (INODE_NILLED(pielem)) {
23565 /*
23566 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
23567 */
23568 ACTIVATE_PARENT_ELEM;
23569 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
23570 VERROR(ret, NULL,
23571 "Neither character nor element content is allowed, "
23572 "because the element was 'nilled'");
23573 ACTIVATE_ELEM;
23574 goto unexpected_elem;
23575 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023576
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023577 ptype = pielem->typeDef;
23578
23579 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
23580 /*
23581 * Workaround for "anyType": we have currently no content model
23582 * assigned for "anyType", so handle it explicitely.
23583 * "anyType" has an unbounded, lax "any" wildcard.
23584 */
23585 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
23586 vctxt->inode->localName,
23587 vctxt->inode->nsName);
23588
23589 if (vctxt->inode->decl == NULL) {
23590 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023591 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023592 * Process "xsi:type".
23593 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023594 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023595 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
23596 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
23597 if (iattr != NULL) {
23598 ret = xmlSchemaProcessXSIType(vctxt, iattr,
23599 &(vctxt->inode->typeDef), NULL);
23600 if (ret != 0) {
23601 if (ret == -1) {
23602 VERROR_INT("xmlSchemaValidateChildElem",
23603 "calling xmlSchemaProcessXSIType() to "
23604 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023605 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000023606 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023607 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000023608 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023609 } else {
23610 /*
23611 * Fallback to "anyType".
23612 *
23613 * SPEC (cvc-assess-elt)
23614 * "If the item cannot be ·strictly assessed·, [...]
23615 * an element information item's schema validity may be laxly
23616 * assessed if its ·context-determined declaration· is not
23617 * skip by ·validating· with respect to the ·ur-type
23618 * definition· as per Element Locally Valid (Type) (§3.3.4)."
23619 */
23620 vctxt->inode->typeDef =
23621 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023622 }
23623 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023624 return (0);
23625 }
23626
23627 switch (ptype->contentType) {
23628 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023629 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023630 * SPEC (2.1) "If the {content type} is empty, then the
23631 * element information item has no character or element
23632 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023633 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023634 ACTIVATE_PARENT_ELEM
23635 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
23636 VERROR(ret, NULL,
23637 "Element content is not allowed, "
23638 "because the content type is empty");
23639 ACTIVATE_ELEM
23640 goto unexpected_elem;
23641 break;
23642
23643 case XML_SCHEMA_CONTENT_MIXED:
23644 case XML_SCHEMA_CONTENT_ELEMENTS: {
23645 xmlRegExecCtxtPtr regexCtxt;
23646 xmlChar *values[10];
23647 int terminal, nbval = 10, nbneg;
23648
23649 /* VAL TODO: Optimized "anyType" validation.*/
23650
23651 if (ptype->contModel == NULL) {
23652 VERROR_INT("xmlSchemaValidateChildElem",
23653 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023654 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000023655 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023656 /*
23657 * Safety belf for evaluation if the cont. model was already
23658 * examined to be invalid.
23659 */
23660 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
23661 VERROR_INT("xmlSchemaValidateChildElem",
23662 "validating elem, but elem content is already invalid");
23663 return (-1);
23664 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000023665
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023666 regexCtxt = pielem->regexCtxt;
23667 if (regexCtxt == NULL) {
23668 /*
23669 * Create the regex context.
23670 */
23671 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
23672 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
23673 vctxt);
23674 if (regexCtxt == NULL) {
23675 VERROR_INT("xmlSchemaValidateChildElem",
23676 "failed to create a regex context");
23677 return (-1);
23678 }
23679 pielem->regexCtxt = regexCtxt;
23680#ifdef DEBUG_AUTOMATA
23681 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
23682 pielem->localName);
23683#endif
23684 }
23685
23686 /*
23687 * SPEC (2.4) "If the {content type} is element-only or mixed,
23688 * then the sequence of the element information item's
23689 * element information item [children], if any, taken in
23690 * order, is ·valid· with respect to the {content type}'s
23691 * particle, as defined in Element Sequence Locally Valid
23692 * (Particle) (§3.9.4)."
23693 */
23694 ret = xmlRegExecPushString2(regexCtxt,
23695 vctxt->inode->localName,
23696 vctxt->inode->nsName,
23697 vctxt->inode);
23698#ifdef DEBUG_AUTOMATA
23699 if (ret < 0)
23700 xmlGenericError(xmlGenericErrorContext,
23701 "AUTOMATON push ERROR for '%s' on '%s'\n",
23702 vctxt->inode->localName, pielem->localName);
23703 else
23704 xmlGenericError(xmlGenericErrorContext,
23705 "AUTOMATON push OK for '%s' on '%s'\n",
23706 vctxt->inode->localName, pielem->localName);
23707#endif
23708 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
23709 VERROR_INT("xmlSchemaValidateChildElem",
23710 "calling xmlRegExecPushString2()");
23711 return (-1);
23712 }
23713 if (ret < 0) {
23714 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
23715 &values[0], &terminal);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023716 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023717 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
23718 "This element is not expected",
23719 nbval, nbneg, values);
23720 ret = vctxt->err;
23721 goto unexpected_elem;
23722 } else
23723 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000023724 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023725 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023726 case XML_SCHEMA_CONTENT_SIMPLE:
23727 case XML_SCHEMA_CONTENT_BASIC:
23728 ACTIVATE_PARENT_ELEM
23729 if (IS_COMPLEX_TYPE(ptype)) {
23730 /*
23731 * SPEC (cvc-complex-type) (2.2)
23732 * "If the {content type} is a simple type definition, then
23733 * the element information item has no element information
23734 * item [children], ..."
23735 */
23736 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
23737 VERROR(ret, NULL, "Element content is not allowed, "
23738 "because the content type is a simple type definition");
23739 } else {
23740 /*
23741 * SPEC (cvc-type) (3.1.2) "The element information item must
23742 * have no element information item [children]."
23743 */
23744 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
23745 VERROR(ret, NULL, "Element content is not allowed, "
23746 "because the type definition is simple");
23747 }
23748 ACTIVATE_ELEM
23749 ret = vctxt->err;
23750 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023751 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023752
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023753 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023754 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023755 }
23756 return (ret);
23757unexpected_elem:
23758 /*
23759 * Pop this element and set the skipDepth to skip
23760 * all further content of the parent element.
23761 */
23762 vctxt->skipDepth = vctxt->depth;
23763 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
23764 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
23765 return (ret);
23766}
23767
23768#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
23769#define XML_SCHEMA_PUSH_TEXT_CREATED 2
23770#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
23771
23772static int
23773xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
23774 int nodeType, const xmlChar *value, int len,
23775 int mode, int *consumed)
23776{
23777 /*
23778 * Unfortunately we have to duplicate the text sometimes.
23779 * OPTIMIZE: Maybe we could skip it, if:
23780 * 1. content type is simple
23781 * 2. whitespace is "collapse"
23782 * 3. it consists of whitespace only
23783 *
23784 * Process character content.
23785 */
23786 if (consumed != NULL)
23787 *consumed = 0;
23788 if (INODE_NILLED(vctxt->inode)) {
23789 /*
23790 * SPEC cvc-elt (3.3.4 - 3.2.1)
23791 * "The element information item must have no character or
23792 * element information item [children]."
23793 */
23794 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
23795 "Neither character nor element content is allowed "
23796 "because the element is 'nilled'");
23797 return (vctxt->err);
23798 }
23799 /*
23800 * SPEC (2.1) "If the {content type} is empty, then the
23801 * element information item has no character or element
23802 * information item [children]."
23803 */
23804 if (vctxt->inode->typeDef->contentType ==
23805 XML_SCHEMA_CONTENT_EMPTY) {
23806 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
23807 "Character content is not allowed, "
23808 "because the content type is empty");
23809 return (vctxt->err);
23810 }
23811
23812 if (vctxt->inode->typeDef->contentType ==
23813 XML_SCHEMA_CONTENT_ELEMENTS) {
23814 if ((nodeType != XML_TEXT_NODE) ||
23815 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
23816 /*
23817 * SPEC cvc-complex-type (2.3)
23818 * "If the {content type} is element-only, then the
23819 * element information item has no character information
23820 * item [children] other than those whose [character
23821 * code] is defined as a white space in [XML 1.0 (Second
23822 * Edition)]."
23823 */
23824 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
23825 "Character content other than whitespace is not allowed "
23826 "because the content type is 'element-only'");
23827 return (vctxt->err);
23828 }
23829 return (0);
23830 }
23831
23832 if ((value == NULL) || (value[0] == 0))
23833 return (0);
23834 /*
23835 * Save the value.
23836 * NOTE that even if the content type is *mixed*, we need the
23837 * *initial value* for default/fixed value constraints.
23838 */
23839 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
23840 ((vctxt->inode->decl == NULL) ||
23841 (vctxt->inode->decl->value == NULL)))
23842 return (0);
23843
23844 if (vctxt->inode->value == NULL) {
23845 /*
23846 * Set the value.
23847 */
23848 switch (mode) {
23849 case XML_SCHEMA_PUSH_TEXT_PERSIST:
23850 /*
23851 * When working on a tree.
23852 */
23853 vctxt->inode->value = value;
23854 break;
23855 case XML_SCHEMA_PUSH_TEXT_CREATED:
23856 /*
23857 * When working with the reader.
23858 * The value will be freed by the element info.
23859 */
23860 vctxt->inode->value = value;
23861 if (consumed != NULL)
23862 *consumed = 1;
23863 vctxt->inode->flags |=
23864 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23865 break;
23866 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
23867 /*
23868 * When working with SAX.
23869 * The value will be freed by the element info.
23870 */
23871 if (len != -1)
23872 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
23873 else
23874 vctxt->inode->value = BAD_CAST xmlStrdup(value);
23875 vctxt->inode->flags |=
23876 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23877 break;
23878 default:
23879 break;
23880 }
23881 } else {
23882 /*
23883 * Concat the value.
23884 */
23885 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000023886 vctxt->inode->value = BAD_CAST xmlStrncat(
23887 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023888 } else {
23889 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023890 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023891 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23892 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023893 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023894
23895 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000023896}
23897
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023898static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023899xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000023900{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023901 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000023902
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023903 if ((vctxt->skipDepth != -1) &&
23904 (vctxt->depth >= vctxt->skipDepth)) {
23905 VERROR_INT("xmlSchemaValidateElem",
23906 "in skip-state");
23907 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023908 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023909 if (vctxt->xsiAssemble) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000023910 /*
23911 * URGENT TODO: Better to fully stop validation
23912 * if there was an error during dynamic schema construction.
23913 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023914 if (xmlSchemaAssembleByXSI(vctxt) == -1)
23915 goto internal_error;
23916 }
23917 if (vctxt->depth > 0) {
23918 /*
23919 * Validate this element against the content model
23920 * of the parent.
23921 */
23922 ret = xmlSchemaValidateChildElem(vctxt);
23923 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023924 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023925 VERROR_INT("xmlSchemaValidateElem",
23926 "calling xmlSchemaStreamValidateChildElement()");
23927 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023928 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023929 goto exit;
23930 }
23931 if (vctxt->depth == vctxt->skipDepth)
23932 goto exit;
23933 if ((vctxt->inode->decl == NULL) &&
23934 (vctxt->inode->typeDef == NULL)) {
23935 VERROR_INT("xmlSchemaValidateElem",
23936 "the child element was valid but neither the "
23937 "declaration nor the type was set");
23938 goto internal_error;
23939 }
23940 } else {
23941 /*
23942 * Get the declaration of the validation root.
23943 */
23944 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
23945 vctxt->inode->localName,
23946 vctxt->inode->nsName);
23947 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000023948 ret = XML_SCHEMAV_CVC_ELT_1;
23949 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023950 "No matching global declaration available "
23951 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023952 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023953 }
23954 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023955
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023956 if (vctxt->inode->decl == NULL)
23957 goto type_validation;
23958
23959 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
23960 int skip;
23961 /*
23962 * Wildcards.
23963 */
23964 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
23965 if (ret != 0) {
23966 if (ret < 0) {
23967 VERROR_INT("xmlSchemaValidateElem",
23968 "calling xmlSchemaValidateElemWildcard()");
23969 goto internal_error;
23970 }
23971 goto exit;
23972 }
23973 if (skip) {
23974 vctxt->skipDepth = vctxt->depth;
23975 goto exit;
23976 }
23977 /*
23978 * The declaration might be set by the wildcard validation,
23979 * when the processContents is "lax" or "strict".
23980 */
23981 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
23982 /*
23983 * Clear the "decl" field to not confuse further processing.
23984 */
23985 vctxt->inode->decl = NULL;
23986 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023987 }
Daniel Veillard4255d502002-04-16 15:50:10 +000023988 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023989 /*
23990 * Validate against the declaration.
23991 */
23992 ret = xmlSchemaValidateElemDecl(vctxt);
23993 if (ret != 0) {
23994 if (ret < 0) {
23995 VERROR_INT("xmlSchemaValidateElem",
23996 "calling xmlSchemaValidateElemDecl()");
23997 goto internal_error;
23998 }
23999 goto exit;
24000 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000024001 /*
24002 * Validate against the type definition.
24003 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024004type_validation:
24005
24006 if (vctxt->inode->typeDef == NULL) {
24007 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
24008 ret = XML_SCHEMAV_CVC_TYPE_1;
24009 VERROR(ret, NULL,
24010 "The type definition is absent");
24011 goto exit;
24012 }
24013 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
24014 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
24015 ret = XML_SCHEMAV_CVC_TYPE_2;
24016 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000024017 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024018 goto exit;
24019 }
24020 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000024021 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024022 * during validation against the declaration. This must be done
24023 * _before_ attribute validation.
24024 */
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000024025 if (vctxt->xpathStates != NULL) {
24026 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
24027 if (ret == -1) {
24028 VERROR_INT("xmlSchemaValidateElem",
24029 "calling xmlSchemaXPathEvaluate()");
24030 goto internal_error;
24031 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024032 }
24033 /*
24034 * Validate attributes.
24035 */
24036 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
24037 if ((vctxt->nbAttrInfos != 0) ||
24038 (vctxt->inode->typeDef->attributeUses != NULL)) {
24039
24040 ret = xmlSchemaVAttributesComplex(vctxt);
24041 }
24042 } else if (vctxt->nbAttrInfos != 0) {
24043
24044 ret = xmlSchemaVAttributesSimple(vctxt);
24045 }
24046 /*
24047 * Clear registered attributes.
24048 */
24049 if (vctxt->nbAttrInfos != 0)
24050 xmlSchemaClearAttrInfos(vctxt);
24051 if (ret == -1) {
24052 VERROR_INT("xmlSchemaValidateElem",
24053 "calling attributes validation");
24054 goto internal_error;
24055 }
24056 /*
24057 * Don't return an error if attributes are invalid on purpose.
24058 */
24059 ret = 0;
24060
24061exit:
24062 if (ret != 0)
24063 vctxt->skipDepth = vctxt->depth;
24064 return (ret);
24065internal_error:
24066 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000024067}
24068
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024069#ifdef XML_SCHEMA_READER_ENABLED
24070static int
24071xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000024072{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024073 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
24074 int depth, nodeType, ret = 0, consumed;
24075 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000024076
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024077 vctxt->depth = -1;
24078 ret = xmlTextReaderRead(vctxt->reader);
24079 /*
24080 * Move to the document element.
24081 */
24082 while (ret == 1) {
24083 nodeType = xmlTextReaderNodeType(vctxt->reader);
24084 if (nodeType == XML_ELEMENT_NODE)
24085 goto root_found;
24086 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024087 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024088 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024089
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024090root_found:
24091
24092 do {
24093 depth = xmlTextReaderDepth(vctxt->reader);
24094 nodeType = xmlTextReaderNodeType(vctxt->reader);
24095
24096 if (nodeType == XML_ELEMENT_NODE) {
24097
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000024098 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024099 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
24100 VERROR_INT("xmlSchemaVReaderWalk",
24101 "calling xmlSchemaValidatorPushElem()");
24102 goto internal_error;
24103 }
24104 ielem = vctxt->inode;
24105 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
24106 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
24107 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
24108 /*
24109 * Is the element empty?
24110 */
24111 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
24112 if (ret == -1) {
24113 VERROR_INT("xmlSchemaVReaderWalk",
24114 "calling xmlTextReaderIsEmptyElement()");
24115 goto internal_error;
24116 }
24117 if (ret) {
24118 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
24119 }
24120 /*
24121 * Register attributes.
24122 */
24123 vctxt->nbAttrInfos = 0;
24124 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
24125 if (ret == -1) {
24126 VERROR_INT("xmlSchemaVReaderWalk",
24127 "calling xmlTextReaderMoveToFirstAttribute()");
24128 goto internal_error;
24129 }
24130 if (ret == 1) {
24131 do {
24132 /*
24133 * VAL TODO: How do we know that the reader works on a
24134 * node tree, to be able to pass a node here?
24135 */
24136 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
24137 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
24138 xmlTextReaderNamespaceUri(vctxt->reader), 1,
24139 xmlTextReaderValue(vctxt->reader), 1) == -1) {
24140
24141 VERROR_INT("xmlSchemaVReaderWalk",
24142 "calling xmlSchemaValidatorPushAttribute()");
24143 goto internal_error;
24144 }
24145 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
24146 if (ret == -1) {
24147 VERROR_INT("xmlSchemaVReaderWalk",
24148 "calling xmlTextReaderMoveToFirstAttribute()");
24149 goto internal_error;
24150 }
24151 } while (ret == 1);
24152 /*
24153 * Back to element position.
24154 */
24155 ret = xmlTextReaderMoveToElement(vctxt->reader);
24156 if (ret == -1) {
24157 VERROR_INT("xmlSchemaVReaderWalk",
24158 "calling xmlTextReaderMoveToElement()");
24159 goto internal_error;
24160 }
24161 }
24162 /*
24163 * Validate the element.
24164 */
24165 ret= xmlSchemaValidateElem(vctxt);
24166 if (ret != 0) {
24167 if (ret == -1) {
24168 VERROR_INT("xmlSchemaVReaderWalk",
24169 "calling xmlSchemaValidateElem()");
24170 goto internal_error;
24171 }
24172 goto exit;
24173 }
24174 if (vctxt->depth == vctxt->skipDepth) {
24175 int curDepth;
24176 /*
24177 * Skip all content.
24178 */
24179 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
24180 ret = xmlTextReaderRead(vctxt->reader);
24181 curDepth = xmlTextReaderDepth(vctxt->reader);
24182 while ((ret == 1) && (curDepth != depth)) {
24183 ret = xmlTextReaderRead(vctxt->reader);
24184 curDepth = xmlTextReaderDepth(vctxt->reader);
24185 }
24186 if (ret < 0) {
24187 /*
24188 * VAL TODO: A reader error occured; what to do here?
24189 */
24190 ret = 1;
24191 goto exit;
24192 }
24193 }
24194 goto leave_elem;
24195 }
24196 /*
24197 * READER VAL TODO: Is an END_ELEM really never called
24198 * if the elem is empty?
24199 */
24200 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
24201 goto leave_elem;
24202 } else if (nodeType == END_ELEM) {
24203 /*
24204 * Process END of element.
24205 */
24206leave_elem:
24207 ret = xmlSchemaValidatorPopElem(vctxt);
24208 if (ret != 0) {
24209 if (ret < 0) {
24210 VERROR_INT("xmlSchemaVReaderWalk",
24211 "calling xmlSchemaValidatorPopElem()");
24212 goto internal_error;
24213 }
24214 goto exit;
24215 }
24216 if (vctxt->depth >= 0)
24217 ielem = vctxt->inode;
24218 else
24219 ielem = NULL;
24220 } else if ((nodeType == XML_TEXT_NODE) ||
24221 (nodeType == XML_CDATA_SECTION_NODE) ||
24222 (nodeType == WHTSP) ||
24223 (nodeType == SIGN_WHTSP)) {
24224 /*
24225 * Process character content.
24226 */
24227 xmlChar *value;
24228
24229 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
24230 nodeType = XML_TEXT_NODE;
24231
24232 value = xmlTextReaderValue(vctxt->reader);
24233 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
24234 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
24235 if (! consumed)
24236 xmlFree(value);
24237 if (ret == -1) {
24238 VERROR_INT("xmlSchemaVReaderWalk",
24239 "calling xmlSchemaVPushText()");
24240 goto internal_error;
24241 }
24242 } else if ((nodeType == XML_ENTITY_NODE) ||
24243 (nodeType == XML_ENTITY_REF_NODE)) {
24244 /*
24245 * VAL TODO: What to do with entities?
24246 */
24247 TODO
24248 }
24249 /*
24250 * Read next node.
24251 */
24252 ret = xmlTextReaderRead(vctxt->reader);
24253 } while (ret == 1);
24254
24255exit:
24256 return (ret);
24257internal_error:
24258 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000024259}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024260#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000024261
24262/************************************************************************
24263 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024264 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000024265 * *
24266 ************************************************************************/
24267
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024268/*
24269* Process text content.
24270*/
24271static void
24272xmlSchemaSAXHandleText(void *ctx,
24273 const xmlChar * ch,
24274 int len)
24275{
24276 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
24277
24278 if (vctxt->depth < 0)
24279 return;
24280 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
24281 return;
24282 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
24283 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
24284 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
24285 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
24286 VERROR_INT("xmlSchemaSAXHandleCDataSection",
24287 "calling xmlSchemaVPushText()");
24288 vctxt->err = -1;
24289 xmlStopParser(vctxt->parserCtxt);
24290 }
24291}
24292
24293/*
24294* Process CDATA content.
24295*/
24296static void
24297xmlSchemaSAXHandleCDataSection(void *ctx,
24298 const xmlChar * ch,
24299 int len)
24300{
24301 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
24302
24303 if (vctxt->depth < 0)
24304 return;
24305 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
24306 return;
24307 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
24308 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
24309 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
24310 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
24311 VERROR_INT("xmlSchemaSAXHandleCDataSection",
24312 "calling xmlSchemaVPushText()");
24313 vctxt->err = -1;
24314 xmlStopParser(vctxt->parserCtxt);
24315 }
24316}
24317
24318static void
24319xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
24320 const xmlChar * name ATTRIBUTE_UNUSED)
24321{
24322 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
24323
24324 if (vctxt->depth < 0)
24325 return;
24326 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
24327 return;
24328 /* SAX VAL TODO: What to do here? */
24329 TODO
24330}
24331
24332static void
24333xmlSchemaSAXHandleStartElementNs(void *ctx,
24334 const xmlChar * localname,
24335 const xmlChar * prefix ATTRIBUTE_UNUSED,
24336 const xmlChar * URI,
24337 int nb_namespaces,
24338 const xmlChar ** namespaces,
24339 int nb_attributes,
24340 int nb_defaulted ATTRIBUTE_UNUSED,
24341 const xmlChar ** attributes)
24342{
24343 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
24344 int ret;
24345 xmlSchemaNodeInfoPtr ielem;
24346 int i, j;
24347
24348 /*
24349 * SAX VAL TODO: What to do with nb_defaulted?
24350 */
24351 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000024352 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024353 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000024354 vctxt->depth++;
24355 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024356 return;
24357 /*
24358 * Push the element.
24359 */
24360 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
24361 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
24362 "calling xmlSchemaValidatorPushElem()");
24363 goto internal_error;
24364 }
24365 ielem = vctxt->inode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024366 /*
24367 * TODO: Is this OK?
24368 */
24369 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024370 ielem->localName = localname;
24371 ielem->nsName = URI;
24372 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
24373 /*
24374 * Register namespaces on the elem info.
24375 */
24376 if (nb_namespaces != 0) {
24377 /*
24378 * Although the parser builds its own namespace list,
24379 * we have no access to it, so we'll use an own one.
24380 */
24381 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
24382 /*
24383 * Store prefix and namespace name.
24384 */
24385 if (ielem->nsBindings == NULL) {
24386 ielem->nsBindings =
24387 (const xmlChar **) xmlMalloc(10 *
24388 sizeof(const xmlChar *));
24389 if (ielem->nsBindings == NULL) {
24390 xmlSchemaVErrMemory(vctxt,
24391 "allocating namespace bindings for SAX validation",
24392 NULL);
24393 goto internal_error;
24394 }
24395 ielem->nbNsBindings = 0;
24396 ielem->sizeNsBindings = 5;
24397 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
24398 ielem->sizeNsBindings *= 2;
24399 ielem->nsBindings =
24400 (const xmlChar **) xmlRealloc(
24401 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000024402 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024403 if (ielem->nsBindings == NULL) {
24404 xmlSchemaVErrMemory(vctxt,
24405 "re-allocating namespace bindings for SAX validation",
24406 NULL);
24407 goto internal_error;
24408 }
24409 }
24410
24411 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
24412 if (namespaces[j+1][0] == 0) {
24413 /*
24414 * Handle xmlns="".
24415 */
24416 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
24417 } else
24418 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
24419 namespaces[j+1];
24420 ielem->nbNsBindings++;
24421 }
24422 }
24423 /*
24424 * Register attributes.
24425 * SAX VAL TODO: We are not adding namespace declaration
24426 * attributes yet.
24427 */
24428 if (nb_attributes != 0) {
24429 xmlChar *value;
24430
24431 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
24432 /*
24433 * Duplicate the value.
24434 */
24435 value = xmlStrndup(attributes[j+3],
24436 attributes[j+4] - attributes[j+3]);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024437 /*
24438 * TODO: Set the node line.
24439 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024440 ret = xmlSchemaValidatorPushAttribute(vctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024441 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024442 value, 1);
24443 if (ret == -1) {
24444 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
24445 "calling xmlSchemaValidatorPushAttribute()");
24446 goto internal_error;
24447 }
24448 }
24449 }
24450 /*
24451 * Validate the element.
24452 */
24453 ret = xmlSchemaValidateElem(vctxt);
24454 if (ret != 0) {
24455 if (ret == -1) {
24456 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
24457 "calling xmlSchemaValidateElem()");
24458 goto internal_error;
24459 }
24460 goto exit;
24461 }
24462
24463exit:
24464 return;
24465internal_error:
24466 vctxt->err = -1;
24467 xmlStopParser(vctxt->parserCtxt);
24468 return;
24469}
24470
24471static void
24472xmlSchemaSAXHandleEndElementNs(void *ctx,
24473 const xmlChar * localname ATTRIBUTE_UNUSED,
24474 const xmlChar * prefix ATTRIBUTE_UNUSED,
24475 const xmlChar * URI ATTRIBUTE_UNUSED)
24476{
24477 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
24478 int res;
24479
24480 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000024481 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024482 */
24483 if (vctxt->skipDepth != -1) {
24484 if (vctxt->depth > vctxt->skipDepth) {
24485 vctxt->depth--;
24486 return;
24487 } else
24488 vctxt->skipDepth = -1;
24489 }
24490 /*
24491 * SAX VAL TODO: Just a temporary check.
24492 */
24493 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
24494 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
24495 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
24496 "elem pop mismatch");
24497 }
24498 res = xmlSchemaValidatorPopElem(vctxt);
24499 if (res != 0) {
24500 if (res < 0) {
24501 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
24502 "calling xmlSchemaValidatorPopElem()");
24503 goto internal_error;
24504 }
24505 goto exit;
24506 }
24507exit:
24508 return;
24509internal_error:
24510 vctxt->err = -1;
24511 xmlStopParser(vctxt->parserCtxt);
24512 return;
24513}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024514
Daniel Veillard4255d502002-04-16 15:50:10 +000024515/************************************************************************
24516 * *
24517 * Validation interfaces *
24518 * *
24519 ************************************************************************/
24520
24521/**
24522 * xmlSchemaNewValidCtxt:
24523 * @schema: a precompiled XML Schemas
24524 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024525 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000024526 *
24527 * Returns the validation context or NULL in case of error
24528 */
24529xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024530xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
24531{
Daniel Veillard4255d502002-04-16 15:50:10 +000024532 xmlSchemaValidCtxtPtr ret;
24533
24534 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
24535 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024536 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000024537 return (NULL);
24538 }
24539 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024540 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024541 ret->dict = xmlDictCreate();
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000024542 ret->nodeQNames = xmlSchemaItemListCreate();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024543 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000024544 return (ret);
24545}
24546
24547/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024548 * xmlSchemaClearValidCtxt:
24549 * @ctxt: the schema validation context
24550 *
24551 * Free the resources associated to the schema validation context;
24552 * leaves some fields alive intended for reuse of the context.
24553 */
24554static void
24555xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
24556{
24557 if (vctxt == NULL)
24558 return;
24559
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000024560 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024561 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024562 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000024563#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024564 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000024565#endif
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024566 if (vctxt->value != NULL) {
24567 xmlSchemaFreeValue(vctxt->value);
24568 vctxt->value = NULL;
24569 }
24570 /*
24571 * Augmented IDC information.
24572 */
24573 if (vctxt->aidcs != NULL) {
24574 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
24575 do {
24576 next = cur->next;
24577 xmlFree(cur);
24578 cur = next;
24579 } while (cur != NULL);
24580 vctxt->aidcs = NULL;
24581 }
24582 if (vctxt->idcNodes != NULL) {
24583 int i;
24584 xmlSchemaPSVIIDCNodePtr item;
24585
24586 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024587 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024588 xmlFree(item->keys);
24589 xmlFree(item);
24590 }
24591 xmlFree(vctxt->idcNodes);
24592 vctxt->idcNodes = NULL;
24593 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024594 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024595 * Note that we won't delete the XPath state pool here.
24596 */
24597 if (vctxt->xpathStates != NULL) {
24598 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
24599 vctxt->xpathStates = NULL;
24600 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024601 /*
24602 * Attribute info.
24603 */
24604 if (vctxt->nbAttrInfos != 0) {
24605 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024606 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024607 /*
24608 * Element info.
24609 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024610 if (vctxt->elemInfos != NULL) {
24611 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024612 xmlSchemaNodeInfoPtr ei;
24613
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024614 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024615 ei = vctxt->elemInfos[i];
24616 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024617 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024618 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024619 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024620 }
24621 xmlSchemaItemListClear(vctxt->nodeQNames);
24622 /* Recreate the dict. */
24623 xmlDictFree(vctxt->dict);
24624 vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024625}
24626
24627/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024628 * xmlSchemaFreeValidCtxt:
24629 * @ctxt: the schema validation context
24630 *
24631 * Free the resources associated to the schema validation context
24632 */
24633void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024634xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
24635{
Daniel Veillard4255d502002-04-16 15:50:10 +000024636 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024637 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000024638 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024639 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024640 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024641 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024642 if (ctxt->idcNodes != NULL) {
24643 int i;
24644 xmlSchemaPSVIIDCNodePtr item;
24645
24646 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024647 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024648 xmlFree(item->keys);
24649 xmlFree(item);
24650 }
24651 xmlFree(ctxt->idcNodes);
24652 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024653 if (ctxt->idcKeys != NULL) {
24654 int i;
24655 for (i = 0; i < ctxt->nbIdcKeys; i++)
24656 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
24657 xmlFree(ctxt->idcKeys);
24658 }
24659
24660 if (ctxt->xpathStates != NULL)
24661 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
24662 if (ctxt->xpathStatePool != NULL)
24663 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
24664
24665 /*
24666 * Augmented IDC information.
24667 */
24668 if (ctxt->aidcs != NULL) {
24669 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
24670 do {
24671 next = cur->next;
24672 xmlFree(cur);
24673 cur = next;
24674 } while (cur != NULL);
24675 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024676 if (ctxt->attrInfos != NULL) {
24677 int i;
24678 xmlSchemaAttrInfoPtr attr;
24679
24680 /* Just a paranoid call to the cleanup. */
24681 if (ctxt->nbAttrInfos != 0)
24682 xmlSchemaClearAttrInfos(ctxt);
24683 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
24684 attr = ctxt->attrInfos[i];
24685 xmlFree(attr);
24686 }
24687 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000024688 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024689 if (ctxt->elemInfos != NULL) {
24690 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024691 xmlSchemaNodeInfoPtr ei;
24692
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024693 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024694 ei = ctxt->elemInfos[i];
24695 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024696 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024697 xmlSchemaClearElemInfo(ei);
24698 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024699 }
24700 xmlFree(ctxt->elemInfos);
24701 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024702 if (ctxt->nodeQNames != NULL)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000024703 xmlSchemaItemListFree(ctxt->nodeQNames);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024704 if (ctxt->dict != NULL)
24705 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000024706 xmlFree(ctxt);
24707}
24708
24709/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000024710 * xmlSchemaIsValid:
24711 * @ctxt: the schema validation context
24712 *
24713 * Check if any error was detected during validation.
24714 *
24715 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
24716 * of internal error.
24717 */
24718int
24719xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
24720{
24721 if (ctxt == NULL)
24722 return(-1);
24723 return(ctxt->err == 0);
24724}
24725
24726/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024727 * xmlSchemaSetValidErrors:
24728 * @ctxt: a schema validation context
24729 * @err: the error function
24730 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000024731 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000024732 *
William M. Brack2f2a6632004-08-20 23:09:47 +000024733 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000024734 */
24735void
24736xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024737 xmlSchemaValidityErrorFunc err,
24738 xmlSchemaValidityWarningFunc warn, void *ctx)
24739{
Daniel Veillard4255d502002-04-16 15:50:10 +000024740 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024741 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000024742 ctxt->error = err;
24743 ctxt->warning = warn;
24744 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024745 if (ctxt->pctxt != NULL)
24746 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000024747}
24748
24749/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000024750 * xmlSchemaSetValidStructuredErrors:
24751 * @ctxt: a schema validation context
24752 * @serror: the structured error function
24753 * @ctx: the functions context
24754 *
24755 * Set the structured error callback
24756 */
24757void
24758xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
24759 xmlStructuredErrorFunc serror, void *ctx)
24760{
24761 if (ctxt == NULL)
24762 return;
24763 ctxt->serror = serror;
24764 ctxt->error = NULL;
24765 ctxt->warning = NULL;
24766 ctxt->userData = ctx;
24767}
24768
24769/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000024770 * xmlSchemaGetValidErrors:
24771 * @ctxt: a XML-Schema validation context
24772 * @err: the error function result
24773 * @warn: the warning function result
24774 * @ctx: the functions context result
24775 *
24776 * Get the error and warning callback informations
24777 *
24778 * Returns -1 in case of error and 0 otherwise
24779 */
24780int
24781xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
24782 xmlSchemaValidityErrorFunc * err,
24783 xmlSchemaValidityWarningFunc * warn, void **ctx)
24784{
24785 if (ctxt == NULL)
24786 return (-1);
24787 if (err != NULL)
24788 *err = ctxt->error;
24789 if (warn != NULL)
24790 *warn = ctxt->warning;
24791 if (ctx != NULL)
24792 *ctx = ctxt->userData;
24793 return (0);
24794}
24795
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024796
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024797/**
Daniel Veillard6927b102004-10-27 17:29:04 +000024798 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024799 * @ctxt: a schema validation context
24800 * @options: a combination of xmlSchemaValidOption
24801 *
24802 * Sets the options to be used during the validation.
24803 *
24804 * Returns 0 in case of success, -1 in case of an
24805 * API error.
24806 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024807int
24808xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
24809 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024810
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024811{
24812 int i;
24813
24814 if (ctxt == NULL)
24815 return (-1);
24816 /*
24817 * WARNING: Change the start value if adding to the
24818 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024819 * TODO: Is there an other, more easy to maintain,
24820 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024821 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024822 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024823 if (options & 1<<i)
24824 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024825 }
24826 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024827 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024828}
24829
24830/**
Daniel Veillard6927b102004-10-27 17:29:04 +000024831 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024832 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024833 *
William M. Brack21e4ef22005-01-02 09:53:13 +000024834 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024835 *
William M. Brack21e4ef22005-01-02 09:53:13 +000024836 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024837 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024838int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024839xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024840
24841{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024842 if (ctxt == NULL)
24843 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024844 else
24845 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024846}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024847
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024848static int
24849xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
24850{
24851 xmlAttrPtr attr;
24852 int ret = 0;
24853 xmlSchemaNodeInfoPtr ielem = NULL;
24854 xmlNodePtr node, valRoot;
24855 const xmlChar *nsName;
24856
24857 /* DOC VAL TODO: Move this to the start function. */
24858 valRoot = xmlDocGetRootElement(vctxt->doc);
24859 if (valRoot == NULL) {
24860 /* VAL TODO: Error code? */
24861 VERROR(1, NULL, "The document has no document element");
24862 return (1);
24863 }
24864 vctxt->depth = -1;
24865 vctxt->validationRoot = valRoot;
24866 node = valRoot;
24867 while (node != NULL) {
24868 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
24869 goto next_sibling;
24870 if (node->type == XML_ELEMENT_NODE) {
24871
24872 /*
24873 * Init the node-info.
24874 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000024875 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024876 if (xmlSchemaValidatorPushElem(vctxt) == -1)
24877 goto internal_error;
24878 ielem = vctxt->inode;
24879 ielem->node = node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024880 ielem->nodeLine = node->line;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024881 ielem->localName = node->name;
24882 if (node->ns != NULL)
24883 ielem->nsName = node->ns->href;
24884 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
24885 /*
24886 * Register attributes.
24887 * DOC VAL TODO: We do not register namespace declaration
24888 * attributes yet.
24889 */
24890 vctxt->nbAttrInfos = 0;
24891 if (node->properties != NULL) {
24892 attr = node->properties;
24893 do {
24894 if (attr->ns != NULL)
24895 nsName = attr->ns->href;
24896 else
24897 nsName = NULL;
24898 ret = xmlSchemaValidatorPushAttribute(vctxt,
24899 (xmlNodePtr) attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024900 /*
24901 * Note that we give it the line number of the
24902 * parent element.
24903 */
24904 ielem->nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024905 attr->name, nsName, 0,
24906 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
24907 if (ret == -1) {
24908 VERROR_INT("xmlSchemaDocWalk",
24909 "calling xmlSchemaValidatorPushAttribute()");
24910 goto internal_error;
24911 }
24912 attr = attr->next;
24913 } while (attr);
24914 }
24915 /*
24916 * Validate the element.
24917 */
24918 ret = xmlSchemaValidateElem(vctxt);
24919 if (ret != 0) {
24920 if (ret == -1) {
24921 VERROR_INT("xmlSchemaDocWalk",
24922 "calling xmlSchemaValidateElem()");
24923 goto internal_error;
24924 }
24925 /*
24926 * Don't stop validation; just skip the content
24927 * of this element.
24928 */
24929 goto leave_node;
24930 }
24931 if ((vctxt->skipDepth != -1) &&
24932 (vctxt->depth >= vctxt->skipDepth))
24933 goto leave_node;
24934 } else if ((node->type == XML_TEXT_NODE) ||
24935 (node->type == XML_CDATA_SECTION_NODE)) {
24936 /*
24937 * Process character content.
24938 */
24939 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
24940 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
24941 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
24942 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
24943 if (ret < 0) {
24944 VERROR_INT("xmlSchemaVDocWalk",
24945 "calling xmlSchemaVPushText()");
24946 goto internal_error;
24947 }
24948 /*
24949 * DOC VAL TODO: Should we skip further validation of the
24950 * element content here?
24951 */
24952 } else if ((node->type == XML_ENTITY_NODE) ||
24953 (node->type == XML_ENTITY_REF_NODE)) {
24954 /*
24955 * DOC VAL TODO: What to do with entities?
24956 */
24957 TODO
24958 } else {
24959 goto leave_node;
24960 /*
24961 * DOC VAL TODO: XInclude nodes, etc.
24962 */
24963 }
24964 /*
24965 * Walk the doc.
24966 */
24967 if (node->children != NULL) {
24968 node = node->children;
24969 continue;
24970 }
24971leave_node:
24972 if (node->type == XML_ELEMENT_NODE) {
24973 /*
24974 * Leaving the scope of an element.
24975 */
24976 if (node != vctxt->inode->node) {
24977 VERROR_INT("xmlSchemaVDocWalk",
24978 "element position mismatch");
24979 goto internal_error;
24980 }
24981 ret = xmlSchemaValidatorPopElem(vctxt);
24982 if (ret != 0) {
24983 if (ret < 0) {
24984 VERROR_INT("xmlSchemaVDocWalk",
24985 "calling xmlSchemaValidatorPopElem()");
24986 goto internal_error;
24987 }
24988 }
24989 if (node == valRoot)
24990 goto exit;
24991 }
24992next_sibling:
24993 if (node->next != NULL)
24994 node = node->next;
24995 else {
24996 node = node->parent;
24997 goto leave_node;
24998 }
24999 }
25000
25001exit:
25002 return (ret);
25003internal_error:
25004 return (-1);
25005}
25006
25007static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000025008xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025009 /*
25010 * Some initialization.
25011 */
25012 vctxt->err = 0;
25013 vctxt->nberrors = 0;
25014 vctxt->depth = -1;
25015 vctxt->skipDepth = -1;
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025016 vctxt->xsiAssemble = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025017 /*
25018 * Create a schema + parser if necessary.
25019 */
25020 if (vctxt->schema == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025021 xmlSchemaParserCtxtPtr pctxt;
25022
25023 vctxt->xsiAssemble = 1;
25024 /*
25025 * If not schema was given then we will create a schema
25026 * dynamically using XSI schema locations.
25027 *
25028 * Create the schema parser context.
25029 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025030 if ((vctxt->pctxt == NULL) &&
25031 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
25032 return (-1);
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025033 pctxt = vctxt->pctxt;
25034 pctxt->xsiAssemble = 1;
25035 /*
25036 * Create the schema.
25037 */
25038 vctxt->schema = xmlSchemaNewSchema(pctxt);
25039 if (vctxt->schema == NULL)
25040 return (-1);
25041 /*
25042 * Create the schema construction context.
25043 */
25044 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
25045 if (pctxt->constructor == NULL)
25046 return(-1);
25047 pctxt->constructor->schema = vctxt->schema;
25048 /*
25049 * Take ownership of the constructor to be able to free it.
25050 */
25051 pctxt->ownsConstructor = 1;
25052 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025053 /*
25054 * Augment the IDC definitions.
25055 */
25056 if (vctxt->schema->idcDef != NULL) {
25057 xmlHashScan(vctxt->schema->idcDef,
25058 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
25059 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000025060 return(0);
25061}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025062
Daniel Veillardf10ae122005-07-10 19:03:16 +000025063static void
25064xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025065 if (vctxt->xsiAssemble) {
25066 if (vctxt->schema != NULL) {
25067 xmlSchemaFree(vctxt->schema);
25068 vctxt->schema = NULL;
25069 }
25070 }
25071 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000025072}
25073
25074static int
25075xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
25076{
25077 int ret = 0;
25078
25079 if (xmlSchemaPreRun(vctxt) < 0)
25080 return(-1);
25081
25082 if (vctxt->doc != NULL) {
25083 /*
25084 * Tree validation.
25085 */
25086 ret = xmlSchemaVDocWalk(vctxt);
25087#ifdef LIBXML_READER_ENABLED
25088 } else if (vctxt->reader != NULL) {
25089 /*
25090 * XML Reader validation.
25091 */
25092#ifdef XML_SCHEMA_READER_ENABLED
25093 ret = xmlSchemaVReaderWalk(vctxt);
25094#endif
25095#endif
25096 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
25097 /*
25098 * SAX validation.
25099 */
25100 ret = xmlParseDocument(vctxt->parserCtxt);
25101 } else {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025102 VERROR_INT("xmlSchemaVStart",
Daniel Veillardf10ae122005-07-10 19:03:16 +000025103 "no instance to validate");
25104 ret = -1;
25105 }
25106
25107 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025108 if (ret == 0)
25109 ret = vctxt->err;
25110 return (ret);
25111}
25112
25113/**
25114 * xmlSchemaValidateOneElement:
25115 * @ctxt: a schema validation context
25116 * @elem: an element node
25117 *
25118 * Validate a branch of a tree, starting with the given @elem.
25119 *
25120 * Returns 0 if the element and its subtree is valid, a positive error
25121 * code number otherwise and -1 in case of an internal or API error.
25122 */
25123int
25124xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
25125{
25126 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
25127 return (-1);
25128
25129 if (ctxt->schema == NULL)
25130 return (-1);
25131
25132 ctxt->doc = elem->doc;
25133 ctxt->node = elem;
25134 ctxt->validationRoot = elem;
25135 return(xmlSchemaVStart(ctxt));
25136}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000025137
Daniel Veillard259f0df2004-08-18 09:13:18 +000025138/**
Daniel Veillard4255d502002-04-16 15:50:10 +000025139 * xmlSchemaValidateDoc:
25140 * @ctxt: a schema validation context
25141 * @doc: a parsed document tree
25142 *
25143 * Validate a document tree in memory.
25144 *
25145 * Returns 0 if the document is schemas valid, a positive error code
25146 * number otherwise and -1 in case of internal or API error.
25147 */
25148int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000025149xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
25150{
Daniel Veillard4255d502002-04-16 15:50:10 +000025151 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000025152 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000025153
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025154 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000025155 ctxt->node = xmlDocGetRootElement(doc);
25156 if (ctxt->node == NULL) {
Kasimier T. Buchcik22c0c462005-09-12 19:09:46 +000025157 xmlSchemaCustomErr(ACTXT_CAST ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000025158 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
25159 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025160 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000025161 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025162 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000025163 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025164 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000025165}
25166
Daniel Veillardcdc82732005-07-08 15:04:06 +000025167
25168/************************************************************************
25169 * *
25170 * Function and data for SAX streaming API *
25171 * *
25172 ************************************************************************/
25173typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
25174typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
25175
25176struct _xmlSchemaSplitSAXData {
25177 xmlSAXHandlerPtr user_sax;
25178 void *user_data;
25179 xmlSchemaValidCtxtPtr ctxt;
25180 xmlSAXHandlerPtr schemas_sax;
25181};
25182
Daniel Veillard971771e2005-07-09 17:32:57 +000025183#define XML_SAX_PLUG_MAGIC 0xdc43ba21
25184
25185struct _xmlSchemaSAXPlug {
25186 unsigned int magic;
25187
25188 /* the original callbacks informations */
25189 xmlSAXHandlerPtr *user_sax_ptr;
25190 xmlSAXHandlerPtr user_sax;
25191 void **user_data_ptr;
25192 void *user_data;
25193
25194 /* the block plugged back and validation informations */
25195 xmlSAXHandler schemas_sax;
25196 xmlSchemaValidCtxtPtr ctxt;
25197};
25198
Daniel Veillardcdc82732005-07-08 15:04:06 +000025199/* All those functions just bounces to the user provided SAX handlers */
25200static void
25201internalSubsetSplit(void *ctx, const xmlChar *name,
25202 const xmlChar *ExternalID, const xmlChar *SystemID)
25203{
Daniel Veillard971771e2005-07-09 17:32:57 +000025204 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025205 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25206 (ctxt->user_sax->internalSubset != NULL))
25207 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
25208 SystemID);
25209}
25210
25211static int
25212isStandaloneSplit(void *ctx)
25213{
Daniel Veillard971771e2005-07-09 17:32:57 +000025214 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025215 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25216 (ctxt->user_sax->isStandalone != NULL))
25217 return(ctxt->user_sax->isStandalone(ctxt->user_data));
25218 return(0);
25219}
25220
25221static int
25222hasInternalSubsetSplit(void *ctx)
25223{
Daniel Veillard971771e2005-07-09 17:32:57 +000025224 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025225 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25226 (ctxt->user_sax->hasInternalSubset != NULL))
25227 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
25228 return(0);
25229}
25230
25231static int
25232hasExternalSubsetSplit(void *ctx)
25233{
Daniel Veillard971771e2005-07-09 17:32:57 +000025234 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025235 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25236 (ctxt->user_sax->hasExternalSubset != NULL))
25237 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
25238 return(0);
25239}
25240
25241static void
25242externalSubsetSplit(void *ctx, const xmlChar *name,
25243 const xmlChar *ExternalID, const xmlChar *SystemID)
25244{
Daniel Veillard971771e2005-07-09 17:32:57 +000025245 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025246 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25247 (ctxt->user_sax->internalSubset != NULL))
25248 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
25249 SystemID);
25250}
25251
25252static xmlParserInputPtr
25253resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
25254{
Daniel Veillard971771e2005-07-09 17:32:57 +000025255 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025256 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25257 (ctxt->user_sax->resolveEntity != NULL))
25258 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
25259 systemId));
25260 return(NULL);
25261}
25262
25263static xmlEntityPtr
25264getEntitySplit(void *ctx, const xmlChar *name)
25265{
Daniel Veillard971771e2005-07-09 17:32:57 +000025266 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025267 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25268 (ctxt->user_sax->getEntity != NULL))
25269 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
25270 return(NULL);
25271}
25272
25273static xmlEntityPtr
25274getParameterEntitySplit(void *ctx, const xmlChar *name)
25275{
Daniel Veillard971771e2005-07-09 17:32:57 +000025276 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025277 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25278 (ctxt->user_sax->getParameterEntity != NULL))
25279 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
25280 return(NULL);
25281}
25282
25283
25284static void
25285entityDeclSplit(void *ctx, const xmlChar *name, int type,
25286 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
25287{
Daniel Veillard971771e2005-07-09 17:32:57 +000025288 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025289 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25290 (ctxt->user_sax->entityDecl != NULL))
25291 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
25292 systemId, content);
25293}
25294
25295static void
25296attributeDeclSplit(void *ctx, const xmlChar * elem,
25297 const xmlChar * name, int type, int def,
25298 const xmlChar * defaultValue, xmlEnumerationPtr tree)
25299{
Daniel Veillard971771e2005-07-09 17:32:57 +000025300 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025301 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25302 (ctxt->user_sax->attributeDecl != NULL)) {
25303 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
25304 def, defaultValue, tree);
25305 } else {
25306 xmlFreeEnumeration(tree);
25307 }
25308}
25309
25310static void
25311elementDeclSplit(void *ctx, const xmlChar *name, int type,
25312 xmlElementContentPtr content)
25313{
Daniel Veillard971771e2005-07-09 17:32:57 +000025314 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025315 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25316 (ctxt->user_sax->elementDecl != NULL))
25317 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
25318}
25319
25320static void
25321notationDeclSplit(void *ctx, const xmlChar *name,
25322 const xmlChar *publicId, const xmlChar *systemId)
25323{
Daniel Veillard971771e2005-07-09 17:32:57 +000025324 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025325 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25326 (ctxt->user_sax->notationDecl != NULL))
25327 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
25328 systemId);
25329}
25330
25331static void
25332unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
25333 const xmlChar *publicId, const xmlChar *systemId,
25334 const xmlChar *notationName)
25335{
Daniel Veillard971771e2005-07-09 17:32:57 +000025336 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025337 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25338 (ctxt->user_sax->unparsedEntityDecl != NULL))
25339 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
25340 systemId, notationName);
25341}
25342
25343static void
25344setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
25345{
Daniel Veillard971771e2005-07-09 17:32:57 +000025346 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025347 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25348 (ctxt->user_sax->setDocumentLocator != NULL))
25349 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
25350}
25351
25352static void
25353startDocumentSplit(void *ctx)
25354{
Daniel Veillard971771e2005-07-09 17:32:57 +000025355 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025356 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25357 (ctxt->user_sax->startDocument != NULL))
25358 ctxt->user_sax->startDocument(ctxt->user_data);
25359}
25360
25361static void
25362endDocumentSplit(void *ctx)
25363{
Daniel Veillard971771e2005-07-09 17:32:57 +000025364 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025365 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25366 (ctxt->user_sax->endDocument != NULL))
25367 ctxt->user_sax->endDocument(ctxt->user_data);
25368}
25369
25370static void
25371processingInstructionSplit(void *ctx, const xmlChar *target,
25372 const xmlChar *data)
25373{
Daniel Veillard971771e2005-07-09 17:32:57 +000025374 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025375 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25376 (ctxt->user_sax->processingInstruction != NULL))
25377 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
25378}
25379
25380static void
25381commentSplit(void *ctx, const xmlChar *value)
25382{
Daniel Veillard971771e2005-07-09 17:32:57 +000025383 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025384 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25385 (ctxt->user_sax->comment != NULL))
25386 ctxt->user_sax->comment(ctxt->user_data, value);
25387}
25388
25389/*
25390 * Varargs error callbacks to the user application, harder ...
25391 */
25392
Daniel Veillardffa3c742005-07-21 13:24:09 +000025393static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000025394warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000025395 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025396 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25397 (ctxt->user_sax->warning != NULL)) {
25398 TODO
25399 }
25400}
Daniel Veillardffa3c742005-07-21 13:24:09 +000025401static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000025402errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000025403 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025404 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25405 (ctxt->user_sax->error != NULL)) {
25406 TODO
25407 }
25408}
Daniel Veillardffa3c742005-07-21 13:24:09 +000025409static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000025410fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000025411 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025412 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25413 (ctxt->user_sax->fatalError != NULL)) {
25414 TODO
25415 }
25416}
25417
25418/*
25419 * Those are function where both the user handler and the schemas handler
25420 * need to be called.
25421 */
25422static void
25423charactersSplit(void *ctx, const xmlChar *ch, int len)
25424{
Daniel Veillard971771e2005-07-09 17:32:57 +000025425 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025426 if (ctxt == NULL)
25427 return;
25428 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
25429 ctxt->user_sax->characters(ctxt->user_data, ch, len);
25430 if (ctxt->ctxt != NULL)
25431 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
25432}
25433
25434static void
25435ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
25436{
Daniel Veillard971771e2005-07-09 17:32:57 +000025437 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025438 if (ctxt == NULL)
25439 return;
25440 if ((ctxt->user_sax != NULL) &&
25441 (ctxt->user_sax->ignorableWhitespace != NULL))
25442 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
25443 if (ctxt->ctxt != NULL)
25444 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
25445}
25446
25447static void
25448cdataBlockSplit(void *ctx, const xmlChar *value, int len)
25449{
Daniel Veillard971771e2005-07-09 17:32:57 +000025450 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025451 if (ctxt == NULL)
25452 return;
25453 if ((ctxt->user_sax != NULL) &&
25454 (ctxt->user_sax->ignorableWhitespace != NULL))
25455 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
25456 if (ctxt->ctxt != NULL)
25457 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
25458}
25459
25460static void
25461referenceSplit(void *ctx, const xmlChar *name)
25462{
Daniel Veillard971771e2005-07-09 17:32:57 +000025463 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025464 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
25465 (ctxt->user_sax->reference != NULL))
25466 ctxt->user_sax->reference(ctxt->user_data, name);
25467 if (ctxt->ctxt != NULL)
25468 xmlSchemaSAXHandleReference(ctxt->user_data, name);
25469}
25470
25471static void
25472startElementNsSplit(void *ctx, const xmlChar * localname,
25473 const xmlChar * prefix, const xmlChar * URI,
25474 int nb_namespaces, const xmlChar ** namespaces,
25475 int nb_attributes, int nb_defaulted,
25476 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000025477 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025478 if (ctxt == NULL)
25479 return;
25480 if ((ctxt->user_sax != NULL) &&
25481 (ctxt->user_sax->startElementNs != NULL))
25482 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
25483 URI, nb_namespaces, namespaces,
25484 nb_attributes, nb_defaulted,
25485 attributes);
25486 if (ctxt->ctxt != NULL)
25487 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
25488 URI, nb_namespaces, namespaces,
25489 nb_attributes, nb_defaulted,
25490 attributes);
25491}
25492
25493static void
25494endElementNsSplit(void *ctx, const xmlChar * localname,
25495 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000025496 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025497 if (ctxt == NULL)
25498 return;
25499 if ((ctxt->user_sax != NULL) &&
25500 (ctxt->user_sax->endElementNs != NULL))
25501 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
25502 if (ctxt->ctxt != NULL)
25503 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
25504}
25505
Daniel Veillard4255d502002-04-16 15:50:10 +000025506/**
Daniel Veillard971771e2005-07-09 17:32:57 +000025507 * xmlSchemaSAXPlug:
25508 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000025509 * @sax: a pointer to the original xmlSAXHandlerPtr
25510 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000025511 *
25512 * Plug a SAX based validation layer in a SAX parsing event flow.
25513 * The original @saxptr and @dataptr data are replaced by new pointers
25514 * but the calls to the original will be maintained.
25515 *
25516 * Returns a pointer to a data structure needed to unplug the validation layer
25517 * or NULL in case of errors.
25518 */
25519xmlSchemaSAXPlugPtr
25520xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
25521 xmlSAXHandlerPtr *sax, void **user_data)
25522{
25523 xmlSchemaSAXPlugPtr ret;
25524 xmlSAXHandlerPtr old_sax;
25525
25526 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
25527 return(NULL);
25528
25529 /*
25530 * We only allow to plug into SAX2 event streams
25531 */
25532 old_sax = *sax;
25533 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
25534 return(NULL);
25535 if ((old_sax != NULL) &&
25536 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
25537 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
25538 return(NULL);
25539
25540 /*
25541 * everything seems right allocate the local data needed for that layer
25542 */
25543 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
25544 if (ret == NULL) {
25545 return(NULL);
25546 }
25547 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
25548 ret->magic = XML_SAX_PLUG_MAGIC;
25549 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
25550 ret->ctxt = ctxt;
25551 ret->user_sax_ptr = sax;
25552 ret->user_sax = old_sax;
25553 if (old_sax == NULL) {
25554 /*
25555 * go direct, no need for the split block and functions.
25556 */
25557 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
25558 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
25559 /*
25560 * Note that we use the same text-function for both, to prevent
25561 * the parser from testing for ignorable whitespace.
25562 */
25563 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
25564 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
25565
25566 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
25567 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
25568
25569 ret->user_data = ctxt;
25570 *user_data = ctxt;
25571 } else {
25572 /*
25573 * for each callback unused by Schemas initialize it to the Split
25574 * routine only if non NULL in the user block, this can speed up
25575 * things at the SAX level.
25576 */
25577 if (old_sax->internalSubset != NULL)
25578 ret->schemas_sax.internalSubset = internalSubsetSplit;
25579 if (old_sax->isStandalone != NULL)
25580 ret->schemas_sax.isStandalone = isStandaloneSplit;
25581 if (old_sax->hasInternalSubset != NULL)
25582 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
25583 if (old_sax->hasExternalSubset != NULL)
25584 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
25585 if (old_sax->resolveEntity != NULL)
25586 ret->schemas_sax.resolveEntity = resolveEntitySplit;
25587 if (old_sax->getEntity != NULL)
25588 ret->schemas_sax.getEntity = getEntitySplit;
25589 if (old_sax->entityDecl != NULL)
25590 ret->schemas_sax.entityDecl = entityDeclSplit;
25591 if (old_sax->notationDecl != NULL)
25592 ret->schemas_sax.notationDecl = notationDeclSplit;
25593 if (old_sax->attributeDecl != NULL)
25594 ret->schemas_sax.attributeDecl = attributeDeclSplit;
25595 if (old_sax->elementDecl != NULL)
25596 ret->schemas_sax.elementDecl = elementDeclSplit;
25597 if (old_sax->unparsedEntityDecl != NULL)
25598 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
25599 if (old_sax->setDocumentLocator != NULL)
25600 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
25601 if (old_sax->startDocument != NULL)
25602 ret->schemas_sax.startDocument = startDocumentSplit;
25603 if (old_sax->endDocument != NULL)
25604 ret->schemas_sax.endDocument = endDocumentSplit;
25605 if (old_sax->processingInstruction != NULL)
25606 ret->schemas_sax.processingInstruction = processingInstructionSplit;
25607 if (old_sax->comment != NULL)
25608 ret->schemas_sax.comment = commentSplit;
25609 if (old_sax->warning != NULL)
25610 ret->schemas_sax.warning = warningSplit;
25611 if (old_sax->error != NULL)
25612 ret->schemas_sax.error = errorSplit;
25613 if (old_sax->fatalError != NULL)
25614 ret->schemas_sax.fatalError = fatalErrorSplit;
25615 if (old_sax->getParameterEntity != NULL)
25616 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
25617 if (old_sax->externalSubset != NULL)
25618 ret->schemas_sax.externalSubset = externalSubsetSplit;
25619
25620 /*
25621 * the 6 schemas callback have to go to the splitter functions
25622 * Note that we use the same text-function for ignorableWhitespace
25623 * if possible, to prevent the parser from testing for ignorable
25624 * whitespace.
25625 */
25626 ret->schemas_sax.characters = charactersSplit;
25627 if ((old_sax->ignorableWhitespace != NULL) &&
25628 (old_sax->ignorableWhitespace != old_sax->characters))
25629 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
25630 else
25631 ret->schemas_sax.ignorableWhitespace = charactersSplit;
25632 ret->schemas_sax.cdataBlock = cdataBlockSplit;
25633 ret->schemas_sax.reference = referenceSplit;
25634 ret->schemas_sax.startElementNs = startElementNsSplit;
25635 ret->schemas_sax.endElementNs = endElementNsSplit;
25636
25637 ret->user_data_ptr = user_data;
25638 ret->user_data = *user_data;
25639 *user_data = ret;
25640 }
25641
25642 /*
25643 * plug the pointers back.
25644 */
25645 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000025646 ctxt->sax = *sax;
25647 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
25648 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000025649 return(ret);
25650}
25651
25652/**
25653 * xmlSchemaSAXUnplug:
25654 * @plug: a data structure returned by xmlSchemaSAXPlug
25655 *
25656 * Unplug a SAX based validation layer in a SAX parsing event flow.
25657 * The original pointers used in the call are restored.
25658 *
25659 * Returns 0 in case of success and -1 in case of failure.
25660 */
25661int
25662xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
25663{
25664 xmlSAXHandlerPtr *sax;
25665 void **user_data;
25666
25667 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
25668 return(-1);
25669 plug->magic = 0;
25670
Daniel Veillardf10ae122005-07-10 19:03:16 +000025671 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000025672 /* restore the data */
25673 sax = plug->user_sax_ptr;
25674 *sax = plug->user_sax;
25675 if (plug->user_sax != NULL) {
25676 user_data = plug->user_data_ptr;
25677 *user_data = plug->user_data;
25678 }
25679
25680 /* free and return */
25681 xmlFree(plug);
25682 return(0);
25683}
25684
25685/**
Daniel Veillard4255d502002-04-16 15:50:10 +000025686 * xmlSchemaValidateStream:
25687 * @ctxt: a schema validation context
25688 * @input: the input to use for reading the data
25689 * @enc: an optional encoding information
25690 * @sax: a SAX handler for the resulting events
25691 * @user_data: the context to provide to the SAX handler.
25692 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000025693 * Validate an input based on a flow of SAX event from the parser
25694 * and forward the events to the @sax handler with the provided @user_data
25695 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000025696 *
25697 * Returns 0 if the document is schemas valid, a positive error code
25698 * number otherwise and -1 in case of internal or API error.
25699 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000025700int
Daniel Veillard4255d502002-04-16 15:50:10 +000025701xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000025702 xmlParserInputBufferPtr input, xmlCharEncoding enc,
25703 xmlSAXHandlerPtr sax, void *user_data)
25704{
Daniel Veillard971771e2005-07-09 17:32:57 +000025705 xmlSchemaSAXPlugPtr plug = NULL;
25706 xmlSAXHandlerPtr old_sax = NULL;
25707 xmlParserCtxtPtr pctxt = NULL;
25708 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025709 int ret;
25710
Daniel Veillard4255d502002-04-16 15:50:10 +000025711 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000025712 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000025713
Daniel Veillardcdc82732005-07-08 15:04:06 +000025714 /*
25715 * prepare the parser
25716 */
25717 pctxt = xmlNewParserCtxt();
25718 if (pctxt == NULL)
25719 return (-1);
25720 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000025721 pctxt->sax = sax;
25722 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025723#if 0
25724 if (options)
25725 xmlCtxtUseOptions(pctxt, options);
25726#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000025727 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025728
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000025729 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025730 if (inputStream == NULL) {
25731 ret = -1;
25732 goto done;
25733 }
25734 inputPush(pctxt, inputStream);
25735 ctxt->parserCtxt = pctxt;
25736 ctxt->input = input;
25737
25738 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000025739 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000025740 */
Daniel Veillard971771e2005-07-09 17:32:57 +000025741 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
25742 if (plug == NULL) {
25743 ret = -1;
25744 goto done;
25745 }
25746 ctxt->input = input;
25747 ctxt->enc = enc;
25748 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025749 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
25750 ret = xmlSchemaVStart(ctxt);
25751
25752 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
25753 ret = ctxt->parserCtxt->errNo;
25754 if (ret == 0)
25755 ret = 1;
25756 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000025757
25758done:
Daniel Veillard971771e2005-07-09 17:32:57 +000025759 ctxt->parserCtxt = NULL;
25760 ctxt->sax = NULL;
25761 ctxt->input = NULL;
25762 if (plug != NULL) {
25763 xmlSchemaSAXUnplug(plug);
25764 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000025765 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000025766 if (pctxt != NULL) {
25767 pctxt->sax = old_sax;
25768 xmlFreeParserCtxt(pctxt);
25769 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000025770 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000025771}
25772
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025773/**
25774 * xmlSchemaValidateFile:
25775 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000025776 * @filename: the URI of the instance
25777 * @options: a future set of options, currently unused
25778 *
25779 * Do a schemas validation of the given resource, it will use the
25780 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025781 *
25782 * Returns 0 if the document is valid, a positive error code
25783 * number otherwise and -1 in case of an internal or API error.
25784 */
25785int
25786xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000025787 const char * filename,
25788 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025789{
25790 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000025791 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025792
25793 if ((ctxt == NULL) || (filename == NULL))
25794 return (-1);
25795
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000025796 input = xmlParserInputBufferCreateFilename(filename,
25797 XML_CHAR_ENCODING_NONE);
25798 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025799 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000025800 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
25801 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025802 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000025803}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025804
Daniel Veillard5d4644e2005-04-01 13:11:58 +000025805#define bottom_xmlschemas
25806#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000025807#endif /* LIBXML_SCHEMAS_ENABLED */