blob: 4cd009b3b12daa67ce36d0b23d4bcce2e44c7739 [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. Buchcikaba15f72005-04-01 15:17:27 +000069#define DUMP_CONTENT_MODEL
70
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000071#define XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000072
73#ifdef LIBXML_READER_ENABLED
74/* #define XML_SCHEMA_READER_ENABLED */
75#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000076
Daniel Veillard4255d502002-04-16 15:50:10 +000077#define UNBOUNDED (1 << 30)
78#define TODO \
79 xmlGenericError(xmlGenericErrorContext, \
80 "Unimplemented block at %s:%d\n", \
81 __FILE__, __LINE__);
82
William M. Brack2f2a6632004-08-20 23:09:47 +000083#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000084
Daniel Veillard4255d502002-04-16 15:50:10 +000085/*
86 * The XML Schemas namespaces
87 */
88static const xmlChar *xmlSchemaNs = (const xmlChar *)
89 "http://www.w3.org/2001/XMLSchema";
90
91static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
92 "http://www.w3.org/2001/XMLSchema-instance";
93
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000094static const xmlChar *xmlNamespaceNs = (const xmlChar *)
95 "http://www.w3.org/2000/xmlns/";
96
Daniel Veillardc0826a72004-08-10 14:17:33 +000097static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000098 "element decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +000099static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000100 "attribute decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000101static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000102 "attribute use";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000103static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000104 "model group";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000105#if 0
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000106static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000107 "model group ref.";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000108#endif
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
142#define HAS_COMPLEX_CONTENT(item) \
143 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
144 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
145 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
146
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000147#define HAS_SIMPLE_CONTENT(item) \
148 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
149 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
150
151#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
152
153#define IS_PARTICLE_EMPTIABLE(item) \
154 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
155
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000156#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
157
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000158#define GET_LIST_ITEM_TYPE(item) item->subtypes
159
160#define VARIETY_ATOMIC(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
161#define VARIETY_LIST(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
162#define VARIETY_UNION(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
163
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000164#define IS_MODEL_GROUP(item) \
165 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
166 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
167 (item->type == XML_SCHEMA_TYPE_ALL))
168
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000169#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
170
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000171#define ELEM_TYPE(item) item->subtypes
172
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000173#define GET_PARTICLE(item) (xmlSchemaParticlePtr) item->subtypes;
174
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000175#define SUBST_GROUP_AFF(item) item->refDecl
176
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000177#if 0
178#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
179#endif
180
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000181#define SUBSET_RESTRICTION 1<<0
182#define SUBSET_EXTENSION 1<<1
183#define SUBSET_SUBSTITUTION 1<<2
184#define SUBSET_LIST 1<<3
185#define SUBSET_UNION 1<<4
186
Daniel Veillard4255d502002-04-16 15:50:10 +0000187#define XML_SCHEMAS_PARSE_ERROR 1
188
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000189#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
190
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000191typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
192typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000193
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000194
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000195typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000196typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000197
198typedef struct _xmlSchemaItemList xmlSchemaItemList;
199typedef xmlSchemaItemList *xmlSchemaItemListPtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000200struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000201 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000202 int nbItems; /* used for dynamic addition of schemata */
203 int sizeItems; /* used for dynamic addition of schemata */
204};
205
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000206/*
207typedef struct _xmlSchemaItemListChain xmlSchemaItemListChain;
208typedef xmlSchemaItemListChain xmlSchemaItemListChainPtr;
209struct _xmlSchemaItemListChain {
210 xmlSchemaItemListChainPtr next;
211 xmlSchemaItemListPtr list;
212}
213*/
214
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000215typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
216typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
217struct _xmlSchemaAbstractCtxt {
218 int type;
219};
220
221#define XML_SCHEMA_CTXT_PARSER 1
222#define XML_SCHEMA_CTXT_VALIDATOR 2
223
Daniel Veillard4255d502002-04-16 15:50:10 +0000224struct _xmlSchemaParserCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000225 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000226 void *userData; /* user specific data block */
227 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
228 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000229 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000230 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000231 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000232
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000233 xmlSchemaPtr topschema; /* The main schema */
234 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
235
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000236 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000237 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000238 int counter;
239
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000240 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000241 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000242 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000243
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000244 const char *buffer;
245 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000246
Daniel Veillard4255d502002-04-16 15:50:10 +0000247 /*
248 * Used to build complex element content models
249 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000250 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000251 xmlAutomataStatePtr start;
252 xmlAutomataStatePtr end;
253 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000254
255 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000256 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000257 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
258 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000259 xmlSchemaAssemblePtr assemble;
260 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000261 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000262 const xmlChar **localImports; /* list of locally imported namespaces */
263 int sizeLocalImports;
264 int nbLocalImports;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000265 xmlHashTablePtr substGroups;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +0000266 int isS4S;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000267 int isRedefine;
Daniel Veillard4255d502002-04-16 15:50:10 +0000268};
269
Daniel Veillard4255d502002-04-16 15:50:10 +0000270#define XML_SCHEMAS_ATTR_UNKNOWN 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000271#define XML_SCHEMAS_ATTR_ASSESSED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000272#define XML_SCHEMAS_ATTR_PROHIBITED 3
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000273#define XML_SCHEMAS_ATTR_ERR_MISSING 4
Daniel Veillard3646d642004-06-02 19:19:14 +0000274#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000275#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
276#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000277#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000278#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000279#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
280#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
281#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
282#define XML_SCHEMAS_ATTR_WILD_SKIP 13
283#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
284#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
285#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
286#define XML_SCHEMAS_ATTR_META 17
Daniel Veillard4255d502002-04-16 15:50:10 +0000287
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000288/**
289 * xmlSchemaBasicItem:
290 *
291 * The abstract base type for schema components.
292 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000293typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
294typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
295struct _xmlSchemaBasicItem {
296 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000297};
298
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000299#define XML_SCHEMA_SCHEMA_REF_IMPORT 1
300#define XML_SCHEMA_SCHEMA_REF_INCLUDE 2
301#define XML_SCHEMA_SCHEMA_REF_REDEFINE 3
302/**
303 * xmlSchemaSchemaRef:
304 *
305 * Used to create a graph of schema relationships.
306 */
307typedef struct _xmlSchemaSchemaRef xmlSchemaSchemaRef;
308typedef xmlSchemaSchemaRef *xmlSchemaSchemaRefPtr;
309struct _xmlSchemaSchemaRef {
310 int type; /* E.g. XML_SCHEMA_SCHEMA_REF_IMPORT */
311 xmlSchemaSchemaRefPtr next;
312 xmlSchemaSchemaRefPtr children;
313};
314
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000315/**
316 * xmlSchemaAnnotItem:
317 *
318 * The abstract base type for annotated schema components.
319 * (Extends xmlSchemaBasicItem)
320 */
321typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
322typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
323struct _xmlSchemaAnnotItem {
324 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000325 xmlSchemaAnnotPtr annot;
326};
327
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000328/**
329 * xmlSchemaTreeItem:
330 *
331 * The abstract base type for tree-like structured schema components.
332 * (Extends xmlSchemaAnnotItem)
333 */
334typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
335typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
336struct _xmlSchemaTreeItem {
337 xmlSchemaTypeType type;
338 xmlSchemaAnnotPtr annot;
339 xmlSchemaTreeItemPtr next;
340 xmlSchemaTreeItemPtr children;
341};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000342
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000343/**
344 * xmlSchemaQNameRef:
345 *
346 * A component reference item (not a schema component)
347 * (Extends xmlSchemaBasicItem)
348 */
349typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
350typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
351struct _xmlSchemaQNameRef {
352 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000353 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000354 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000355 const xmlChar *name;
356 const xmlChar *targetNamespace;
357};
358
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000359/**
360 * xmlSchemaParticle:
361 *
362 * A particle component.
363 * (Extends xmlSchemaTreeItem)
364 */
365typedef struct _xmlSchemaParticle xmlSchemaParticle;
366typedef xmlSchemaParticle *xmlSchemaParticlePtr;
367struct _xmlSchemaParticle {
368 xmlSchemaTypeType type;
369 xmlSchemaAnnotPtr annot;
370 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
371 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
372 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000373 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000374 xmlNodePtr node;
375};
376
377/**
378 * xmlSchemaModelGroup:
379 *
380 * A model group component.
381 * (Extends xmlSchemaTreeItem)
382 */
383typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
384typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
385struct _xmlSchemaModelGroup {
386 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
387 xmlSchemaAnnotPtr annot;
388 xmlSchemaTreeItemPtr next; /* not used */
389 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
390 xmlNodePtr node;
391};
392
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000393#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000394/**
395 * xmlSchemaModelGroupDef:
396 *
397 * A model group definition component.
398 * (Extends xmlSchemaTreeItem)
399 */
400typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
401typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
402struct _xmlSchemaModelGroupDef {
403 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
404 xmlSchemaAnnotPtr annot;
405 xmlSchemaTreeItemPtr next; /* not used */
406 xmlSchemaTreeItemPtr children; /* the "model group" */
407 const xmlChar *name;
408 const xmlChar *targetNamespace;
409 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000410 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000411};
412
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000413typedef struct _xmlSchemaIDC xmlSchemaIDC;
414typedef xmlSchemaIDC *xmlSchemaIDCPtr;
415
416/**
417 * xmlSchemaIDCSelect:
418 *
419 * The identity-constraint "field" and "selector" item, holding the
420 * XPath expression.
421 */
422typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
423typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000424struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000425 xmlSchemaIDCSelectPtr next;
426 xmlSchemaIDCPtr idc;
427 int index; /* an index position if significant for IDC key-sequences */
428 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000429 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000430};
431
432/**
433 * xmlSchemaIDC:
434 *
435 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000436 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000437 */
438
439struct _xmlSchemaIDC {
440 xmlSchemaTypeType type;
441 xmlSchemaAnnotPtr annot;
442 xmlSchemaIDCPtr next;
443 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000444 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000445 const xmlChar *targetNamespace;
446 xmlSchemaIDCSelectPtr selector;
447 xmlSchemaIDCSelectPtr fields;
448 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000449 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000450};
451
452/**
453 * xmlSchemaIDCAug:
454 *
455 * The augmented IDC information used for validation.
456 */
457typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
458typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
459struct _xmlSchemaIDCAug {
460 xmlSchemaIDCAugPtr next; /* next in a list */
461 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000462 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000463 tables need to be bubbled upwards */
464};
465
466/**
467 * xmlSchemaPSVIIDCKeySequence:
468 *
469 * The key sequence of a node table item.
470 */
471typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
472typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
473struct _xmlSchemaPSVIIDCKey {
474 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000475 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000476};
477
478/**
479 * xmlSchemaPSVIIDCNode:
480 *
481 * The node table item of a node table.
482 */
483typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
484typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
485struct _xmlSchemaPSVIIDCNode {
486 xmlNodePtr node;
487 xmlSchemaPSVIIDCKeyPtr *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000488 int nodeLine;
489 int nodeQNameID;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000490};
491
492/**
493 * xmlSchemaPSVIIDCBinding:
494 *
495 * The identity-constraint binding item of the [identity-constraint table].
496 */
497typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
498typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
499struct _xmlSchemaPSVIIDCBinding {
500 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
501 xmlSchemaIDCPtr definition; /* the IDC definition */
502 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
503 int nbNodes; /* number of entries in the node table */
504 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000505 int nbDupls; /* number of already identified duplicates in the node
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000506 table */
507 /* int nbKeys; number of keys in each key-sequence */
508};
509
510#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
511#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
512
513#define XPATH_STATE_OBJ_MATCHES -2
514#define XPATH_STATE_OBJ_BLOCKED -3
515
516typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
517typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
518
519/**
520 * xmlSchemaIDCStateObj:
521 *
522 * The state object used to evaluate XPath expressions.
523 */
524typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
525typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
526struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000527 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000528 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000529 int depth; /* depth of creation */
530 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000531 int nbHistory;
532 int sizeHistory;
533 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
534 matcher */
535 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000536 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000537};
538
539#define IDC_MATCHER 0
540
541/**
542 * xmlSchemaIDCMatcher:
543 *
544 * Used to IDC selectors (and fields) successively.
545 */
546struct _xmlSchemaIDCMatcher {
547 int type;
548 int depth; /* the tree depth at creation time */
549 xmlSchemaIDCMatcherPtr next; /* next in the list */
550 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
551 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
552 elements */
553 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000554 int targetDepth;
555};
556
557/*
558* Element info flags.
559*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000560#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
561#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
562#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
563#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
564
565#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
566#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
567#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
568
569#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
570#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
571#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
572#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000573
574/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000575 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000576 *
577 * Holds information of an element node.
578 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000579struct _xmlSchemaNodeInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000580 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000581 xmlNodePtr node;
582 int nodeLine;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000583 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000584 const xmlChar *nsName;
585 const xmlChar *value;
586 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000587 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000588 int flags; /* combination of node info flags */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000589
590
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000591 int valNeeded;
592 int normVal;
593
594 xmlSchemaElementPtr decl; /* the element/attribute declaration */
595 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000596 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
597 for the scope element*/
598 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
599 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000600 xmlRegExecCtxtPtr regexCtxt;
601
602 const xmlChar **nsBindings; /* Namespace bindings on this element */
603 int nbNsBindings;
604 int sizeNsBindings;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000605};
606
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000607/*
608* @metaType values of xmlSchemaAttrInfo.
609*/
610#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
611#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
612#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
613#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
614#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000615
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000616typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
617typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
618struct _xmlSchemaAttrInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000619 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000620 xmlNodePtr node;
621 int nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000622 const xmlChar *localName;
623 const xmlChar *nsName;
624 const xmlChar *value;
625 xmlSchemaValPtr val; /* the pre-computed value if any */
626 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
627 int flags; /* combination of node info flags */
628
629 xmlSchemaAttributePtr decl; /* the attribute declaration */
630 xmlSchemaAttributePtr use; /* the attribute use */
631 int state;
632 int metaType;
633 const xmlChar *vcValue; /* the value constraint value */
634 xmlSchemaNodeInfoPtr parent;
635};
636
637
638#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000639/**
640 * xmlSchemaValidCtxt:
641 *
642 * A Schemas validation context
643 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000644struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000645 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000646 void *userData; /* user specific data block */
647 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000648 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000649 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000650
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000651 xmlSchemaPtr schema; /* The schema in use */
652 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000653 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000654 xmlCharEncoding enc;
655 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000656 xmlParserCtxtPtr parserCtxt;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000657 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000658
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000659 int err;
660 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000661
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000662 xmlNodePtr node;
663 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000664 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000665
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000666 xmlRegExecCtxtPtr regexp;
667 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000668
Daniel Veillardc0826a72004-08-10 14:17:33 +0000669 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000670 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000671 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000672 xmlSchemaParserCtxtPtr pctxt;
673 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000674
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000675 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000676 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000677 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000678 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000679
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000680 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
681
682 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
683 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000684
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000685 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
686 int nbIdcNodes;
687 int sizeIdcNodes;
688
689 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
690 int nbIdcKeys;
691 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000692
693 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000694
695 xmlDictPtr dict;
696
Daniel Veillard39e5c892005-07-03 22:48:50 +0000697#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000698 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +0000699#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000700
701 xmlSchemaAttrInfoPtr *attrInfos;
702 int nbAttrInfos;
703 int sizeAttrInfos;
704
705 int skipDepth;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000706 xmlSchemaItemListPtr nodeQNames;
Daniel Veillard4255d502002-04-16 15:50:10 +0000707};
708
Daniel Veillard1d913862003-11-21 00:28:39 +0000709/*
710 * These are the entries in the schemas importSchemas hash table
711 */
712typedef struct _xmlSchemaImport xmlSchemaImport;
713typedef xmlSchemaImport *xmlSchemaImportPtr;
714struct _xmlSchemaImport {
715 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000716 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000717 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000718 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000719};
Daniel Veillard4255d502002-04-16 15:50:10 +0000720
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000721/*
722 * These are the entries associated to includes in a schemas
723 */
724typedef struct _xmlSchemaInclude xmlSchemaInclude;
725typedef xmlSchemaInclude *xmlSchemaIncludePtr;
726struct _xmlSchemaInclude {
727 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000728 const xmlChar *schemaLocation;
729 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000730 const xmlChar *origTargetNamespace;
731 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000732};
733
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000734/**
735 * xmlSchemaSubstGroup:
736 *
737 *
738 */
739typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
740typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
741struct _xmlSchemaSubstGroup {
742 xmlSchemaElementPtr head;
743 xmlSchemaItemListPtr members;
744};
745
Daniel Veillard4255d502002-04-16 15:50:10 +0000746/************************************************************************
747 * *
748 * Some predeclarations *
749 * *
750 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000751
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000752static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
753 xmlSchemaPtr schema,
754 xmlNodePtr node);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000755#if 0
756static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
757 xmlSchemaPtr schema,
758 xmlNodePtr node);
759#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +0000760static void
761xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
762 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000763static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000764xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
765static int
William M. Brack2f2a6632004-08-20 23:09:47 +0000766xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
767 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000768static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000769xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
770 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000771static void
772xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000773static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000774xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000775static xmlSchemaTreeItemPtr
776xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
777 xmlNodePtr node, xmlSchemaTypeType type,
778 int withParticle);
779static const xmlChar *
780xmlSchemaCompTypeToString(xmlSchemaTypeType type);
781static xmlSchemaTypeLinkPtr
782xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000783static void
784xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
785 const char *funcName,
786 const char *message);
787static int
788xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
789 xmlSchemaTypePtr baseType,
790 int subset);
791static void
792xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
793 xmlSchemaParserCtxtPtr ctxt,
794 const xmlChar * name ATTRIBUTE_UNUSED);
William M. Brack87640d52004-04-17 14:58:15 +0000795
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000796/************************************************************************
797 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000798 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000799 * *
800 ************************************************************************/
801
802/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000803 * xmlSchemaCompTypeToString:
804 * @type: the type of the schema item
805 *
806 * Returns the component name of a schema item.
807 */
808static const xmlChar *
809xmlSchemaCompTypeToString(xmlSchemaTypeType type)
810{
811 switch (type) {
812 case XML_SCHEMA_TYPE_SIMPLE:
813 return(BAD_CAST "simple type definition");
814 case XML_SCHEMA_TYPE_COMPLEX:
815 return(BAD_CAST "complex type definition");
816 case XML_SCHEMA_TYPE_ELEMENT:
817 return(BAD_CAST "element declaration");
818 case XML_SCHEMA_TYPE_ATTRIBUTE:
819 return(BAD_CAST "attribute declaration");
820 case XML_SCHEMA_TYPE_GROUP:
821 return(BAD_CAST "model group definition");
822 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
823 return(BAD_CAST "attribute group definition");
824 case XML_SCHEMA_TYPE_NOTATION:
825 return(BAD_CAST "notation declaration");
826 case XML_SCHEMA_TYPE_SEQUENCE:
827 return(BAD_CAST "model group (sequence)");
828 case XML_SCHEMA_TYPE_CHOICE:
829 return(BAD_CAST "model group (choice)");
830 case XML_SCHEMA_TYPE_ALL:
831 return(BAD_CAST "model group (all)");
832 case XML_SCHEMA_TYPE_PARTICLE:
833 return(BAD_CAST "particle");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +0000834 case XML_SCHEMA_TYPE_IDC_UNIQUE:
835 return(BAD_CAST "IDC (unique)");
836 case XML_SCHEMA_TYPE_IDC_KEY:
837 return(BAD_CAST "IDC (key)");
838 case XML_SCHEMA_TYPE_IDC_KEYREF:
839 return(BAD_CAST "IDC (keyref)");
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +0000840 case XML_SCHEMA_TYPE_ANY:
841 return(BAD_CAST "wildcard (any)");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +0000842 case XML_SCHEMA_EXTRA_QNAMEREF:
843 return(BAD_CAST "[helper component] QName reference");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000844 default:
845 return(BAD_CAST "Not a schema component");
846 }
847}
848
849/**
850 * xmlSchemaGetComponentNode:
851 * @item: a schema component
852 *
853 * Returns node associated with the schema component.
854 * NOTE that such a node need not be available; plus, a component's
855 * node need not to reflect the component directly, since there is no
856 * one-to-one relationship between the XML Schema representation and
857 * the component representation.
858 */
859static xmlNodePtr
860xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
861{
862 switch (item->type) {
863 case XML_SCHEMA_TYPE_ELEMENT:
864 return (((xmlSchemaElementPtr) item)->node);
865 case XML_SCHEMA_TYPE_ATTRIBUTE:
866 return (((xmlSchemaAttributePtr) item)->node);
867 case XML_SCHEMA_TYPE_COMPLEX:
868 case XML_SCHEMA_TYPE_SIMPLE:
869 return (((xmlSchemaTypePtr) item)->node);
870 case XML_SCHEMA_TYPE_ANY:
871 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
872 return (((xmlSchemaWildcardPtr) item)->node);
873 case XML_SCHEMA_TYPE_PARTICLE:
874 return (((xmlSchemaParticlePtr) item)->node);
875 case XML_SCHEMA_TYPE_SEQUENCE:
876 case XML_SCHEMA_TYPE_CHOICE:
877 case XML_SCHEMA_TYPE_ALL:
878 return (((xmlSchemaModelGroupPtr) item)->node);
879 case XML_SCHEMA_TYPE_GROUP:
880 return (((xmlSchemaModelGroupDefPtr) item)->node);
881 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
882 return (((xmlSchemaAttributeGroupPtr) item)->node);
883 case XML_SCHEMA_TYPE_IDC_UNIQUE:
884 case XML_SCHEMA_TYPE_IDC_KEY:
885 case XML_SCHEMA_TYPE_IDC_KEYREF:
886 return (((xmlSchemaIDCPtr) item)->node);
887 default:
888 return (NULL);
889 }
890}
891
892#if 0
893/**
894 * xmlSchemaGetNextComponent:
895 * @item: a schema component
896 *
897 * Returns the next sibling of the schema component.
898 */
899static xmlSchemaBasicItemPtr
900xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
901{
902 switch (item->type) {
903 case XML_SCHEMA_TYPE_ELEMENT:
904 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
905 case XML_SCHEMA_TYPE_ATTRIBUTE:
906 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
907 case XML_SCHEMA_TYPE_COMPLEX:
908 case XML_SCHEMA_TYPE_SIMPLE:
909 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
910 case XML_SCHEMA_TYPE_ANY:
911 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
912 return (NULL);
913 case XML_SCHEMA_TYPE_PARTICLE:
914 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
915 case XML_SCHEMA_TYPE_SEQUENCE:
916 case XML_SCHEMA_TYPE_CHOICE:
917 case XML_SCHEMA_TYPE_ALL:
918 return (NULL);
919 case XML_SCHEMA_TYPE_GROUP:
920 return (NULL);
921 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
922 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
923 case XML_SCHEMA_TYPE_IDC_UNIQUE:
924 case XML_SCHEMA_TYPE_IDC_KEY:
925 case XML_SCHEMA_TYPE_IDC_KEYREF:
926 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
927 default:
928 return (NULL);
929 }
930}
931#endif
932
933/**
934 * xmlSchemaGetAttrName:
935 * @attr: the attribute declaration/use
936 *
937 * Returns the name of the attribute; if the attribute
938 * is a reference, the name of the referenced global type will be returned.
939 */
940static const xmlChar *
941xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
942{
943 if (attr->ref != NULL)
944 return(attr->ref);
945 else
946 return(attr->name);
947}
948
949/**
950 * xmlSchemaGetAttrTargetNsURI:
951 * @type: the type (element or attribute)
952 *
953 * Returns the target namespace URI of the type; if the type is a reference,
954 * the target namespace of the referenced type will be returned.
955 */
956static const xmlChar *
957xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
958{
959 if (attr->ref != NULL)
960 return (attr->refNs);
961 else
962 return(attr->targetNamespace);
963}
964
965/**
966 * xmlSchemaFormatQName:
967 * @buf: the string buffer
968 * @namespaceName: the namespace name
969 * @localName: the local name
970 *
971 * Returns the given QName in the format "{namespaceName}localName" or
972 * just "localName" if @namespaceName is NULL.
973 *
974 * Returns the localName if @namespaceName is NULL, a formatted
975 * string otherwise.
976 */
977static const xmlChar*
978xmlSchemaFormatQName(xmlChar **buf,
979 const xmlChar *namespaceName,
980 const xmlChar *localName)
981{
982 FREE_AND_NULL(*buf)
983 if (namespaceName == NULL)
984 return(localName);
985
986 *buf = xmlStrdup(BAD_CAST "{");
987 *buf = xmlStrcat(*buf, namespaceName);
988 *buf = xmlStrcat(*buf, BAD_CAST "}");
989 *buf = xmlStrcat(*buf, localName);
990
991 return ((const xmlChar *) *buf);
992}
993
994static const xmlChar*
995xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
996{
997 if (ns != NULL)
998 return (xmlSchemaFormatQName(buf, ns->href, localName));
999 else
1000 return (xmlSchemaFormatQName(buf, NULL, localName));
1001}
1002
1003static const xmlChar *
1004xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1005{
1006 switch (item->type) {
1007 case XML_SCHEMA_TYPE_ELEMENT:
1008 return (((xmlSchemaElementPtr) item)->name);
1009 case XML_SCHEMA_TYPE_ATTRIBUTE:
1010 return (((xmlSchemaAttributePtr) item)->name);
1011 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1012 return (((xmlSchemaAttributeGroupPtr) item)->name);
1013 case XML_SCHEMA_TYPE_BASIC:
1014 case XML_SCHEMA_TYPE_SIMPLE:
1015 case XML_SCHEMA_TYPE_COMPLEX:
1016 return (((xmlSchemaTypePtr) item)->name);
1017 case XML_SCHEMA_TYPE_GROUP:
1018 return (((xmlSchemaModelGroupDefPtr) item)->name);
1019 case XML_SCHEMA_TYPE_IDC_KEY:
1020 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1021 case XML_SCHEMA_TYPE_IDC_KEYREF:
1022 return (((xmlSchemaIDCPtr) item)->name);
1023 default:
1024 /*
1025 * Other components cannot have names.
1026 */
1027 break;
1028 }
1029 return (NULL);
1030}
1031
1032static const xmlChar *
1033xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1034{
1035 switch (item->type) {
1036 case XML_SCHEMA_TYPE_ELEMENT:
1037 return (((xmlSchemaElementPtr) item)->targetNamespace);
1038 case XML_SCHEMA_TYPE_ATTRIBUTE:
1039 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1040 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1041 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1042 case XML_SCHEMA_TYPE_BASIC:
1043 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1044 case XML_SCHEMA_TYPE_SIMPLE:
1045 case XML_SCHEMA_TYPE_COMPLEX:
1046 return (((xmlSchemaTypePtr) item)->targetNamespace);
1047 case XML_SCHEMA_TYPE_GROUP:
1048 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1049 case XML_SCHEMA_TYPE_IDC_KEY:
1050 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1051 case XML_SCHEMA_TYPE_IDC_KEYREF:
1052 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1053 default:
1054 /*
1055 * Other components cannot have names.
1056 */
1057 break;
1058 }
1059 return (NULL);
1060}
1061
1062static const xmlChar*
1063xmlSchemaGetComponentQName(xmlChar **buf,
1064 void *item)
1065{
1066 return (xmlSchemaFormatQName(buf,
1067 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1068 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1069}
1070
1071/**
1072 * xmlSchemaWildcardPCToString:
1073 * @pc: the type of processContents
1074 *
1075 * Returns a string representation of the type of
1076 * processContents.
1077 */
1078static const xmlChar *
1079xmlSchemaWildcardPCToString(int pc)
1080{
1081 switch (pc) {
1082 case XML_SCHEMAS_ANY_SKIP:
1083 return (BAD_CAST "skip");
1084 case XML_SCHEMAS_ANY_LAX:
1085 return (BAD_CAST "lax");
1086 case XML_SCHEMAS_ANY_STRICT:
1087 return (BAD_CAST "strict");
1088 default:
1089 return (BAD_CAST "invalid process contents");
1090 }
1091}
1092
1093/**
1094 * xmlSchemaGetCanonValueWhtspExt:
1095 * @val: the precomputed value
1096 * @retValue: the returned value
1097 * @ws: the whitespace type of the value
1098 *
1099 * Get a the cononical representation of the value.
1100 * The caller has to free the returned retValue.
1101 *
1102 * Returns 0 if the value could be built and -1 in case of
1103 * API errors or if the value type is not supported yet.
1104 */
1105static int
1106xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1107 xmlSchemaWhitespaceValueType ws,
1108 xmlChar **retValue)
1109{
1110 int list;
1111 xmlSchemaValType valType;
1112 const xmlChar *value, *value2 = NULL;
1113
1114
1115 if ((retValue == NULL) || (val == NULL))
1116 return (-1);
1117 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1118 *retValue = NULL;
1119 do {
1120 value = NULL;
1121 valType = xmlSchemaGetValType(val);
1122 switch (valType) {
1123 case XML_SCHEMAS_STRING:
1124 case XML_SCHEMAS_NORMSTRING:
1125 case XML_SCHEMAS_ANYSIMPLETYPE:
1126 value = xmlSchemaValueGetAsString(val);
1127 if (value != NULL) {
1128 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1129 value2 = xmlSchemaCollapseString(value);
1130 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1131 value2 = xmlSchemaWhiteSpaceReplace(value);
1132 if (value2 != NULL)
1133 value = value2;
1134 }
1135 break;
1136 default:
1137 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1138 if (value2 != NULL)
1139 xmlFree((xmlChar *) value2);
1140 goto internal_error;
1141 }
1142 value = value2;
1143 }
1144 if (*retValue == NULL)
1145 if (value == NULL) {
1146 if (! list)
1147 *retValue = xmlStrdup(BAD_CAST "");
1148 } else
1149 *retValue = xmlStrdup(value);
1150 else if (value != NULL) {
1151 /* List. */
1152 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1153 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1154 }
1155 FREE_AND_NULL(value2)
1156 val = xmlSchemaValueGetNext(val);
1157 } while (val != NULL);
1158
1159 return (0);
1160internal_error:
1161 if (*retValue != NULL)
1162 xmlFree((xmlChar *) (*retValue));
1163 if (value2 != NULL)
1164 xmlFree((xmlChar *) value2);
1165 return (-1);
1166}
1167
1168/**
1169 * xmlSchemaFormatItemForReport:
1170 * @buf: the string buffer
1171 * @itemDes: the designation of the item
1172 * @itemName: the name of the item
1173 * @item: the item as an object
1174 * @itemNode: the node of the item
1175 * @local: the local name
1176 * @parsing: if the function is used during the parse
1177 *
1178 * Returns a representation of the given item used
1179 * for error reports.
1180 *
1181 * The following order is used to build the resulting
1182 * designation if the arguments are not NULL:
1183 * 1a. If itemDes not NULL -> itemDes
1184 * 1b. If (itemDes not NULL) and (itemName not NULL)
1185 * -> itemDes + itemName
1186 * 2. If the preceding was NULL and (item not NULL) -> item
1187 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1188 *
1189 * If the itemNode is an attribute node, the name of the attribute
1190 * will be appended to the result.
1191 *
1192 * Returns the formatted string and sets @buf to the resulting value.
1193 */
1194static xmlChar*
1195xmlSchemaFormatItemForReport(xmlChar **buf,
1196 const xmlChar *itemDes,
1197 xmlSchemaTypePtr item,
1198 xmlNodePtr itemNode)
1199{
1200 xmlChar *str = NULL;
1201 int named = 1;
1202
1203 if (*buf != NULL) {
1204 xmlFree(*buf);
1205 *buf = NULL;
1206 }
1207
1208 if (itemDes != NULL) {
1209 *buf = xmlStrdup(itemDes);
1210 } else if (item != NULL) {
1211 switch (item->type) {
1212 case XML_SCHEMA_TYPE_BASIC:
1213 if (VARIETY_ATOMIC(item))
1214 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1215 else if (VARIETY_LIST(item))
1216 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1217 else if (VARIETY_UNION(item))
1218 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1219 else
1220 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1221 *buf = xmlStrcat(*buf, item->name);
1222 *buf = xmlStrcat(*buf, BAD_CAST "'");
1223 break;
1224 case XML_SCHEMA_TYPE_SIMPLE:
1225 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1226 *buf = xmlStrdup(BAD_CAST"");
1227 } else {
1228 *buf = xmlStrdup(BAD_CAST "local ");
1229 }
1230 if (VARIETY_ATOMIC(item))
1231 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1232 else if (VARIETY_LIST(item))
1233 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1234 else if (VARIETY_UNION(item))
1235 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1236 else
1237 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1238 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1239 *buf = xmlStrcat(*buf, BAD_CAST " '");
1240 *buf = xmlStrcat(*buf, item->name);
1241 *buf = xmlStrcat(*buf, BAD_CAST "'");
1242 }
1243 break;
1244 case XML_SCHEMA_TYPE_COMPLEX:
1245 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1246 *buf = xmlStrdup(BAD_CAST "");
1247 else
1248 *buf = xmlStrdup(BAD_CAST "local ");
1249 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1250 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1251 *buf = xmlStrcat(*buf, BAD_CAST " '");
1252 *buf = xmlStrcat(*buf, item->name);
1253 *buf = xmlStrcat(*buf, BAD_CAST "'");
1254 }
1255 break;
1256 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1257 xmlSchemaAttributePtr attr;
1258
1259 attr = (xmlSchemaAttributePtr) item;
1260 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
1261 (attr->ref == NULL)) {
1262 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1263 *buf = xmlStrcat(*buf, BAD_CAST " '");
1264 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1265 attr->targetNamespace, attr->name));
1266 FREE_AND_NULL(str)
1267 *buf = xmlStrcat(*buf, BAD_CAST "'");
1268 } else {
1269 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1270 *buf = xmlStrcat(*buf, BAD_CAST " '");
1271 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1272 attr->refNs, attr->ref));
1273 FREE_AND_NULL(str)
1274 *buf = xmlStrcat(*buf, BAD_CAST "'");
1275 }
1276 }
1277 break;
1278 case XML_SCHEMA_TYPE_ELEMENT: {
1279 xmlSchemaElementPtr elem;
1280
1281 elem = (xmlSchemaElementPtr) item;
1282 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
1283 (elem->ref == NULL)) {
1284 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1285 *buf = xmlStrcat(*buf, BAD_CAST " '");
1286 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1287 elem->targetNamespace, elem->name));
1288 *buf = xmlStrcat(*buf, BAD_CAST "'");
1289 }
1290 }
1291 break;
1292 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1293 case XML_SCHEMA_TYPE_IDC_KEY:
1294 case XML_SCHEMA_TYPE_IDC_KEYREF:
1295 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1296 *buf = xmlStrdup(BAD_CAST "unique '");
1297 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1298 *buf = xmlStrdup(BAD_CAST "key '");
1299 else
1300 *buf = xmlStrdup(BAD_CAST "keyRef '");
1301 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1302 *buf = xmlStrcat(*buf, BAD_CAST "'");
1303 break;
1304 case XML_SCHEMA_TYPE_ANY:
1305 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1306 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1307 ((xmlSchemaWildcardPtr) item)->processContents));
1308 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1309 break;
1310 case XML_SCHEMA_FACET_MININCLUSIVE:
1311 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1312 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1313 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1314 case XML_SCHEMA_FACET_TOTALDIGITS:
1315 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1316 case XML_SCHEMA_FACET_PATTERN:
1317 case XML_SCHEMA_FACET_ENUMERATION:
1318 case XML_SCHEMA_FACET_WHITESPACE:
1319 case XML_SCHEMA_FACET_LENGTH:
1320 case XML_SCHEMA_FACET_MAXLENGTH:
1321 case XML_SCHEMA_FACET_MINLENGTH:
1322 *buf = xmlStrdup(BAD_CAST "facet '");
1323 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1324 *buf = xmlStrcat(*buf, BAD_CAST "'");
1325 break;
1326 case XML_SCHEMA_TYPE_NOTATION:
1327 *buf = xmlStrdup(BAD_CAST "notation");
1328 break;
1329 case XML_SCHEMA_TYPE_GROUP: {
1330 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1331 *buf = xmlStrcat(*buf, BAD_CAST " '");
1332 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1333 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1334 ((xmlSchemaModelGroupDefPtr) item)->name));
1335 *buf = xmlStrcat(*buf, BAD_CAST "'");
1336 FREE_AND_NULL(str)
1337 }
1338 break;
1339 case XML_SCHEMA_TYPE_SEQUENCE:
1340 case XML_SCHEMA_TYPE_CHOICE:
1341 case XML_SCHEMA_TYPE_ALL:
1342 case XML_SCHEMA_TYPE_PARTICLE:
1343 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1344 break;
1345 default:
1346 named = 0;
1347 }
1348 } else
1349 named = 0;
1350
1351 if ((named == 0) && (itemNode != NULL)) {
1352 xmlNodePtr elem;
1353
1354 if (itemNode->type == XML_ATTRIBUTE_NODE)
1355 elem = itemNode->parent;
1356 else
1357 elem = itemNode;
1358 *buf = xmlStrdup(BAD_CAST "Element '");
1359 if (elem->ns != NULL) {
1360 *buf = xmlStrcat(*buf,
1361 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1362 FREE_AND_NULL(str)
1363 } else
1364 *buf = xmlStrcat(*buf, elem->name);
1365 *buf = xmlStrcat(*buf, BAD_CAST "'");
1366
1367 }
1368 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1369 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1370 if (itemNode->ns != NULL) {
1371 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1372 itemNode->ns->href, itemNode->name));
1373 FREE_AND_NULL(str)
1374 } else
1375 *buf = xmlStrcat(*buf, itemNode->name);
1376 *buf = xmlStrcat(*buf, BAD_CAST "'");
1377 }
1378 FREE_AND_NULL(str)
1379
1380 return (*buf);
1381}
1382
1383/**
1384 * xmlSchemaFormatFacetEnumSet:
1385 * @buf: the string buffer
1386 * @type: the type holding the enumeration facets
1387 *
1388 * Builds a string consisting of all enumeration elements.
1389 *
1390 * Returns a string of all enumeration elements.
1391 */
1392static const xmlChar *
1393xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1394 xmlChar **buf, xmlSchemaTypePtr type)
1395{
1396 xmlSchemaFacetPtr facet;
1397 xmlSchemaWhitespaceValueType ws;
1398 xmlChar *value = NULL;
1399 int res;
1400
1401 if (*buf != NULL)
1402 xmlFree(*buf);
1403 *buf = NULL;
1404
1405 do {
1406 /*
1407 * Use the whitespace type of the base type.
1408 */
1409 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1410 for (facet = type->facets; facet != NULL; facet = facet->next) {
1411 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1412 continue;
1413 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1414 ws, &value);
1415 if (res == -1) {
1416 xmlSchemaInternalErr(actxt,
1417 "xmlSchemaFormatFacetEnumSet",
1418 "compute the canonical lexical representation");
1419 if (*buf != NULL)
1420 xmlFree(*buf);
1421 *buf = NULL;
1422 return (NULL);
1423 }
1424 if (*buf == NULL)
1425 *buf = xmlStrdup(BAD_CAST "'");
1426 else
1427 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1428 *buf = xmlStrcat(*buf, BAD_CAST value);
1429 *buf = xmlStrcat(*buf, BAD_CAST "'");
1430 if (value != NULL) {
1431 xmlFree((xmlChar *)value);
1432 value = NULL;
1433 }
1434 }
1435 type = type->baseType;
1436 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1437
1438 return ((const xmlChar *) *buf);
1439}
1440
1441/************************************************************************
1442 * *
1443 * Error functions *
1444 * *
1445 ************************************************************************/
1446
1447#if 0
1448static void
1449xmlSchemaErrMemory(const char *msg)
1450{
1451 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1452 msg);
1453}
1454#endif
1455
1456/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001457 * xmlSchemaPErrMemory:
1458 * @node: a context node
1459 * @extra: extra informations
1460 *
1461 * Handle an out of memory condition
1462 */
1463static void
1464xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1465 const char *extra, xmlNodePtr node)
1466{
1467 if (ctxt != NULL)
1468 ctxt->nberrors++;
1469 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1470 extra);
1471}
1472
1473/**
1474 * xmlSchemaPErr:
1475 * @ctxt: the parsing context
1476 * @node: the context node
1477 * @error: the error code
1478 * @msg: the error message
1479 * @str1: extra data
1480 * @str2: extra data
1481 *
1482 * Handle a parser error
1483 */
1484static void
1485xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1486 const char *msg, const xmlChar * str1, const xmlChar * str2)
1487{
1488 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001489 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001490 void *data = NULL;
1491
1492 if (ctxt != NULL) {
1493 ctxt->nberrors++;
1494 channel = ctxt->error;
1495 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001496 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001497 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001498 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001499 error, XML_ERR_ERROR, NULL, 0,
1500 (const char *) str1, (const char *) str2, NULL, 0, 0,
1501 msg, str1, str2);
1502}
1503
1504/**
1505 * xmlSchemaPErr2:
1506 * @ctxt: the parsing context
1507 * @node: the context node
1508 * @node: the current child
1509 * @error: the error code
1510 * @msg: the error message
1511 * @str1: extra data
1512 * @str2: extra data
1513 *
1514 * Handle a parser error
1515 */
1516static void
1517xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1518 xmlNodePtr child, int error,
1519 const char *msg, const xmlChar * str1, const xmlChar * str2)
1520{
1521 if (child != NULL)
1522 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1523 else
1524 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1525}
1526
Daniel Veillard01fa6152004-06-29 17:04:39 +00001527
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001528/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001529 * xmlSchemaPErrExt:
1530 * @ctxt: the parsing context
1531 * @node: the context node
1532 * @error: the error code
1533 * @strData1: extra data
1534 * @strData2: extra data
1535 * @strData3: extra data
1536 * @msg: the message
1537 * @str1: extra parameter for the message display
1538 * @str2: extra parameter for the message display
1539 * @str3: extra parameter for the message display
1540 * @str4: extra parameter for the message display
1541 * @str5: extra parameter for the message display
1542 *
1543 * Handle a parser error
1544 */
1545static void
1546xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1547 const xmlChar * strData1, const xmlChar * strData2,
1548 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1549 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1550 const xmlChar * str5)
1551{
1552
1553 xmlGenericErrorFunc channel = NULL;
1554 xmlStructuredErrorFunc schannel = NULL;
1555 void *data = NULL;
1556
1557 if (ctxt != NULL) {
1558 ctxt->nberrors++;
1559 channel = ctxt->error;
1560 data = ctxt->userData;
1561 schannel = ctxt->serror;
1562 }
1563 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1564 error, XML_ERR_ERROR, NULL, 0,
1565 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001566 (const char *) strData3, 0, 0, msg, str1, str2,
1567 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001568}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001569
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001570/************************************************************************
1571 * *
1572 * Allround error functions *
1573 * *
1574 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001575
1576/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001577 * xmlSchemaVTypeErrMemory:
1578 * @node: a context node
1579 * @extra: extra informations
1580 *
1581 * Handle an out of memory condition
1582 */
1583static void
1584xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1585 const char *extra, xmlNodePtr node)
1586{
1587 if (ctxt != NULL) {
1588 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001589 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001590 }
1591 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1592 extra);
1593}
1594
1595/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001596 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001597 * @ctxt: the validation 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 * @str3: extra data
1604 *
1605 * Handle a validation error
1606 */
1607static void
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001608xmlSchemaErr3Line(xmlSchemaAbstractCtxtPtr ctxt,
1609 int error, xmlNodePtr node, int line, const char *msg,
1610 const xmlChar *str1, const xmlChar *str2,
1611 const xmlChar *str3)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001612{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001613 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001614 xmlGenericErrorFunc channel = NULL;
1615 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001616
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001617 if (ctxt != NULL) {
1618 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1619 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00001620 const char *file = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001621
1622 vctxt->nberrors++;
1623 vctxt->err = error;
1624 channel = vctxt->error;
1625 schannel = vctxt->serror;
1626 data = vctxt->userData;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001627
1628 /*
1629 * Error node. If we specify a line number, then
1630 * do not channel any node to the error function.
1631 */
1632 if (line == 0) {
1633 if ((node == NULL) &&
1634 (vctxt->depth >= 0) &&
1635 (vctxt->inode != NULL)) {
1636 node = vctxt->inode->node;
1637 }
1638 /*
1639 * Get filename and line if no node-tree.
1640 */
1641 if ((node == NULL) &&
1642 (vctxt->parserCtxt != NULL) &&
1643 (vctxt->parserCtxt->input != NULL)) {
1644 file = vctxt->parserCtxt->input->filename;
1645 line = vctxt->parserCtxt->input->line;
1646 }
1647 } else {
1648 /*
1649 * Override the given node's (if any) position
1650 * and channel only the given line number.
1651 */
1652 node = NULL;
1653 /*
1654 * Get filename.
1655 */
1656 if (vctxt->doc != NULL)
1657 file = (const char *) vctxt->doc->URL;
1658 else if ((vctxt->parserCtxt != NULL) &&
1659 (vctxt->parserCtxt->input != NULL))
1660 file = vctxt->parserCtxt->input->filename;
1661 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001662 __xmlRaiseError(schannel, channel, data, ctxt,
1663 node, XML_FROM_SCHEMASV,
Daniel Veillard971771e2005-07-09 17:32:57 +00001664 error, XML_ERR_ERROR, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001665 (const char *) str1, (const char *) str2,
1666 (const char *) str3, 0, 0, msg, str1, str2, str3);
1667
1668 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
1669 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
1670
1671 pctxt->nberrors++;
1672 pctxt->err = error;
1673 channel = pctxt->error;
1674 schannel = pctxt->serror;
1675 data = pctxt->userData;
1676 __xmlRaiseError(schannel, channel, data, ctxt,
1677 node, XML_FROM_SCHEMASP,
1678 error, XML_ERR_ERROR, NULL, 0,
1679 (const char *) str1, (const char *) str2,
1680 (const char *) str3, 0, 0, msg, str1, str2, str3);
1681 } else {
1682 TODO
1683 }
1684 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001685}
1686
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001687/**
1688 * xmlSchemaErr3:
1689 * @ctxt: the validation context
1690 * @node: the context node
1691 * @error: the error code
1692 * @msg: the error message
1693 * @str1: extra data
1694 * @str2: extra data
1695 * @str3: extra data
1696 *
1697 * Handle a validation error
1698 */
1699static void
1700xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
1701 int error, xmlNodePtr node, const char *msg,
1702 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
1703{
1704 xmlSchemaErr3Line(actxt, error, node, 0, msg, str1, str2, str3);
1705}
1706
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001707static void
1708xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
1709 int error, xmlNodePtr node, const char *msg,
1710 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001711{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001712 xmlSchemaErr3(actxt, error, node, msg, str1, str2, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001713}
1714
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001715static xmlChar *
1716xmlSchemaFormatNodeForError(xmlChar ** msg,
1717 xmlSchemaAbstractCtxtPtr actxt,
1718 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001719{
1720 xmlChar *str = NULL;
1721
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001722 if (node != NULL) {
1723 /*
1724 * Work on tree nodes.
1725 */
1726 if (node->type == XML_ATTRIBUTE_NODE) {
1727 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001728
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001729 *msg = xmlStrdup(BAD_CAST "Element '");
1730 if (elem->ns != NULL)
1731 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1732 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001733 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001734 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1735 NULL, elem->name));
1736 FREE_AND_NULL(str);
1737 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1738 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1739 } else {
1740 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001741 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001742 if (node->ns != NULL)
1743 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1744 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001745 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001746 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1747 NULL, node->name));
1748 FREE_AND_NULL(str);
1749 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1750 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1751 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
1752 /*
1753 * Work on node infos.
1754 */
1755 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
1756 xmlSchemaNodeInfoPtr ielem =
1757 vctxt->elemInfos[vctxt->depth];
1758
1759 *msg = xmlStrdup(BAD_CAST "Element '");
1760 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1761 ielem->nsName, ielem->localName));
1762 FREE_AND_NULL(str);
1763 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1764 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1765 } else {
1766 *msg = xmlStrdup(BAD_CAST "Element '");
1767 }
1768 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1769 vctxt->inode->nsName, vctxt->inode->localName));
1770 FREE_AND_NULL(str);
1771 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1772 } else {
1773 TODO
1774 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001775 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001776 /*
1777 * VAL TODO: The output of the given schema component is currently
1778 * disabled.
1779 */
1780#if 0
1781 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
1782 *msg = xmlStrcat(*msg, BAD_CAST " [");
1783 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
1784 NULL, type, NULL, 0));
1785 FREE_AND_NULL(str)
1786 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001787 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001788#endif
1789 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001790}
1791
Daniel Veillardc0826a72004-08-10 14:17:33 +00001792static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001793xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001794 const char *funcName,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001795 const char *message,
1796 const xmlChar *str1,
1797 const xmlChar *str2)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001798{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001799 xmlChar *msg = NULL;
1800
1801 msg = xmlStrdup(BAD_CAST "Internal error: ");
1802 msg = xmlStrcat(msg, BAD_CAST funcName);
1803 msg = xmlStrcat(msg, BAD_CAST ", ");
1804 msg = xmlStrcat(msg, BAD_CAST message);
1805 msg = xmlStrcat(msg, BAD_CAST ".\n");
1806
1807 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
1808 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001809 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001810
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001811 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001812 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001813 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001814
1815 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001816}
1817
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001818static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001819xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1820 const char *funcName,
1821 const char *message)
1822{
1823 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
1824}
1825
1826static void
1827xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
1828 const char *funcName,
1829 const char *message,
1830 const xmlChar *str1,
1831 const xmlChar *str2)
1832{
1833 xmlSchemaInternalErr2((xmlSchemaAbstractCtxtPtr) pctxt, funcName, message,
1834 str1, str2);
1835}
1836
1837static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001838xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
1839 xmlParserErrors error,
1840 xmlNodePtr node,
1841 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1842 const char *message,
1843 const xmlChar *str1,
1844 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001845{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001846 xmlChar *msg = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001847
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001848 xmlSchemaFormatNodeForError(&msg, actxt, node);
1849 msg = xmlStrcat(msg, (const xmlChar *) message);
1850 msg = xmlStrcat(msg, BAD_CAST ".\n");
1851 xmlSchemaErr(actxt, error, node,
1852 (const char *) msg, str1, str2);
1853 FREE_AND_NULL(msg)
1854}
1855
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001856static void
1857xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
1858 xmlParserErrors error,
1859 xmlSchemaPSVIIDCNodePtr idcNode,
1860 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1861 const char *message,
1862 const xmlChar *str1,
1863 const xmlChar *str2)
1864{
1865 xmlChar *msg = NULL, *qname = NULL;
1866
1867 msg = xmlStrdup(BAD_CAST "Element '%s': ");
1868 msg = xmlStrcat(msg, (const xmlChar *) message);
1869 msg = xmlStrcat(msg, BAD_CAST ".\n");
1870 xmlSchemaErr3Line((xmlSchemaAbstractCtxtPtr) vctxt,
1871 error, NULL, idcNode->nodeLine, (const char *) msg,
1872 xmlSchemaFormatQName(&qname,
1873 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
1874 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
1875 str1, str2);
1876 FREE_AND_NULL(qname);
1877 FREE_AND_NULL(msg);
1878}
1879
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001880static int
1881xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
1882 xmlNodePtr node)
1883{
1884 if (node != NULL)
1885 return (node->type);
1886 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
1887 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
1888 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
1889 return (-1);
1890}
1891
1892static int
1893xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1894{
1895 switch (item->type) {
1896 case XML_SCHEMA_TYPE_COMPLEX:
1897 case XML_SCHEMA_TYPE_SIMPLE:
1898 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1899 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001900 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001901 case XML_SCHEMA_TYPE_GROUP:
1902 return (1);
1903 case XML_SCHEMA_TYPE_ELEMENT:
1904 if ( ((xmlSchemaElementPtr) item)->flags &
1905 XML_SCHEMAS_ELEM_GLOBAL)
1906 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001907 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001908 case XML_SCHEMA_TYPE_ATTRIBUTE:
1909 if ( ((xmlSchemaAttributePtr) item)->flags &
1910 XML_SCHEMAS_ATTR_GLOBAL)
1911 return(1);
1912 break;
1913 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001914 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001915 return(1);
1916 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001917 return (0);
1918}
1919
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001920static void
1921xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1922 xmlParserErrors error,
1923 xmlNodePtr node,
1924 const xmlChar *value,
1925 xmlSchemaTypePtr type,
1926 int displayValue)
1927{
1928 xmlChar *msg = NULL;
1929
1930 xmlSchemaFormatNodeForError(&msg, actxt, node);
1931
1932 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1933 XML_ATTRIBUTE_NODE))
1934 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
1935 else
1936 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
1937 "value of ");
1938
1939 if (! xmlSchemaIsGlobalItem(type))
1940 msg = xmlStrcat(msg, BAD_CAST "the local ");
1941 else
1942 msg = xmlStrcat(msg, BAD_CAST "the ");
1943
1944 if (VARIETY_ATOMIC(type))
1945 msg = xmlStrcat(msg, BAD_CAST "atomic type");
1946 else if (VARIETY_LIST(type))
1947 msg = xmlStrcat(msg, BAD_CAST "list type");
1948 else if (VARIETY_UNION(type))
1949 msg = xmlStrcat(msg, BAD_CAST "union type");
1950
1951 if (xmlSchemaIsGlobalItem(type)) {
1952 xmlChar *str = NULL;
1953 msg = xmlStrcat(msg, BAD_CAST " '");
1954 if (type->builtInType != 0) {
1955 msg = xmlStrcat(msg, BAD_CAST "xs:");
1956 msg = xmlStrcat(msg, type->name);
1957 } else
1958 msg = xmlStrcat(msg,
1959 xmlSchemaFormatQName(&str,
1960 type->targetNamespace, type->name));
1961 msg = xmlStrcat(msg, BAD_CAST "'");
1962 FREE_AND_NULL(str);
1963 }
1964 msg = xmlStrcat(msg, BAD_CAST ".\n");
1965 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1966 XML_ATTRIBUTE_NODE))
1967 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
1968 else
1969 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
1970 FREE_AND_NULL(msg)
1971}
1972
Daniel Veillardc0826a72004-08-10 14:17:33 +00001973static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001974xmlSchemaFormatErrorNodeQName(xmlChar ** str,
1975 xmlSchemaNodeInfoPtr ni,
1976 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001977{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001978 if (node != NULL) {
1979 if (node->ns != NULL)
1980 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
1981 else
1982 return (xmlSchemaFormatQName(str, NULL, node->name));
1983 } else if (ni != NULL)
1984 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
1985 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001986}
1987
Daniel Veillardc0826a72004-08-10 14:17:33 +00001988static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001989xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
1990 xmlParserErrors error,
1991 xmlSchemaAttrInfoPtr ni,
1992 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001993{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001994 xmlChar *msg = NULL, *str = NULL;
1995
1996 xmlSchemaFormatNodeForError(&msg, actxt, node);
1997 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
1998 xmlSchemaErr(actxt, error, node, (const char *) msg,
1999 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2000 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002001 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002002 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002003}
2004
Daniel Veillardc0826a72004-08-10 14:17:33 +00002005static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002006xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2007 xmlParserErrors error,
2008 xmlNodePtr node,
2009 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002010 const char *message,
2011 int nbval,
2012 int nbneg,
2013 xmlChar **values)
2014{
2015 xmlChar *str = NULL, *msg = NULL;
2016 xmlChar *localName, *nsName;
2017 const xmlChar *cur, *end;
Daniel Veillard77005e62005-07-19 16:26:18 +00002018 int i, is_not;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002019
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002020 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002021 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002022 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002023 /*
2024 * Note that is does not make sense to report that we have a
2025 * wildcard here, since the wildcard might be unfolded into
2026 * multiple transitions.
2027 */
2028 if (nbval + nbneg > 0) {
2029 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002030 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002031 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002032 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002033 nsName = NULL;
2034
2035 for (i = 0; i < nbval + nbneg; i++) {
2036 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00002037 if (cur == NULL)
2038 continue;
2039 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2040 (cur[3] == ' ')) {
2041 is_not = 1;
2042 cur += 4;
Daniel Veillard6e65e152005-08-09 11:09:52 +00002043 str = xmlStrcat(str, BAD_CAST "##other");
Daniel Veillard77005e62005-07-19 16:26:18 +00002044 } else {
2045 is_not = 0;
2046 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002047 /*
2048 * Get the local name.
2049 */
2050 localName = NULL;
2051
2052 end = cur;
2053 if (*end == '*') {
2054 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002055 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002056 } else {
2057 while ((*end != 0) && (*end != '|'))
2058 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002059 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002060 }
2061 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002062 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002063 /*
2064 * Skip "*|*" if they come with negated expressions, since
2065 * they represent the same negated wildcard.
2066 */
2067 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2068 /*
2069 * Get the namespace name.
2070 */
2071 cur = end;
2072 if (*end == '*') {
2073 nsName = xmlStrdup(BAD_CAST "{*}");
2074 } else {
2075 while (*end != 0)
2076 end++;
2077
2078 if (i >= nbval)
2079 nsName = xmlStrdup(BAD_CAST "{##other:");
2080 else
2081 nsName = xmlStrdup(BAD_CAST "{");
2082
2083 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2084 nsName = xmlStrcat(nsName, BAD_CAST "}");
2085 }
2086 str = xmlStrcat(str, BAD_CAST nsName);
2087 FREE_AND_NULL(nsName)
2088 } else {
2089 FREE_AND_NULL(localName);
2090 continue;
2091 }
2092 }
2093 str = xmlStrcat(str, BAD_CAST localName);
2094 FREE_AND_NULL(localName);
2095
2096 if (i < nbval + nbneg -1)
2097 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00002098 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002099 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002100 msg = xmlStrcat(msg, BAD_CAST str);
2101 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002102 } else
2103 msg = xmlStrcat(msg, BAD_CAST "\n");
2104 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002105 xmlFree(msg);
2106}
2107
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002108static void
2109xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2110 xmlParserErrors error,
2111 xmlNodePtr node,
2112 const xmlChar *value,
2113 unsigned long length,
2114 xmlSchemaTypePtr type,
2115 xmlSchemaFacetPtr facet,
2116 const char *message,
2117 const xmlChar *str1,
2118 const xmlChar *str2)
2119{
2120 xmlChar *str = NULL, *msg = NULL;
2121 xmlSchemaTypeType facetType;
2122 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2123
2124 xmlSchemaFormatNodeForError(&msg, actxt, node);
2125 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2126 facetType = XML_SCHEMA_FACET_ENUMERATION;
2127 /*
2128 * If enumerations are validated, one must not expect the
2129 * facet to be given.
2130 */
2131 } else
2132 facetType = facet->type;
2133 msg = xmlStrcat(msg, BAD_CAST "[");
2134 msg = xmlStrcat(msg, BAD_CAST "facet '");
2135 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2136 msg = xmlStrcat(msg, BAD_CAST "'] ");
2137 if (message == NULL) {
2138 /*
2139 * Use a default message.
2140 */
2141 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2142 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2143 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2144
2145 char len[25], actLen[25];
2146
2147 /* FIXME, TODO: What is the max expected string length of the
2148 * this value?
2149 */
2150 if (nodeType == XML_ATTRIBUTE_NODE)
2151 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2152 else
2153 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2154
2155 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2156 snprintf(actLen, 24, "%lu", length);
2157
2158 if (facetType == XML_SCHEMA_FACET_LENGTH)
2159 msg = xmlStrcat(msg,
2160 BAD_CAST "this differs from the allowed length of '%s'.\n");
2161 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2162 msg = xmlStrcat(msg,
2163 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2164 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2165 msg = xmlStrcat(msg,
2166 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2167
2168 if (nodeType == XML_ATTRIBUTE_NODE)
2169 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2170 value, (const xmlChar *) actLen, (const xmlChar *) len);
2171 else
2172 xmlSchemaErr(actxt, error, node, (const char *) msg,
2173 (const xmlChar *) actLen, (const xmlChar *) len);
2174
2175 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2176 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2177 "of the set {%s}.\n");
2178 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2179 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2180 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2181 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2182 "by the pattern '%s'.\n");
2183 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2184 facet->value);
2185 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2186 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2187 "minimum value allowed ('%s').\n");
2188 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2189 facet->value);
2190 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2191 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2192 "maximum value allowed ('%s').\n");
2193 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2194 facet->value);
2195 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2196 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2197 "'%s'.\n");
2198 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2199 facet->value);
2200 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2201 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2202 "'%s'.\n");
2203 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2204 facet->value);
2205 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2206 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2207 "digits than are allowed ('%s').\n");
2208 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2209 facet->value);
2210 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2211 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2212 "digits than are allowed ('%s').\n");
2213 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2214 facet->value);
2215 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2216 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2217 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2218 } else {
2219 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2220 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2221 }
2222 } else {
2223 msg = xmlStrcat(msg, (const xmlChar *) message);
2224 msg = xmlStrcat(msg, BAD_CAST ".\n");
2225 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2226 }
2227 FREE_AND_NULL(str)
2228 xmlFree(msg);
2229}
2230
2231#define VERROR(err, type, msg) \
2232 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
2233
2234#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
2235
2236#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002237#define PERROR_INT2(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) ctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002238
2239#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2240
2241
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002242/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002243 * xmlSchemaPMissingAttrErr:
2244 * @ctxt: the schema validation context
2245 * @ownerDes: the designation of the owner
2246 * @ownerName: the name of the owner
2247 * @ownerItem: the owner as a schema object
2248 * @ownerElem: the owner as an element node
2249 * @node: the parent element node of the missing attribute node
2250 * @type: the corresponding type of the attribute node
2251 *
2252 * Reports an illegal attribute.
2253 */
2254static void
2255xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002256 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002257 xmlSchemaTypePtr ownerItem,
2258 xmlNodePtr ownerElem,
2259 const char *name,
2260 const char *message)
2261{
2262 xmlChar *des = NULL;
2263
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002264 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2265
Daniel Veillardc0826a72004-08-10 14:17:33 +00002266 if (message != NULL)
2267 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002268 else
2269 xmlSchemaPErr(ctxt, ownerElem, error,
2270 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002271 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002272 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002273}
2274
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002275
Daniel Veillardc0826a72004-08-10 14:17:33 +00002276/**
2277 * xmlSchemaPResCompAttrErr:
2278 * @ctxt: the schema validation context
2279 * @error: the error code
2280 * @ownerDes: the designation of the owner
2281 * @ownerItem: the owner as a schema object
2282 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002283 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002284 * @refName: the referenced local name
2285 * @refURI: the referenced namespace URI
2286 * @message: optional message
2287 *
2288 * Used to report QName attribute values that failed to resolve
2289 * to schema components.
2290 */
2291static void
2292xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002293 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002294 xmlSchemaTypePtr ownerItem,
2295 xmlNodePtr ownerElem,
2296 const char *name,
2297 const xmlChar *refName,
2298 const xmlChar *refURI,
2299 xmlSchemaTypeType refType,
2300 const char *refTypeStr)
2301{
2302 xmlChar *des = NULL, *strA = NULL;
2303
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002304 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002305 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002306 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2307 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002308 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002309 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2310 "%s.\n", BAD_CAST des, BAD_CAST name,
2311 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002312 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002313 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002314 FREE_AND_NULL(strA)
2315}
2316
William M. Brack2f2a6632004-08-20 23:09:47 +00002317/**
2318 * xmlSchemaPCustomAttrErr:
2319 * @ctxt: the schema parser context
2320 * @error: the error code
2321 * @ownerDes: the designation of the owner
2322 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002323 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002324 *
2325 * Reports an illegal attribute during the parse.
2326 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002327static void
2328xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002329 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002330 xmlChar **ownerDes,
2331 xmlSchemaTypePtr ownerItem,
2332 xmlAttrPtr attr,
2333 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002334{
2335 xmlChar *des = NULL;
2336
2337 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002338 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002339 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002340 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002341 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002342 } else
2343 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002344 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002345 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002346 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2347 if (ownerDes == NULL)
2348 FREE_AND_NULL(des);
2349}
2350
2351/**
2352 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002353 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002354 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002355 * @ownerDes: the designation of the attribute's owner
2356 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002357 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002358 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002359 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002360 */
2361static void
2362xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002363 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002364 xmlChar **ownerDes,
2365 xmlSchemaTypePtr ownerItem,
2366 xmlAttrPtr attr)
2367{
2368 xmlChar *des = NULL, *strA = NULL;
2369
2370 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002371 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002372 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002373 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002374 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002375 } else
2376 des = *ownerDes;
2377 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2378 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2379 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002380 if (ownerDes == NULL)
2381 FREE_AND_NULL(des);
2382 FREE_AND_NULL(strA);
2383}
2384
William M. Brack2f2a6632004-08-20 23:09:47 +00002385/**
2386 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002387 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002388 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002389 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002390 * @itemElem: the node of the schema item
2391 *
2392 * Creates a designation for an item.
2393 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002394static void
2395xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002396 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002397 xmlSchemaTypePtr item,
2398 xmlNodePtr itemElem)
2399{
2400 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002401 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002402 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002403 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002404 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002405 } else
2406 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002407}
2408
William M. Brack2f2a6632004-08-20 23:09:47 +00002409/**
2410 * xmlSchemaPCustomErr:
2411 * @ctxt: the schema parser context
2412 * @error: the error code
2413 * @itemDes: the designation of the schema item
2414 * @item: the schema item
2415 * @itemElem: the node of the schema item
2416 * @message: the error message
2417 * @str1: an optional param for the error message
2418 * @str2: an optional param for the error message
2419 * @str3: an optional param for the error message
2420 *
2421 * Reports an error during parsing.
2422 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002423static void
2424xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002425 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002426 xmlChar **itemDes,
2427 xmlSchemaTypePtr item,
2428 xmlNodePtr itemElem,
2429 const char *message,
2430 const xmlChar *str1,
2431 const xmlChar *str2,
2432 const xmlChar *str3)
2433{
2434 xmlChar *des = NULL, *msg = NULL;
2435
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002436 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002437 msg = xmlStrdup(BAD_CAST "%s: ");
2438 msg = xmlStrcat(msg, (const xmlChar *) message);
2439 msg = xmlStrcat(msg, BAD_CAST ".\n");
2440 if ((itemElem == NULL) && (item != NULL))
2441 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002442 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002443 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2444 if (itemDes == NULL)
2445 FREE_AND_NULL(des);
2446 FREE_AND_NULL(msg);
2447}
2448
William M. Brack2f2a6632004-08-20 23:09:47 +00002449/**
2450 * xmlSchemaPCustomErr:
2451 * @ctxt: the schema parser context
2452 * @error: the error code
2453 * @itemDes: the designation of the schema item
2454 * @item: the schema item
2455 * @itemElem: the node of the schema item
2456 * @message: the error message
2457 * @str1: the optional param for the error message
2458 *
2459 * Reports an error during parsing.
2460 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002461static void
2462xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002463 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002464 xmlChar **itemDes,
2465 xmlSchemaTypePtr item,
2466 xmlNodePtr itemElem,
2467 const char *message,
2468 const xmlChar *str1)
2469{
2470 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2471 str1, NULL, NULL);
2472}
2473
William M. Brack2f2a6632004-08-20 23:09:47 +00002474/**
2475 * xmlSchemaPAttrUseErr:
2476 * @ctxt: the schema parser context
2477 * @error: the error code
2478 * @itemDes: the designation of the schema type
2479 * @item: the schema type
2480 * @itemElem: the node of the schema type
2481 * @attr: the invalid schema attribute
2482 * @message: the error message
2483 * @str1: the optional param for the error message
2484 *
2485 * Reports an attribute use error during parsing.
2486 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002487static void
2488xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002489 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002490 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002491 const xmlSchemaAttributePtr attr,
2492 const char *message,
2493 const xmlChar *str1)
2494{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002495 xmlChar *str = NULL, *msg = NULL;
2496 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2497 msg = xmlStrcat(msg, BAD_CAST ", ");
2498 msg = xmlStrcat(msg,
2499 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2500 (xmlSchemaTypePtr) attr, NULL));
2501 FREE_AND_NULL(str);
2502 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002503 msg = xmlStrcat(msg, (const xmlChar *) message);
2504 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002505 xmlSchemaPErr(ctxt, attr->node, error,
2506 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002507 xmlFree(msg);
2508}
2509
William M. Brack2f2a6632004-08-20 23:09:47 +00002510/**
2511 * xmlSchemaPIllegalFacetAtomicErr:
2512 * @ctxt: the schema parser context
2513 * @error: the error code
2514 * @itemDes: the designation of the type
2515 * @item: the schema type
2516 * @baseItem: the base type of type
2517 * @facet: the illegal facet
2518 *
2519 * Reports an illegal facet for atomic simple types.
2520 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002521static void
2522xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002523 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002524 xmlChar **itemDes,
2525 xmlSchemaTypePtr item,
2526 xmlSchemaTypePtr baseItem,
2527 xmlSchemaFacetPtr facet)
2528{
2529 xmlChar *des = NULL, *strT = NULL;
2530
2531 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2532 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2533 "%s: The facet '%s' is not allowed on types derived from the "
2534 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002535 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002536 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002537 NULL, NULL);
2538 if (itemDes == NULL)
2539 FREE_AND_NULL(des);
2540 FREE_AND_NULL(strT);
2541}
2542
William M. Brack2f2a6632004-08-20 23:09:47 +00002543/**
2544 * xmlSchemaPIllegalFacetListUnionErr:
2545 * @ctxt: the schema parser context
2546 * @error: the error code
2547 * @itemDes: the designation of the schema item involved
2548 * @item: the schema item involved
2549 * @facet: the illegal facet
2550 *
2551 * Reports an illegal facet for <list> and <union>.
2552 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002553static void
2554xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002555 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002556 xmlChar **itemDes,
2557 xmlSchemaTypePtr item,
2558 xmlSchemaFacetPtr facet)
2559{
2560 xmlChar *des = NULL, *strT = NULL;
2561
2562 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002563 xmlSchemaPErr(ctxt, item->node, error,
2564 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002565 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002566 if (itemDes == NULL)
2567 FREE_AND_NULL(des);
2568 FREE_AND_NULL(strT);
2569}
2570
2571/**
2572 * xmlSchemaPMutualExclAttrErr:
2573 * @ctxt: the schema validation context
2574 * @error: the error code
2575 * @elemDes: the designation of the parent element node
2576 * @attr: the bad attribute node
2577 * @type: the corresponding type of the attribute node
2578 *
2579 * Reports an illegal attribute.
2580 */
2581static void
2582xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2583 xmlParserErrors error,
2584 xmlChar **ownerDes,
2585 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002586 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002587 const char *name1,
2588 const char *name2)
2589{
2590 xmlChar *des = NULL;
2591
2592 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002593 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002594 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002595 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002596 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002597 } else
2598 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002599 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002600 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002601 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2602 if (ownerDes == NULL)
2603 FREE_AND_NULL(des)
2604}
2605
2606/**
2607 * xmlSchemaPSimpleTypeErr:
2608 * @ctxt: the schema validation context
2609 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002610 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002611 * @ownerDes: the designation of the owner
2612 * @ownerItem: the schema object if existent
2613 * @node: the validated node
2614 * @value: the validated value
2615 *
2616 * Reports a simple type validation error.
2617 * TODO: Should this report the value of an element as well?
2618 */
2619static void
2620xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2621 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002622 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002623 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002624 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002625 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002626 const xmlChar *value,
2627 const char *message,
2628 const xmlChar *str1,
2629 const xmlChar *str2)
2630{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002631 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002632
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002633 xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002634 if (message == NULL) {
2635 /*
2636 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002637 */
2638 if (type != NULL) {
2639 if (node->type == XML_ATTRIBUTE_NODE)
2640 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2641 else
2642 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2643 "valid value of ");
2644 if (! xmlSchemaIsGlobalItem(type))
2645 msg = xmlStrcat(msg, BAD_CAST "the local ");
2646 else
2647 msg = xmlStrcat(msg, BAD_CAST "the ");
2648
2649 if (VARIETY_ATOMIC(type))
2650 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2651 else if (VARIETY_LIST(type))
2652 msg = xmlStrcat(msg, BAD_CAST "list type");
2653 else if (VARIETY_UNION(type))
2654 msg = xmlStrcat(msg, BAD_CAST "union type");
2655
2656 if (xmlSchemaIsGlobalItem(type)) {
2657 xmlChar *str = NULL;
2658 msg = xmlStrcat(msg, BAD_CAST " '");
2659 if (type->builtInType != 0) {
2660 msg = xmlStrcat(msg, BAD_CAST "xs:");
2661 msg = xmlStrcat(msg, type->name);
2662 } else
2663 msg = xmlStrcat(msg,
2664 xmlSchemaFormatQName(&str,
2665 type->targetNamespace, type->name));
2666 msg = xmlStrcat(msg, BAD_CAST "'.");
2667 FREE_AND_NULL(str);
2668 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002669 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002670 if (node->type == XML_ATTRIBUTE_NODE)
2671 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2672 else
2673 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2674 "valid.");
2675 }
2676 if (expected) {
2677 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2678 msg = xmlStrcat(msg, BAD_CAST expected);
2679 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2680 } else
2681 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002682 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002683 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2684 else
2685 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2686 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00002687 msg = xmlStrcat(msg, BAD_CAST message);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00002688 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002689 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00002690 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002691 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002692 /* Cleanup. */
2693 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002694}
2695
William M. Brack2f2a6632004-08-20 23:09:47 +00002696/**
2697 * xmlSchemaPContentErr:
2698 * @ctxt: the schema parser context
2699 * @error: the error code
2700 * @onwerDes: the designation of the holder of the content
2701 * @ownerItem: the owner item of the holder of the content
2702 * @ownerElem: the node of the holder of the content
2703 * @child: the invalid child node
2704 * @message: the optional error message
2705 * @content: the optional string describing the correct content
2706 *
2707 * Reports an error concerning the content of a schema element.
2708 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002709static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002710xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002711 xmlParserErrors error,
2712 xmlChar **ownerDes,
2713 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002714 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002715 xmlNodePtr child,
2716 const char *message,
2717 const char *content)
2718{
2719 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002720
Daniel Veillardc0826a72004-08-10 14:17:33 +00002721 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002722 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002723 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002724 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002725 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002726 } else
2727 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002728 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002729 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2730 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002731 BAD_CAST des, BAD_CAST message);
2732 else {
2733 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002734 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2735 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002736 BAD_CAST des, BAD_CAST content);
2737 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002738 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2739 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002740 BAD_CAST des, NULL);
2741 }
2742 }
2743 if (ownerDes == NULL)
2744 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002745}
2746
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002747/************************************************************************
2748 * *
2749 * Streamable error functions *
2750 * *
2751 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002752
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002753
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002754
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002755
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002756/************************************************************************
2757 * *
2758 * Validation helper functions *
2759 * *
2760 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002761
Daniel Veillardc0826a72004-08-10 14:17:33 +00002762
Daniel Veillard4255d502002-04-16 15:50:10 +00002763/************************************************************************
2764 * *
2765 * Allocation functions *
2766 * *
2767 ************************************************************************/
2768
2769/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002770 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002771 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002772 *
2773 * Allocate a new Schema structure.
2774 *
2775 * Returns the newly allocated structure or NULL in case or error
2776 */
2777static xmlSchemaPtr
2778xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2779{
2780 xmlSchemaPtr ret;
2781
2782 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2783 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002784 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002785 return (NULL);
2786 }
2787 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002788 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002789 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002790
2791 return (ret);
2792}
2793
2794/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002795 * xmlSchemaNewSchema:
2796 * @ctxt: a schema validation context
2797 *
2798 * Allocate a new Schema structure.
2799 *
2800 * Returns the newly allocated structure or NULL in case or error
2801 */
2802static xmlSchemaAssemblePtr
2803xmlSchemaNewAssemble(void)
2804{
2805 xmlSchemaAssemblePtr ret;
2806
2807 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2808 if (ret == NULL) {
2809 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2810 return (NULL);
2811 }
2812 memset(ret, 0, sizeof(xmlSchemaAssemble));
2813 ret->items = NULL;
2814 return (ret);
2815}
2816
2817/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002818 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002819 *
2820 * Allocate a new Facet structure.
2821 *
2822 * Returns the newly allocated structure or NULL in case or error
2823 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002824xmlSchemaFacetPtr
2825xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002826{
2827 xmlSchemaFacetPtr ret;
2828
2829 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2830 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002831 return (NULL);
2832 }
2833 memset(ret, 0, sizeof(xmlSchemaFacet));
2834
2835 return (ret);
2836}
2837
2838/**
2839 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002840 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002841 * @node: a node
2842 *
2843 * Allocate a new annotation structure.
2844 *
2845 * Returns the newly allocated structure or NULL in case or error
2846 */
2847static xmlSchemaAnnotPtr
2848xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2849{
2850 xmlSchemaAnnotPtr ret;
2851
2852 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2853 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002854 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002855 return (NULL);
2856 }
2857 memset(ret, 0, sizeof(xmlSchemaAnnot));
2858 ret->content = node;
2859 return (ret);
2860}
2861
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002862static xmlSchemaItemListPtr
2863xmlSchemaNewItemList(void)
2864{
2865 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002866
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002867 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2868 if (ret == NULL) {
2869 xmlSchemaPErrMemory(NULL,
2870 "allocating an item list structure", NULL);
2871 return (NULL);
2872 }
2873 memset(ret, 0, sizeof(xmlSchemaItemList));
2874 return (ret);
2875}
2876
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002877static void
2878xmlSchemaItemListClear(xmlSchemaItemListPtr list)
2879{
2880 if (list->items != NULL) {
2881 xmlFree(list->items);
2882 list->items = NULL;
2883 }
2884 list->nbItems = 0;
2885 list->sizeItems = 0;
2886}
2887
2888static int
2889xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
2890{
2891 if (list->items == NULL) {
2892 list->items = (void **) xmlMalloc(
2893 20 * sizeof(void *));
2894 if (list->items == NULL) {
2895 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
2896 return(-1);
2897 }
2898 list->sizeItems = 20;
2899 } else if (list->sizeItems <= list->nbItems) {
2900 list->sizeItems *= 2;
2901 list->items = (void **) xmlRealloc(list->items,
2902 list->sizeItems * sizeof(void *));
2903 if (list->items == NULL) {
2904 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
2905 list->sizeItems = 0;
2906 return(-1);
2907 }
2908 }
2909 /* ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item; */
2910 list->items[list->nbItems++] = item;
2911 return(0);
2912}
2913
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002914/**
2915 * xmlSchemaAddElementSubstitutionMember:
2916 * @pctxt: a schema parser context
2917 * @head: the head of the substitution group
2918 * @member: the new member of the substitution group
2919 *
2920 * Allocate a new annotation structure.
2921 *
2922 * Returns the newly allocated structure or NULL in case or error
2923 */
2924static int
2925xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2926 xmlSchemaElementPtr head,
2927 xmlSchemaElementPtr member)
2928{
2929 xmlSchemaSubstGroupPtr substGroup;
2930
2931 if (pctxt == NULL)
2932 return (-1);
2933
2934 if (pctxt->substGroups == NULL) {
2935 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2936 if (pctxt->substGroups == NULL)
2937 return (-1);
2938 }
2939 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2940 head->targetNamespace);
2941 if (substGroup == NULL) {
2942 int res;
2943
2944 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2945 if (substGroup == NULL) {
2946 xmlSchemaPErrMemory(NULL,
2947 "xmlSchemaAddElementSubstitution, allocating a substitution "
2948 "group container",
2949 NULL);
2950 return (-1);
2951 }
2952 substGroup->members = xmlSchemaNewItemList();
2953 if (substGroup->members == NULL) {
2954 xmlFree(substGroup);
2955 return (-1);
2956 }
2957 substGroup->head = head;
2958
2959 res = xmlHashAddEntry2(pctxt->substGroups,
2960 head->name, head->targetNamespace, substGroup);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002961 if (res != 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002962 xmlFree(substGroup->members);
2963 xmlFree(substGroup);
2964 xmlSchemaPErr(pctxt, member->node,
2965 XML_SCHEMAP_INTERNAL,
2966 "Internal error: xmlSchemaAddElementSubstitution, "
2967 "failed to add a new substitution group container for "
2968 "'%s'.\n", head->name, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002969 return (-1);
2970 }
2971 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002972 if (substGroup->members->items == NULL) {
2973 substGroup->members->items = (void **) xmlMalloc(
2974 5 * sizeof(xmlSchemaElementPtr));
2975 if (substGroup->members->items == NULL) {
2976 xmlSchemaPErrMemory(NULL,
2977 "allocating list of substitution group members", NULL);
2978 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002979 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002980 substGroup->members->sizeItems = 5;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002981 } else if (substGroup->members->sizeItems <=
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002982 substGroup->members->nbItems) {
2983 substGroup->members->sizeItems *= 2;
2984 substGroup->members->items = (void **) xmlRealloc(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002985 substGroup->members->items,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002986 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2987 if (substGroup->members->items == NULL) {
2988 xmlSchemaPErrMemory(NULL,
2989 "re-allocating list of substitution group members", NULL);
2990 substGroup->members->sizeItems = 0;
2991 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002992 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002993 }
2994 ((xmlSchemaElementPtr *) substGroup->members->items)
2995 [substGroup->members->nbItems++] = (void *) member;
2996 return (0);
2997}
2998
2999/**
3000 * xmlSchemaGetElementSubstitutionGroup:
3001 * @pctxt: a schema parser context
3002 * @head: the head of the substitution group
3003 * @member: the new member of the substitution group
3004 *
3005 * Allocate a new annotation structure.
3006 *
3007 * Returns the newly allocated structure or NULL in case or error
3008 */
3009static xmlSchemaSubstGroupPtr
3010xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
3011 xmlSchemaElementPtr head)
3012{
3013 if (pctxt == NULL)
3014 return (NULL);
3015
3016 if (pctxt->substGroups == NULL)
3017 return (NULL);
3018
3019 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
3020 head->name, head->targetNamespace));
3021}
3022
3023/**
3024 * xmlSchemaFreeItemList:
3025 * @annot: a schema type structure
3026 *
3027 * Deallocate a annotation structure
3028 */
3029static void
3030xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
3031{
3032 if (list == NULL)
3033 return;
3034 if (list->items != NULL)
3035 xmlFree(list->items);
3036 xmlFree(list);
3037}
3038
Daniel Veillard4255d502002-04-16 15:50:10 +00003039/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00003040 * xmlSchemaFreeAnnot:
3041 * @annot: a schema type structure
3042 *
3043 * Deallocate a annotation structure
3044 */
3045static void
3046xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3047{
3048 if (annot == NULL)
3049 return;
Kasimier T. Buchcik004b5462005-08-08 12:43:09 +00003050 if (annot->next == NULL) {
3051 xmlFree(annot);
3052 } else {
3053 xmlSchemaAnnotPtr prev;
3054
3055 do {
3056 prev = annot;
3057 annot = annot->next;
3058 xmlFree(prev);
3059 } while (annot != NULL);
3060 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00003061}
3062
3063/**
Daniel Veillard1d913862003-11-21 00:28:39 +00003064 * xmlSchemaFreeImport:
3065 * @import: a schema import structure
3066 *
3067 * Deallocate an import structure
3068 */
3069static void
3070xmlSchemaFreeImport(xmlSchemaImportPtr import)
3071{
3072 if (import == NULL)
3073 return;
3074
3075 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00003076 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00003077 xmlFree(import);
3078}
3079
3080/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003081 * xmlSchemaFreeInclude:
3082 * @include: a schema include structure
3083 *
3084 * Deallocate an include structure
3085 */
3086static void
3087xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
3088{
3089 if (include == NULL)
3090 return;
3091
3092 xmlFreeDoc(include->doc);
3093 xmlFree(include);
3094}
3095
3096/**
3097 * xmlSchemaFreeIncludeList:
3098 * @includes: a schema include list
3099 *
3100 * Deallocate an include structure
3101 */
3102static void
3103xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
3104{
3105 xmlSchemaIncludePtr next;
3106
3107 while (includes != NULL) {
3108 next = includes->next;
3109 xmlSchemaFreeInclude(includes);
3110 includes = next;
3111 }
3112}
3113
3114/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003115 * xmlSchemaFreeNotation:
3116 * @schema: a schema notation structure
3117 *
3118 * Deallocate a Schema Notation structure.
3119 */
3120static void
3121xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3122{
3123 if (nota == NULL)
3124 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003125 xmlFree(nota);
3126}
3127
3128/**
3129 * xmlSchemaFreeAttribute:
3130 * @schema: a schema attribute structure
3131 *
3132 * Deallocate a Schema Attribute structure.
3133 */
3134static void
3135xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3136{
3137 if (attr == NULL)
3138 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003139 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003140 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003141 if (attr->defVal != NULL)
3142 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003143 xmlFree(attr);
3144}
3145
3146/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003147 * xmlSchemaFreeWildcardNsSet:
3148 * set: a schema wildcard namespace
3149 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003150 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003151 */
3152static void
3153xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3154{
3155 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003156
Daniel Veillard3646d642004-06-02 19:19:14 +00003157 while (set != NULL) {
3158 next = set->next;
3159 xmlFree(set);
3160 set = next;
3161 }
3162}
3163
3164/**
3165 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003166 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003167 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003168 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003169 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003170void
Daniel Veillard3646d642004-06-02 19:19:14 +00003171xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3172{
3173 if (wildcard == NULL)
3174 return;
3175 if (wildcard->annot != NULL)
3176 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003177 if (wildcard->nsSet != NULL)
3178 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3179 if (wildcard->negNsSet != NULL)
3180 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00003181 xmlFree(wildcard);
3182}
3183
3184/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003185 * xmlSchemaFreeAttributeGroup:
3186 * @schema: a schema attribute group structure
3187 *
3188 * Deallocate a Schema Attribute Group structure.
3189 */
3190static void
3191xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
3192{
3193 if (attr == NULL)
3194 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00003195 if (attr->annot != NULL)
3196 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003197 xmlFree(attr);
3198}
3199
3200/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003201 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003202 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00003203 *
3204 * Deallocate a list of schema attribute uses.
3205 */
3206static void
3207xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3208{
3209 xmlSchemaAttributeLinkPtr next;
3210
3211 while (attrUse != NULL) {
3212 next = attrUse->next;
3213 xmlFree(attrUse);
3214 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003215 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003216}
3217
3218/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003219 * xmlSchemaFreeQNameRef:
3220 * @item: a QName reference structure
3221 *
3222 * Deallocatea a QName reference structure.
3223 */
3224static void
3225xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3226{
3227 xmlFree(item);
3228}
3229
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003230/**
3231 * xmlSchemaFreeQNameRef:
3232 * @item: a QName reference structure
3233 *
3234 * Deallocatea a QName reference structure.
3235 */
3236static void
3237xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3238{
3239 if (item == NULL)
3240 return;
3241 if (item->members != NULL)
3242 xmlSchemaFreeItemList(item->members);
3243 xmlFree(item);
3244}
3245
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003246static int
3247xmlSchemaAddVolatile(xmlSchemaPtr schema,
3248 xmlSchemaBasicItemPtr item)
3249{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003250 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003251 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003252 if (schema->volatiles == NULL) {
3253 xmlSchemaPErrMemory(NULL,
3254 "allocating list of volatiles", NULL);
3255 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003256 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003257 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003258 return(xmlSchemaItemListAdd((xmlSchemaItemListPtr) schema->volatiles, item));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003259}
3260
3261/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003262 * xmlSchemaFreeTypeLinkList:
3263 * @alink: a type link
3264 *
3265 * Deallocate a list of types.
3266 */
3267static void
3268xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3269{
3270 xmlSchemaTypeLinkPtr next;
3271
3272 while (link != NULL) {
3273 next = link->next;
3274 xmlFree(link);
3275 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003276 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003277}
3278
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003279static void
3280xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3281{
3282 xmlSchemaIDCStateObjPtr next;
3283 while (sto != NULL) {
3284 next = sto->next;
3285 if (sto->history != NULL)
3286 xmlFree(sto->history);
3287 if (sto->xpathCtxt != NULL)
3288 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3289 xmlFree(sto);
3290 sto = next;
3291 }
3292}
3293
3294/**
3295 * xmlSchemaFreeIDC:
3296 * @idc: a identity-constraint definition
3297 *
3298 * Deallocates an identity-constraint definition.
3299 */
3300static void
3301xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3302{
3303 xmlSchemaIDCSelectPtr cur, prev;
3304
3305 if (idcDef == NULL)
3306 return;
3307 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003308 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003309 /* Selector */
3310 if (idcDef->selector != NULL) {
3311 if (idcDef->selector->xpathComp != NULL)
3312 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3313 xmlFree(idcDef->selector);
3314 }
3315 /* Fields */
3316 if (idcDef->fields != NULL) {
3317 cur = idcDef->fields;
3318 do {
3319 prev = cur;
3320 cur = cur->next;
3321 if (prev->xpathComp != NULL)
3322 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003323 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003324 } while (cur != NULL);
3325 }
3326 xmlFree(idcDef);
3327}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003328
Daniel Veillard01fa6152004-06-29 17:04:39 +00003329/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003330 * xmlSchemaFreeElement:
3331 * @schema: a schema element structure
3332 *
3333 * Deallocate a Schema Element structure.
3334 */
3335static void
3336xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3337{
3338 if (elem == NULL)
3339 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003340 if (elem->annot != NULL)
3341 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003342 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003343 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003344 if (elem->defVal != NULL)
3345 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003346 xmlFree(elem);
3347}
3348
3349/**
3350 * xmlSchemaFreeFacet:
3351 * @facet: a schema facet structure
3352 *
3353 * Deallocate a Schema Facet structure.
3354 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003355void
Daniel Veillard4255d502002-04-16 15:50:10 +00003356xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3357{
3358 if (facet == NULL)
3359 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003360 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003361 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003362 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003363 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003364 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003365 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003366 xmlFree(facet);
3367}
3368
3369/**
3370 * xmlSchemaFreeType:
3371 * @type: a schema type structure
3372 *
3373 * Deallocate a Schema Type structure.
3374 */
3375void
3376xmlSchemaFreeType(xmlSchemaTypePtr type)
3377{
3378 if (type == NULL)
3379 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003380 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003381 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003382 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003383 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003384
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003385 facet = type->facets;
3386 while (facet != NULL) {
3387 next = facet->next;
3388 xmlSchemaFreeFacet(facet);
3389 facet = next;
3390 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003391 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003392 if (type->type != XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00003393 /*
3394 * TODO: Why is this restricted to non built-in types?
3395 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003396 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003397 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003398 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003399 if (type->memberTypes != NULL)
3400 xmlSchemaFreeTypeLinkList(type->memberTypes);
3401 if (type->facetSet != NULL) {
3402 xmlSchemaFacetLinkPtr next, link;
3403
3404 link = type->facetSet;
3405 do {
3406 next = link->next;
3407 xmlFree(link);
3408 link = next;
3409 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003410 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003411 if (type->contModel != NULL)
3412 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003413 xmlFree(type);
3414}
3415
3416/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003417 * xmlSchemaFreeModelGroupDef:
3418 * @item: a schema model group definition
3419 *
3420 * Deallocates a schema model group definition.
3421 */
3422static void
3423xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3424{
3425 if (item->annot != NULL)
3426 xmlSchemaFreeAnnot(item->annot);
3427 xmlFree(item);
3428}
3429
3430/**
3431 * xmlSchemaFreeModelGroup:
3432 * @item: a schema model group
3433 *
3434 * Deallocates a schema model group structure.
3435 */
3436static void
3437xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3438{
3439 if (item->annot != NULL)
3440 xmlSchemaFreeAnnot(item->annot);
3441 xmlFree(item);
3442}
3443
3444/**
3445 * xmlSchemaFreeParticle:
3446 * @type: a schema type structure
3447 *
3448 * Deallocate a Schema Type structure.
3449 */
3450static void
3451xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3452{
3453 if (item->annot != NULL)
3454 xmlSchemaFreeAnnot(item->annot);
3455 xmlFree(item);
3456}
3457
3458/**
3459 * xmlSchemaFreeMiscComponents:
3460 * @item: a schema component
3461 *
3462 * Deallocates misc. schema component structures.
3463 */
3464static void
3465xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3466{
3467 if (item == NULL)
3468 return;
3469 switch (item->type) {
3470 case XML_SCHEMA_TYPE_PARTICLE:
3471 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3472 return;
3473 case XML_SCHEMA_TYPE_SEQUENCE:
3474 case XML_SCHEMA_TYPE_CHOICE:
3475 case XML_SCHEMA_TYPE_ALL:
3476 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3477 return;
3478 case XML_SCHEMA_TYPE_ANY:
3479 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3480 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3481 break;
3482 default:
3483 /* TODO: This should never be hit. */
3484 TODO
3485 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003486 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003487}
3488
3489static void
3490xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3491{
3492 if (schema->volatiles == NULL)
3493 return;
3494 {
3495 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3496 xmlSchemaTreeItemPtr item;
3497 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003498
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003499 for (i = 0; i < list->nbItems; i++) {
3500 if (list->items[i] != NULL) {
3501 item = (xmlSchemaTreeItemPtr) list->items[i];
3502 switch (item->type) {
3503 case XML_SCHEMA_EXTRA_QNAMEREF:
3504 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3505 break;
3506 default:
3507 xmlSchemaFreeMiscComponents(item);
3508 }
3509 }
3510 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003511 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003512 }
3513}
3514/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003515 * xmlSchemaFreeTypeList:
3516 * @type: a schema type structure
3517 *
3518 * Deallocate a Schema Type structure.
3519 */
3520static void
3521xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3522{
3523 xmlSchemaTypePtr next;
3524
3525 while (type != NULL) {
3526 next = type->redef;
3527 xmlSchemaFreeType(type);
3528 type = next;
3529 }
3530}
3531
3532/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003533 * xmlSchemaFree:
3534 * @schema: a schema structure
3535 *
3536 * Deallocate a Schema structure.
3537 */
3538void
3539xmlSchemaFree(xmlSchemaPtr schema)
3540{
3541 if (schema == NULL)
3542 return;
3543
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003544 if (schema->volatiles != NULL)
3545 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003546 if (schema->notaDecl != NULL)
3547 xmlHashFree(schema->notaDecl,
3548 (xmlHashDeallocator) xmlSchemaFreeNotation);
3549 if (schema->attrDecl != NULL)
3550 xmlHashFree(schema->attrDecl,
3551 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3552 if (schema->attrgrpDecl != NULL)
3553 xmlHashFree(schema->attrgrpDecl,
3554 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3555 if (schema->elemDecl != NULL)
3556 xmlHashFree(schema->elemDecl,
3557 (xmlHashDeallocator) xmlSchemaFreeElement);
3558 if (schema->typeDecl != NULL)
3559 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003560 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003561 if (schema->groupDecl != NULL)
3562 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003563 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003564 if (schema->idcDef != NULL)
3565 xmlHashFree(schema->idcDef,
3566 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003567 if (schema->schemasImports != NULL)
3568 xmlHashFree(schema->schemasImports,
3569 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003570 if (schema->includes != NULL) {
3571 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3572 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003573 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003574 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003575 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003576 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003577 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003578 xmlFree(schema);
3579}
3580
3581/************************************************************************
3582 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003583 * Debug functions *
3584 * *
3585 ************************************************************************/
3586
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003587#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003588
Daniel Veillard4255d502002-04-16 15:50:10 +00003589/**
3590 * xmlSchemaElementDump:
3591 * @elem: an element
3592 * @output: the file output
3593 *
3594 * Dump the element
3595 */
3596static void
3597xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003598 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003599 const xmlChar * namespace ATTRIBUTE_UNUSED,
3600 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003601{
3602 if (elem == NULL)
3603 return;
3604
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003605 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3606 fprintf(output, "Particle: %s", name);
3607 fprintf(output, ", term element: %s", elem->ref);
3608 if (elem->refNs != NULL)
3609 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003610 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003611 fprintf(output, "Element");
3612 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3613 fprintf(output, " (global)");
3614 fprintf(output, ": %s ", elem->name);
3615 if (namespace != NULL)
3616 fprintf(output, "ns %s", namespace);
3617 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003618 fprintf(output, "\n");
3619 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003620 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003621 if (elem->maxOccurs >= UNBOUNDED)
3622 fprintf(output, "max: unbounded\n");
3623 else if (elem->maxOccurs != 1)
3624 fprintf(output, "max: %d\n", elem->maxOccurs);
3625 else
3626 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003627 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003628 /*
3629 * Misc other properties.
3630 */
3631 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3632 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3633 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3634 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3635 (elem->id != NULL)) {
3636 fprintf(output, " props: ");
3637 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3638 fprintf(output, "[fixed] ");
3639 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3640 fprintf(output, "[default] ");
3641 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3642 fprintf(output, "[abstract] ");
3643 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3644 fprintf(output, "[nillable] ");
3645 if (elem->id != NULL)
3646 fprintf(output, "[id: '%s'] ", elem->id);
3647 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003648 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003649 /*
3650 * Default/fixed value.
3651 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003652 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003653 fprintf(output, " value: '%s'\n", elem->value);
3654 /*
3655 * Type.
3656 */
3657 if (elem->namedType != NULL) {
3658 fprintf(output, " type: %s ", elem->namedType);
3659 if (elem->namedTypeNs != NULL)
3660 fprintf(output, "ns %s\n", elem->namedTypeNs);
3661 else
3662 fprintf(output, "\n");
3663 }
3664 /*
3665 * Substitution group.
3666 */
3667 if (elem->substGroup != NULL) {
3668 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3669 if (elem->substGroupNs != NULL)
3670 fprintf(output, "ns %s\n", elem->substGroupNs);
3671 else
3672 fprintf(output, "\n");
3673 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003674}
3675
3676/**
3677 * xmlSchemaAnnotDump:
3678 * @output: the file output
3679 * @annot: a annotation
3680 *
3681 * Dump the annotation
3682 */
3683static void
3684xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3685{
3686 xmlChar *content;
3687
3688 if (annot == NULL)
3689 return;
3690
3691 content = xmlNodeGetContent(annot->content);
3692 if (content != NULL) {
3693 fprintf(output, " Annot: %s\n", content);
3694 xmlFree(content);
3695 } else
3696 fprintf(output, " Annot: empty\n");
3697}
3698
3699/**
3700 * xmlSchemaTypeDump:
3701 * @output: the file output
3702 * @type: a type structure
3703 *
3704 * Dump a SchemaType structure
3705 */
3706static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003707xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3708{
3709 xmlChar *str = NULL;
3710 xmlSchemaTreeItemPtr term;
3711 char shift[100];
3712 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003713
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003714 if (particle == NULL)
3715 return;
3716 for (i = 0;((i < depth) && (i < 25));i++)
3717 shift[2 * i] = shift[2 * i + 1] = ' ';
3718 shift[2 * i] = shift[2 * i + 1] = 0;
3719 fprintf(output, shift);
3720 if (particle->children == NULL) {
3721 fprintf(output, "MISSING particle term\n");
3722 return;
3723 }
3724 term = particle->children;
3725 switch (term->type) {
3726 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003727 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003728 ((xmlSchemaElementPtr)term)->targetNamespace,
3729 ((xmlSchemaElementPtr)term)->name));
3730 break;
3731 case XML_SCHEMA_TYPE_SEQUENCE:
3732 fprintf(output, "SEQUENCE");
3733 break;
3734 case XML_SCHEMA_TYPE_CHOICE:
3735 fprintf(output, "CHOICE");
3736 break;
3737 case XML_SCHEMA_TYPE_ALL:
3738 fprintf(output, "ALL");
3739 break;
3740 case XML_SCHEMA_TYPE_ANY:
3741 fprintf(output, "ANY");
3742 break;
3743 default:
3744 fprintf(output, "UNKNOWN\n");
3745 return;
3746 }
3747 if (particle->minOccurs != 1)
3748 fprintf(output, " min: %d", particle->minOccurs);
3749 if (particle->maxOccurs >= UNBOUNDED)
3750 fprintf(output, " max: unbounded");
3751 else if (particle->maxOccurs != 1)
3752 fprintf(output, " max: %d", particle->maxOccurs);
3753 fprintf(output, "\n");
3754 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3755 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3756 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3757 (term->children != NULL)) {
3758 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3759 output, depth +1);
3760 }
3761 if (particle->next != NULL)
3762 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3763 output, depth);
3764}
3765/**
3766 * xmlSchemaTypeDump:
3767 * @output: the file output
3768 * @type: a type structure
3769 *
3770 * Dump a SchemaType structure
3771 */
3772static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003773xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3774{
3775 if (type == NULL) {
3776 fprintf(output, "Type: NULL\n");
3777 return;
3778 }
3779 fprintf(output, "Type: ");
3780 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003781 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003782 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003783 fprintf(output, "no name ");
3784 if (type->targetNamespace != NULL)
3785 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003786 switch (type->type) {
3787 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003788 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003789 break;
3790 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003791 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003792 break;
3793 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003794 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003795 break;
3796 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003797 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003798 break;
3799 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003800 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003801 break;
3802 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003803 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003804 break;
3805 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003806 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003807 break;
3808 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003809 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003810 break;
3811 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003812 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003813 break;
3814 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003815 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003816 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003817 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003818 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003819 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003820 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003821 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003822 break;
3823 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003824 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003825 break;
3826 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003827 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003828 break;
3829 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003830 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003831 break;
3832 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003833 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003834 break;
3835 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003836 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003837 break;
3838 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003839 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003840 break;
3841 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003842 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003843 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003844 }
3845 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003846 if (type->base != NULL) {
3847 fprintf(output, " base type: %s", type->base);
3848 if (type->baseNs != NULL)
3849 fprintf(output, " ns %s\n", type->baseNs);
3850 else
3851 fprintf(output, "\n");
3852 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003853 if (type->annot != NULL)
3854 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003855#ifdef DUMP_CONTENT_MODEL
3856 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3857 (type->subtypes != NULL)) {
3858 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3859 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003860 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003861#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003862}
3863
3864/**
3865 * xmlSchemaDump:
3866 * @output: the file output
3867 * @schema: a schema structure
3868 *
3869 * Dump a Schema structure.
3870 */
3871void
3872xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3873{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003874 if (output == NULL)
3875 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003876 if (schema == NULL) {
3877 fprintf(output, "Schemas: NULL\n");
3878 return;
3879 }
3880 fprintf(output, "Schemas: ");
3881 if (schema->name != NULL)
3882 fprintf(output, "%s, ", schema->name);
3883 else
3884 fprintf(output, "no name, ");
3885 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003886 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003887 else
3888 fprintf(output, "no target namespace");
3889 fprintf(output, "\n");
3890 if (schema->annot != NULL)
3891 xmlSchemaAnnotDump(output, schema->annot);
3892
3893 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3894 output);
3895 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003896 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003897}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003898
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003899#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003900/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003901 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003902 * @vctxt: the WXS validation context
3903 *
3904 * Displays the current IDC table for debug purposes.
3905 */
3906static void
3907xmlSchemaDebugDumpIDCTable(FILE * output,
3908 const xmlChar *namespaceName,
3909 const xmlChar *localName,
3910 xmlSchemaPSVIIDCBindingPtr bind)
3911{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003912 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003913 xmlSchemaPSVIIDCNodePtr tab;
3914 xmlSchemaPSVIIDCKeyPtr key;
3915 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003916
3917 fprintf(output, "IDC: TABLES on %s\n",
3918 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003919 FREE_AND_NULL(str)
3920
3921 if (bind == NULL)
3922 return;
3923 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003924 fprintf(output, "IDC: BINDING %s\n",
3925 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003926 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003927 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003928 for (i = 0; i < bind->nbNodes; i++) {
3929 tab = bind->nodeTable[i];
3930 fprintf(output, " ( ");
3931 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003932 key = tab->keys[j];
3933 if ((key != NULL) && (key->val != NULL)) {
3934 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003935 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003936 fprintf(output, "\"%s\" ", value);
3937 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003938 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003939 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003940 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003941 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003942 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003943 else
3944 fprintf(output, "(key missing), ");
3945 }
3946 fprintf(output, ")\n");
3947 }
3948 bind = bind->next;
3949 } while (bind != NULL);
3950}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003951#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003952#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003953
3954/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003955 * *
3956 * Utilities *
3957 * *
3958 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003959
Daniel Veillardc0826a72004-08-10 14:17:33 +00003960/**
3961 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003962 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003963 * @name: the name of the attribute
3964 *
3965 * Seeks an attribute with a name of @name in
3966 * no namespace.
3967 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003968 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003969 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003970static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003971xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003972{
3973 xmlAttrPtr prop;
3974
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003975 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003976 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003977 prop = node->properties;
3978 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003979 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003980 return(prop);
3981 prop = prop->next;
3982 }
3983 return (NULL);
3984}
3985
3986/**
3987 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003988 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003989 * @uri: the uri
3990 * @name: the name of the attribute
3991 *
3992 * Seeks an attribute with a local name of @name and
3993 * a namespace URI of @uri.
3994 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003995 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003996 */
3997static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003998xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003999{
4000 xmlAttrPtr prop;
4001
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004002 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004003 return(NULL);
4004 prop = node->properties;
4005 while (prop != NULL) {
4006 if ((prop->ns != NULL) &&
4007 xmlStrEqual(prop->name, BAD_CAST name) &&
4008 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00004009 return(prop);
4010 prop = prop->next;
4011 }
4012 return (NULL);
4013}
4014
4015static const xmlChar *
4016xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4017{
4018 xmlChar *val;
4019 const xmlChar *ret;
4020
4021 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004022 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00004023 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00004024 ret = xmlDictLookup(ctxt->dict, val, -1);
4025 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004026 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004027}
4028
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004029/**
4030 * xmlSchemaGetProp:
4031 * @ctxt: the parser context
4032 * @node: the node
4033 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004034 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004035 * Read a attribute value and internalize the string
4036 *
4037 * Returns the string or NULL if not present.
4038 */
4039static const xmlChar *
4040xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4041 const char *name)
4042{
4043 xmlChar *val;
4044 const xmlChar *ret;
4045
4046 val = xmlGetProp(node, BAD_CAST name);
4047 if (val == NULL)
4048 return(NULL);
4049 ret = xmlDictLookup(ctxt->dict, val, -1);
4050 xmlFree(val);
4051 return(ret);
4052}
4053
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004054/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00004055 * *
4056 * Parsing functions *
4057 * *
4058 ************************************************************************/
4059
4060/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004061 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004062 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004063 * @name: the element name
4064 * @ns: the element namespace
4065 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004066 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004067 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004068 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004069 */
4070static xmlSchemaElementPtr
4071xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004072 const xmlChar * nsName)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004073{
4074 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004075
4076 if ((name == NULL) || (schema == NULL))
4077 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004078
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004079 ret = xmlHashLookup2(schema->elemDecl, name, nsName);
Daniel Veillardf2a12832003-11-24 13:04:35 +00004080 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004081 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004082 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004083 } else
4084 ret = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004085
William M. Brack2f2a6632004-08-20 23:09:47 +00004086 /*
4087 * Removed since imported components will be hold by the main schema only.
4088 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004089 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004090 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004091 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004092 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004093 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00004094 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00004095 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
4096 return (ret);
4097 } else
4098 ret = NULL;
4099 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004100 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004101#ifdef DEBUG
4102 if (ret == NULL) {
4103 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004104 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004105 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004106 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004107 namespace);
4108 }
4109#endif
4110 return (ret);
4111}
4112
4113/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004114 * xmlSchemaGetType:
4115 * @schema: the schemas context
4116 * @name: the type name
4117 * @ns: the type namespace
4118 *
4119 * Lookup a type in the schemas or the predefined types
4120 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004121 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004122 */
4123static xmlSchemaTypePtr
4124xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004125 const xmlChar * nsName)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004126{
Daniel Veillard4255d502002-04-16 15:50:10 +00004127 xmlSchemaTypePtr ret;
4128
4129 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004130 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004131 if (schema != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004132 ret = xmlHashLookup2(schema->typeDecl, name, nsName);
4133 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
4134 if (ret->redef != NULL) {
4135 /*
4136 * Return the last redefinition.
4137 */
4138 return(ret->redef);
4139 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004140 return (ret);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004141 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004142 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004143 ret = xmlSchemaGetPredefinedType(name, nsName);
Daniel Veillard1d913862003-11-21 00:28:39 +00004144 if (ret != NULL)
4145 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004146 /*
4147 * Removed, since the imported components will be grafted on the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004148 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00004149 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004150 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004151 else
Daniel Veillard1d913862003-11-21 00:28:39 +00004152 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004153 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00004154 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004155 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
4156 return (ret);
4157 } else
4158 ret = NULL;
4159 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004160 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004161#ifdef DEBUG
4162 if (ret == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004163 if (nsName == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004164 fprintf(stderr, "Unable to lookup type %s", name);
4165 else
4166 fprintf(stderr, "Unable to lookup type %s:%s", name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004167 nsName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004168 }
4169#endif
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004170 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004171}
4172
Daniel Veillard3646d642004-06-02 19:19:14 +00004173/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004174 * xmlSchemaGetAttributeDecl:
4175 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004176 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004177 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004178 *
4179 * Lookup a an attribute in the schema or imported schemas
4180 *
4181 * Returns the attribute declaration or NULL if not found.
4182 */
4183static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004184xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillard3646d642004-06-02 19:19:14 +00004185 const xmlChar * namespace)
4186{
4187 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004188
4189 if ((name == NULL) || (schema == NULL))
4190 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004191
4192
Daniel Veillard3646d642004-06-02 19:19:14 +00004193 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4194 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004195 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004196 else
4197 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004198 /*
4199 * Removed, since imported components will be hold by the main schema only.
4200 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004201 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004202 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004203 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004204 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004205 if (import != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004206 ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004207 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4208 return (ret);
4209 } else
4210 ret = NULL;
4211 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004212 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004213#ifdef DEBUG
4214 if (ret == NULL) {
4215 if (namespace == NULL)
4216 fprintf(stderr, "Unable to lookup attribute %s", name);
4217 else
4218 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4219 namespace);
4220 }
4221#endif
4222 return (ret);
4223}
4224
4225/**
4226 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004227 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004228 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004229 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004230 *
4231 * Lookup a an attribute group in the schema or imported schemas
4232 *
4233 * Returns the attribute group definition or NULL if not found.
4234 */
4235static xmlSchemaAttributeGroupPtr
4236xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4237 const xmlChar * namespace)
4238{
4239 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004240
4241 if ((name == NULL) || (schema == NULL))
4242 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004243
4244
Daniel Veillard3646d642004-06-02 19:19:14 +00004245 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4246 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004247 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004248 else
4249 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004250 /*
4251 * Removed since imported components will be hold by the main schema only.
4252 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004253 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004254 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004255 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004256 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004257 if (import != NULL) {
4258 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4259 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4260 return (ret);
4261 else
4262 ret = NULL;
4263 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004264 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004265#ifdef DEBUG
4266 if (ret == NULL) {
4267 if (namespace == NULL)
4268 fprintf(stderr, "Unable to lookup attribute group %s", name);
4269 else
4270 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4271 namespace);
4272 }
4273#endif
4274 return (ret);
4275}
4276
4277/**
4278 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004279 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004280 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004281 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004282 *
4283 * Lookup a group in the schema or imported schemas
4284 *
4285 * Returns the group definition or NULL if not found.
4286 */
4287static xmlSchemaTypePtr
4288xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4289 const xmlChar * namespace)
4290{
4291 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004292
4293 if ((name == NULL) || (schema == NULL))
4294 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004295
Daniel Veillard3646d642004-06-02 19:19:14 +00004296 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004297 /*
4298 * Removed since imported components will be hold by the main schema only.
4299 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004300 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004301 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004302 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004303 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004304 if (import != NULL) {
4305 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4306 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4307 return (ret);
4308 else
4309 ret = NULL;
4310 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004311 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004312#ifdef DEBUG
4313 if (ret == NULL) {
4314 if (namespace == NULL)
4315 fprintf(stderr, "Unable to lookup group %s", name);
4316 else
4317 fprintf(stderr, "Unable to lookup group %s:%s", name,
4318 namespace);
4319 }
4320#endif
4321 return (ret);
4322}
4323
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004324/**
4325 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004326 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004327 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004328 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004329 *
4330 * Lookup a group in the schema or imported schemas
4331 *
4332 * Returns the group definition or NULL if not found.
4333 */
4334static xmlSchemaTreeItemPtr
4335xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4336 xmlSchemaTypeType itemType,
4337 const xmlChar *name,
4338 const xmlChar *targetNs)
4339{
4340 switch (itemType) {
4341 case XML_SCHEMA_TYPE_GROUP:
4342 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4343 name, targetNs));
4344 case XML_SCHEMA_TYPE_ELEMENT:
4345 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4346 name, targetNs));
4347 default:
4348 return (NULL);
4349 }
4350}
4351
Daniel Veillard4255d502002-04-16 15:50:10 +00004352/************************************************************************
4353 * *
4354 * Parsing functions *
4355 * *
4356 ************************************************************************/
4357
4358#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004359 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004360
4361/**
4362 * xmlSchemaIsBlank:
4363 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004364 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004365 *
4366 * Check if a string is ignorable
4367 *
4368 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4369 */
4370static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004371xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004372{
Daniel Veillard4255d502002-04-16 15:50:10 +00004373 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004374 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004375 if (len < 0) {
4376 while (*str != 0) {
4377 if (!(IS_BLANK_CH(*str)))
4378 return (0);
4379 str++;
4380 }
4381 } else while ((*str != 0) && (len != 0)) {
4382 if (!(IS_BLANK_CH(*str)))
4383 return (0);
4384 str++;
4385 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004386 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004387
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004388 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004389}
4390
4391/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004392 * xmlSchemaAddAssembledItem:
4393 * @ctxt: a schema parser context
4394 * @schema: the schema being built
4395 * @item: the item
4396 *
4397 * Add a item to the schema's list of current items.
4398 * This is used if the schema was already constructed and
4399 * new schemata need to be added to it.
4400 * *WARNING* this interface is highly subject to change.
4401 *
4402 * Returns 0 if suceeds and -1 if an internal error occurs.
4403 */
4404static int
4405xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4406 xmlSchemaTypePtr item)
4407{
4408 static int growSize = 100;
4409 xmlSchemaAssemblePtr ass;
4410
4411 ass = ctxt->assemble;
4412 if (ass->sizeItems < 0) {
4413 /* If disabled. */
4414 return (0);
4415 }
4416 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004417 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004418 if (ass->items == NULL) {
4419 xmlSchemaPErrMemory(ctxt,
4420 "allocating new item buffer", NULL);
4421 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004422 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004423 ass->sizeItems = growSize;
4424 } else if (ass->sizeItems <= ass->nbItems) {
4425 ass->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004426 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004427 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4428 if (ass->items == NULL) {
4429 xmlSchemaPErrMemory(ctxt,
4430 "growing item buffer", NULL);
4431 ass->sizeItems = 0;
4432 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004433 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004434 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004435 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004436 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4437 return (0);
4438}
4439
4440/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004441 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004442 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004443 * @schema: the schema being built
4444 * @name: the item name
4445 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004446 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004447 * *WARNING* this interface is highly subject to change
4448 *
4449 * Returns the new struture or NULL in case of error
4450 */
4451static xmlSchemaNotationPtr
4452xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004453 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004454{
4455 xmlSchemaNotationPtr ret = NULL;
4456 int val;
4457
4458 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4459 return (NULL);
4460
4461 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004462 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004463 if (schema->notaDecl == NULL)
4464 return (NULL);
4465
4466 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4467 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004468 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004469 return (NULL);
4470 }
4471 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004472 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004473 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4474 ret);
4475 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004476 /*
4477 * TODO: This should never happen, since a unique name will be computed.
4478 * If it fails, then an other internal error must have occured.
4479 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004480 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4481 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004482 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004483 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004484 xmlFree(ret);
4485 return (NULL);
4486 }
4487 return (ret);
4488}
4489
4490
4491/**
4492 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004493 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004494 * @schema: the schema being built
4495 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004496 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004497 *
4498 * Add an XML schema Attrribute declaration
4499 * *WARNING* this interface is highly subject to change
4500 *
4501 * Returns the new struture or NULL in case of error
4502 */
4503static xmlSchemaAttributePtr
4504xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004505 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004506 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004507{
4508 xmlSchemaAttributePtr ret = NULL;
4509 int val;
4510
4511 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4512 return (NULL);
4513
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004514#ifdef DEBUG
4515 fprintf(stderr, "Adding attribute %s\n", name);
4516 if (namespace != NULL)
4517 fprintf(stderr, " target namespace %s\n", namespace);
4518#endif
4519
Daniel Veillard4255d502002-04-16 15:50:10 +00004520 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004521 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004522 if (schema->attrDecl == NULL)
4523 return (NULL);
4524
4525 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4526 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004527 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004528 return (NULL);
4529 }
4530 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004531 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004532 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004533 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004534 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004535 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004536 if (topLevel) {
4537 xmlSchemaPCustomErr(ctxt,
4538 XML_SCHEMAP_REDEFINED_ATTR,
4539 NULL, NULL, node,
4540 "A global attribute declaration with the name '%s' does "
4541 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004542 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004543 return (NULL);
4544 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004545 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004546 /*
4547 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4548 * in the scenario:
4549 * 1. multiple top-level complex types have different target
4550 * namespaces but have the SAME NAME; this can happen if
4551 * schemata are imported
4552 * 2. those complex types contain attributes with an equal name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004553 * 3. those attributes are in no namespace
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004554 * We will compute a new context string.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004555 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004556 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004557 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004558 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004559
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004560 if (val != 0) {
4561 xmlSchemaPCustomErr(ctxt,
4562 XML_SCHEMAP_INTERNAL,
4563 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004564 "Internal error: xmlSchemaAddAttribute, "
4565 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004566 "could not be added to the hash.", name);
4567 xmlFree(ret);
4568 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004569 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004570 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004571 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004572 if (ctxt->assemble != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004573 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004574 return (ret);
4575}
4576
4577/**
4578 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004579 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004580 * @schema: the schema being built
4581 * @name: the item name
4582 *
4583 * Add an XML schema Attrribute Group declaration
4584 *
4585 * Returns the new struture or NULL in case of error
4586 */
4587static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004588xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004589 xmlSchemaPtr schema, const xmlChar * name,
4590 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004591{
4592 xmlSchemaAttributeGroupPtr ret = NULL;
4593 int val;
4594
4595 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4596 return (NULL);
4597
4598 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004599 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004600 if (schema->attrgrpDecl == NULL)
4601 return (NULL);
4602
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004603 ret =
4604 (xmlSchemaAttributeGroupPtr)
4605 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004606 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004607 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004608 return (NULL);
4609 }
4610 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004611 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004612 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004613 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004614 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004615 xmlSchemaPCustomErr(ctxt,
4616 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4617 NULL, NULL, node,
4618 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004619 xmlFree(ret);
4620 return (NULL);
4621 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004622 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004623 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004624 return (ret);
4625}
4626
4627/**
4628 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004629 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004630 * @schema: the schema being built
4631 * @name: the type name
4632 * @namespace: the type namespace
4633 *
4634 * Add an XML schema Element declaration
4635 * *WARNING* this interface is highly subject to change
4636 *
4637 * Returns the new struture or NULL in case of error
4638 */
4639static xmlSchemaElementPtr
4640xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004641 const xmlChar * name, const xmlChar * namespace,
4642 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004643{
4644 xmlSchemaElementPtr ret = NULL;
4645 int val;
4646
4647 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4648 return (NULL);
4649
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004650#ifdef DEBUG
4651 fprintf(stderr, "Adding element %s\n", name);
4652 if (namespace != NULL)
4653 fprintf(stderr, " target namespace %s\n", namespace);
4654#endif
4655
Daniel Veillard4255d502002-04-16 15:50:10 +00004656 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004657 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004658 if (schema->elemDecl == NULL)
4659 return (NULL);
4660
4661 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4662 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004663 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004664 return (NULL);
4665 }
4666 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004667 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004668 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004669 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004670 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004671 if (topLevel) {
4672 xmlSchemaPCustomErr(ctxt,
4673 XML_SCHEMAP_REDEFINED_ELEMENT,
4674 NULL, NULL, node,
4675 "A global element declaration with the name '%s' does "
4676 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004677 xmlFree(ret);
4678 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004679 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004680 char buf[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00004681
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004682 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004683 val = xmlHashAddEntry3(schema->elemDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004684 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004685 if (val != 0) {
4686 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004687 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004688 NULL, NULL, node,
4689 "Internal error: xmlSchemaAddElement, "
4690 "a dublicate element declaration with the name '%s' "
4691 "could not be added to the hash.", name);
4692 xmlFree(ret);
4693 return (NULL);
4694 }
4695 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004696
Daniel Veillard4255d502002-04-16 15:50:10 +00004697 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004698 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004699 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004700 return (ret);
4701}
4702
4703/**
4704 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004705 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004706 * @schema: the schema being built
4707 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004708 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004709 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004710 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004711 * *WARNING* this interface is highly subject to change
4712 *
4713 * Returns the new struture or NULL in case of error
4714 */
4715static xmlSchemaTypePtr
4716xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004717 const xmlChar * name, const xmlChar * nsName,
4718 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004719{
4720 xmlSchemaTypePtr ret = NULL;
4721 int val;
4722
4723 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4724 return (NULL);
4725
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004726#ifdef DEBUG
4727 fprintf(stderr, "Adding type %s\n", name);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004728 if (nsName != NULL)
4729 fprintf(stderr, " target namespace %s\n", nsName);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004730#endif
4731
Daniel Veillard4255d502002-04-16 15:50:10 +00004732 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004733 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004734 if (schema->typeDecl == NULL)
4735 return (NULL);
4736
4737 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4738 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004739 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004740 return (NULL);
4741 }
4742 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004743 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004744 ret->redef = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004745 val = xmlHashAddEntry2(schema->typeDecl, name, nsName, ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004746 if (val != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004747 if (! ctxt->isRedefine) {
4748 xmlChar *str = NULL;
4749 if (topLevel) {
4750 xmlSchemaPCustomErr(ctxt,
4751 XML_SCHEMAP_REDEFINED_TYPE,
4752 NULL, NULL, node,
4753 "A global type definition with the name '%s' does "
4754 "already exist",
4755 xmlSchemaFormatQName(&str, nsName, name));
4756 } else {
4757 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
4758 NULL, NULL, node, "Internal error: xmlSchemaAddType, "
4759 "local type '%s' has a duplicate",
4760 xmlSchemaFormatQName(&str, nsName, name));
4761 }
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004762 xmlFree(ret);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004763 FREE_AND_NULL(str);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004764 return (NULL);
4765 } else {
4766 xmlSchemaTypePtr prev;
4767
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004768 /*
4769 * REDEFINE: Add a redefinition.
4770 */
4771 TODO
4772 prev = xmlHashLookup2(schema->typeDecl, name, nsName);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004773 if (prev == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004774 PERROR_INT2("xmlSchemaAddType", "hash list didn't return "
4775 "a type component, but should");
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004776 xmlFree(ret);
4777 return (NULL);
4778 }
4779 ret->redef = prev->redef;
4780 prev->redef = ret;
4781 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004782 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004783 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004784 ret->minOccurs = 1;
4785 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004786 ret->attributeUses = NULL;
4787 ret->attributeWildcard = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004788 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004789 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004790 return (ret);
4791}
4792
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004793static xmlSchemaQNameRefPtr
4794xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4795 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004796 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004797 const xmlChar *refNs)
4798{
4799 xmlSchemaQNameRefPtr ret;
4800
4801 ret = (xmlSchemaQNameRefPtr)
4802 xmlMalloc(sizeof(xmlSchemaQNameRef));
4803 if (ret == NULL) {
4804 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4805 NULL);
4806 return (NULL);
4807 }
4808 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4809 ret->name = refName;
4810 ret->targetNamespace = refNs;
4811 ret->item = NULL;
4812 ret->itemType = refType;
4813 /*
4814 * Store the reference item in the schema.
4815 */
4816 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4817 return (ret);
4818}
4819
4820/**
4821 * xmlSchemaAddModelGroup:
4822 * @ctxt: a schema parser context
4823 * @schema: the schema being built
4824 * @type: the "compositor" type of the model group
4825 * @container: the internal component name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004826 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004827 *
4828 * Adds a schema model group
4829 * *WARNING* this interface is highly subject to change
4830 *
4831 * Returns the new struture or NULL in case of error
4832 */
4833static xmlSchemaModelGroupPtr
4834xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4835 xmlSchemaTypeType type, const xmlChar **container,
4836 xmlNodePtr node)
4837{
4838 xmlSchemaModelGroupPtr ret = NULL;
4839 xmlChar buf[30];
4840
4841 if ((ctxt == NULL) || (schema == NULL))
4842 return (NULL);
4843
4844#ifdef DEBUG
4845 fprintf(stderr, "Adding model group component\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004846#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004847 ret = (xmlSchemaModelGroupPtr)
4848 xmlMalloc(sizeof(xmlSchemaModelGroup));
4849 if (ret == NULL) {
4850 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4851 NULL);
4852 return (NULL);
4853 }
4854 ret->type = type;
4855 ret->annot = NULL;
4856 ret->node = node;
4857 ret->children = NULL;
4858 ret->next = NULL;
4859 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4860 if (container != NULL)
4861 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4862 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004863 if (container != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004864 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4865 } else {
4866 if (container != NULL)
4867 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4868 }
4869 if (container != NULL)
4870 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4871 /*
4872 * Add to volatile items.
4873 * TODO: this should be changed someday.
4874 */
4875 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4876 xmlFree(ret);
4877 return (NULL);
4878 }
4879 return (ret);
4880}
4881
4882
4883/**
4884 * xmlSchemaAddParticle:
4885 * @ctxt: a schema parser context
4886 * @schema: the schema being built
4887 * @node: the corresponding node in the schema doc
4888 * @min: the minOccurs
4889 * @max: the maxOccurs
4890 *
4891 * Adds an XML schema particle component.
4892 * *WARNING* this interface is highly subject to change
4893 *
4894 * Returns the new struture or NULL in case of error
4895 */
4896static xmlSchemaParticlePtr
4897xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4898 xmlNodePtr node, int min, int max)
4899{
4900 xmlSchemaParticlePtr ret = NULL;
4901 if ((ctxt == NULL) || (schema == NULL))
4902 return (NULL);
4903
4904#ifdef DEBUG
4905 fprintf(stderr, "Adding particle component\n");
4906#endif
4907 ret = (xmlSchemaParticlePtr)
4908 xmlMalloc(sizeof(xmlSchemaParticle));
4909 if (ret == NULL) {
4910 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4911 NULL);
4912 return (NULL);
4913 }
4914 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4915 ret->annot = NULL;
4916 ret->node = node;
4917 ret->minOccurs = min;
4918 ret->maxOccurs = max;
4919 ret->next = NULL;
4920 ret->children = NULL;
4921
4922 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4923 xmlFree(ret);
4924 return (NULL);
4925 }
4926 return (ret);
4927}
4928
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004929/**
4930 * xmlSchemaAddGroup:
4931 * @ctxt: a schema validation context
4932 * @schema: the schema being built
4933 * @name: the group name
4934 *
4935 * Add an XML schema Group definition
4936 *
4937 * Returns the new struture or NULL in case of error
4938 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004939static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004940xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004941 const xmlChar *name, const xmlChar *namespaceName,
4942 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004943{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004944 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004945 int val;
4946
4947 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4948 return (NULL);
4949
4950 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004951 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004952 if (schema->groupDecl == NULL)
4953 return (NULL);
4954
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004955 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004956 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004957 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004958 return (NULL);
4959 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004960 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004961 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004962 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004963 ret->node = node;
4964 ret->targetNamespace = namespaceName;
4965 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004966 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004967 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004968 XML_SCHEMAP_REDEFINED_GROUP,
4969 NULL, NULL, node,
4970 "A global model group definition with the name '%s' does already "
4971 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004972 xmlFree(ret);
4973 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004974 }
4975 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004976 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004977 return (ret);
4978}
4979
Daniel Veillard3646d642004-06-02 19:19:14 +00004980/**
4981 * xmlSchemaNewWildcardNs:
4982 * @ctxt: a schema validation context
4983 *
4984 * Creates a new wildcard namespace constraint.
4985 *
4986 * Returns the new struture or NULL in case of error
4987 */
4988static xmlSchemaWildcardNsPtr
4989xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4990{
4991 xmlSchemaWildcardNsPtr ret;
4992
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004993 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004994 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4995 if (ret == NULL) {
4996 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004997 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00004998 }
4999 ret->value = NULL;
5000 ret->next = NULL;
5001 return (ret);
5002}
5003
5004/**
5005 * xmlSchemaAddWildcard:
5006 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005007 * @schema: a schema
5008 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005009 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005010 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00005011 *
5012 * Returns the new struture or NULL in case of error
5013 */
5014static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005015xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5016 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00005017{
5018 xmlSchemaWildcardPtr ret = NULL;
5019
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005020 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00005021 return (NULL);
5022
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005023#ifdef DEBUG
5024 fprintf(stderr, "Adding wildcard component\n");
5025#endif
5026
Daniel Veillard3646d642004-06-02 19:19:14 +00005027 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5028 if (ret == NULL) {
5029 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5030 return (NULL);
5031 }
5032 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005033 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00005034 ret->minOccurs = 1;
5035 ret->maxOccurs = 1;
5036
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005037 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
5038 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
5039 "Failed to add a wildcard component to the list", NULL);
5040 xmlFree(ret);
5041 return (NULL);
5042 }
Daniel Veillard3646d642004-06-02 19:19:14 +00005043 return (ret);
5044}
5045
Daniel Veillard4255d502002-04-16 15:50:10 +00005046/************************************************************************
5047 * *
5048 * Utilities for parsing *
5049 * *
5050 ************************************************************************/
5051
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00005052#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00005053/**
5054 * xmlGetQNameProp:
5055 * @ctxt: a schema validation context
5056 * @node: a subtree containing XML Schema informations
5057 * @name: the attribute name
5058 * @namespace: the result namespace if any
5059 *
5060 * Extract a QName Attribute value
5061 *
5062 * Returns the NCName or NULL if not found, and also update @namespace
5063 * with the namespace URI
5064 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005065static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00005066xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005067 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005068{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005069 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005070 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005071 const xmlChar *ret, *prefix;
5072 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005073 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005074
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005075 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005076 attr = xmlSchemaGetPropNode(node, name);
5077 if (attr == NULL)
5078 return (NULL);
5079 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005080
Daniel Veillard4255d502002-04-16 15:50:10 +00005081 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005082 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005083
Daniel Veillardba0153a2004-04-01 10:42:31 +00005084 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00005085 ns = xmlSearchNs(node->doc, node, 0);
5086 if (ns) {
5087 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
5088 return (val);
5089 }
5090 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005091 ret = xmlSplitQName3(val, &len);
5092 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005093 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005094 }
5095 ret = xmlDictLookup(ctxt->dict, ret, -1);
5096 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00005097
5098 ns = xmlSearchNs(node->doc, node, prefix);
5099 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005100 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
5101 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005102 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005103 "The QName value '%s' has no corresponding namespace "
5104 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005105 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005106 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005107 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005108 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005109}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00005110#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00005111
5112/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005113 * xmlSchemaPValAttrNodeQNameValue:
5114 * @ctxt: a schema parser context
5115 * @schema: the schema context
5116 * @ownerDes: the designation of the parent element
5117 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005118 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00005119 * @local: the resulting local part if found, the attribute value otherwise
5120 * @uri: the resulting namespace URI if found
5121 *
5122 * Extracts the local name and the URI of a QName value and validates it.
5123 * This one is intended to be used on attribute values that
5124 * should resolve to schema components.
5125 *
5126 * Returns 0, in case the QName is valid, a positive error code
5127 * if not valid and -1 if an internal error occurs.
5128 */
5129static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005130xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005131 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005132 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005133 xmlSchemaTypePtr ownerItem,
5134 xmlAttrPtr attr,
5135 const xmlChar *value,
5136 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005137 const xmlChar **local)
5138{
5139 const xmlChar *pref;
5140 xmlNsPtr ns;
5141 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005142
Daniel Veillardc0826a72004-08-10 14:17:33 +00005143 *uri = NULL;
5144 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005145 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005146 if (ret > 0) {
5147 xmlSchemaPSimpleTypeErr(ctxt,
5148 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5149 ownerItem, (xmlNodePtr) attr,
5150 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5151 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005152 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005153 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005154 } else if (ret < 0)
5155 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005156
5157 if (!strchr((char *) value, ':')) {
Daniel Veillard24505b02005-07-28 23:49:35 +00005158 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005159 if (ns)
5160 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5161 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5162 /*
5163 * This one takes care of included schemas with no
5164 * target namespace.
5165 */
5166 *uri = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005167 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005168 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005169 return (0);
5170 }
5171 /*
5172 * At this point xmlSplitQName3 has to return a local name.
5173 */
5174 *local = xmlSplitQName3(value, &len);
5175 *local = xmlDictLookup(ctxt->dict, *local, -1);
5176 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005177 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5178 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005179 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005180 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005181 ownerItem, (xmlNodePtr) attr,
5182 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5183 "The value '%s' of simple type 'xs:QName' has no "
5184 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005185 return (ctxt->err);
5186 } else {
5187 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005188 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005189 return (0);
5190}
5191
5192/**
5193 * xmlSchemaPValAttrNodeQName:
5194 * @ctxt: a schema parser context
5195 * @schema: the schema context
5196 * @ownerDes: the designation of the owner element
5197 * @ownerItem: the owner as a schema object
5198 * @attr: the attribute node
5199 * @local: the resulting local part if found, the attribute value otherwise
5200 * @uri: the resulting namespace URI if found
5201 *
5202 * Extracts and validates the QName of an attribute value.
5203 * This one is intended to be used on attribute values that
5204 * should resolve to schema components.
5205 *
5206 * Returns 0, in case the QName is valid, a positive error code
5207 * if not valid and -1 if an internal error occurs.
5208 */
5209static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005210xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005211 xmlSchemaPtr schema,
5212 xmlChar **ownerDes,
5213 xmlSchemaTypePtr ownerItem,
5214 xmlAttrPtr attr,
5215 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005216 const xmlChar **local)
5217{
5218 const xmlChar *value;
5219
5220 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005221 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5222 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005223}
5224
5225/**
5226 * xmlSchemaPValAttrQName:
5227 * @ctxt: a schema parser context
5228 * @schema: the schema context
5229 * @ownerDes: the designation of the parent element
5230 * @ownerItem: the owner as a schema object
5231 * @ownerElem: the parent node of the attribute
5232 * @name: the name of the attribute
5233 * @local: the resulting local part if found, the attribute value otherwise
5234 * @uri: the resulting namespace URI if found
5235 *
5236 * Extracts and validates the QName of an attribute value.
5237 *
5238 * Returns 0, in case the QName is valid, a positive error code
5239 * if not valid and -1 if an internal error occurs.
5240 */
5241static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005242xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5243 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005244 xmlChar **ownerDes,
5245 xmlSchemaTypePtr ownerItem,
5246 xmlNodePtr ownerElem,
5247 const char *name,
5248 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005249 const xmlChar **local)
5250{
5251 xmlAttrPtr attr;
5252
5253 attr = xmlSchemaGetPropNode(ownerElem, name);
5254 if (attr == NULL) {
5255 *local = NULL;
5256 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005257 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005258 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005259 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5260 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005261}
5262
5263/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005264 * xmlSchemaPValAttrID:
5265 * @ctxt: a schema parser context
5266 * @schema: the schema context
5267 * @ownerDes: the designation of the parent element
5268 * @ownerItem: the owner as a schema object
5269 * @ownerElem: the parent node of the attribute
5270 * @name: the name of the attribute
5271 *
5272 * Extracts and validates the ID of an attribute value.
5273 *
5274 * Returns 0, in case the ID is valid, a positive error code
5275 * if not valid and -1 if an internal error occurs.
5276 */
5277static int
5278xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005279 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005280 xmlSchemaTypePtr ownerItem,
5281 xmlNodePtr ownerElem,
5282 const xmlChar *name)
5283{
5284 int ret;
5285 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005286 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005287
5288 value = xmlGetNoNsProp(ownerElem, name);
5289 if (value == NULL)
5290 return (0);
5291
5292 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5293 if (attr == NULL)
5294 return (-1);
5295
5296 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005297 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005298 /*
5299 * NOTE: the IDness might have already be declared in the DTD
5300 */
5301 if (attr->atype != XML_ATTRIBUTE_ID) {
5302 xmlIDPtr res;
5303 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005304
5305 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005306 * TODO: Use xmlSchemaStrip here; it's not exported at this
5307 * moment.
5308 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005309 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005310 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005311 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005312 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5313 if (res == NULL) {
5314 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005315 xmlSchemaPSimpleTypeErr(ctxt,
5316 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5317 ownerItem, (xmlNodePtr) attr,
5318 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5319 NULL, NULL, "Duplicate value '%s' of simple "
5320 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005321 } else
5322 attr->atype = XML_ATTRIBUTE_ID;
5323 if (strip != NULL)
5324 xmlFree(strip);
5325 }
5326 } else if (ret > 0) {
5327 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005328 xmlSchemaPSimpleTypeErr(ctxt,
5329 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5330 ownerItem, (xmlNodePtr) attr,
5331 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5332 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5333 "not a valid 'xs:NCName'",
5334 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005335 }
5336 xmlFree(value);
5337
5338 return (ret);
5339}
5340
5341/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005342 * xmlGetMaxOccurs:
5343 * @ctxt: a schema validation context
5344 * @node: a subtree containing XML Schema informations
5345 *
5346 * Get the maxOccurs property
5347 *
5348 * Returns the default if not found, or the value
5349 */
5350static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005351xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5352 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005353{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005354 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005355 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005356 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005357
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005358 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5359 if (attr == NULL)
5360 return (def);
5361 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005362
5363 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005364 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005365 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005366 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5367 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005368 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005369 val, NULL, NULL, NULL);
5370 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005371 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005372 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005373 }
5374
5375 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005376 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005377 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005378 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005379 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005380 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5381 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005382 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005383 val, NULL, NULL, NULL);
5384 return (def);
5385 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005386 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005387 ret = ret * 10 + (*cur - '0');
5388 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005389 }
William M. Brack76e95df2003-10-18 16:20:14 +00005390 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005391 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005392 /*
5393 * TODO: Restrict the maximal value to Integer.
5394 */
5395 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005396 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005397 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5398 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005399 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005400 val, NULL, NULL, NULL);
5401 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005402 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005403 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005404}
5405
5406/**
5407 * xmlGetMinOccurs:
5408 * @ctxt: a schema validation context
5409 * @node: a subtree containing XML Schema informations
5410 *
5411 * Get the minOccurs property
5412 *
5413 * Returns the default if not found, or the value
5414 */
5415static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005416xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005417 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005418{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005419 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005420 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005421 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005422
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005423 attr = xmlSchemaGetPropNode(node, "minOccurs");
5424 if (attr == NULL)
5425 return (def);
5426 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005427 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005428 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005429 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005430 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005431 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005432 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5433 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005434 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005435 val, NULL, NULL, NULL);
5436 return (def);
5437 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005438 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005439 ret = ret * 10 + (*cur - '0');
5440 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005441 }
William M. Brack76e95df2003-10-18 16:20:14 +00005442 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005443 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005444 /*
5445 * TODO: Restrict the maximal value to Integer.
5446 */
5447 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005448 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005449 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5450 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005451 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005452 val, NULL, NULL, NULL);
5453 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005454 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005455 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005456}
5457
5458/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005459 * xmlSchemaPGetBoolNodeValue:
5460 * @ctxt: a schema validation context
5461 * @ownerDes: owner designation
5462 * @ownerItem: the owner as a schema item
5463 * @node: the node holding the value
5464 *
5465 * Converts a boolean string value into 1 or 0.
5466 *
5467 * Returns 0 or 1.
5468 */
5469static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005470xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5471 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005472 xmlSchemaTypePtr ownerItem,
5473 xmlNodePtr node)
5474{
5475 xmlChar *value = NULL;
5476 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005477
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005478 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005479 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005480 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005481 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005482 * can have the following legal literals {true, false, 1, 0}.
5483 */
5484 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5485 res = 1;
5486 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5487 res = 0;
5488 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5489 res = 1;
5490 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005491 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005492 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005493 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005494 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005495 ownerItem, node,
5496 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5497 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005498 NULL, NULL, NULL);
5499 }
5500 if (value != NULL)
5501 xmlFree(value);
5502 return (res);
5503}
5504
5505/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005506 * xmlGetBooleanProp:
5507 * @ctxt: a schema validation context
5508 * @node: a subtree containing XML Schema informations
5509 * @name: the attribute name
5510 * @def: the default value
5511 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005512 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005513 *
5514 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005515 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005516 */
5517static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005518xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5519 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005520 xmlSchemaTypePtr ownerItem,
5521 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005522 const char *name, int def)
5523{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005524 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005525
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005526 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005527 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005528 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005529 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005530 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005531 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005532 * can have the following legal literals {true, false, 1, 0}.
5533 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005534 if (xmlStrEqual(val, BAD_CAST "true"))
5535 def = 1;
5536 else if (xmlStrEqual(val, BAD_CAST "false"))
5537 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005538 else if (xmlStrEqual(val, BAD_CAST "1"))
5539 def = 1;
5540 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005541 def = 0;
5542 else {
5543 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005544 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005545 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005546 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005547 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5548 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005549 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005550 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005551}
5552
5553/************************************************************************
5554 * *
5555 * Shema extraction from an Infoset *
5556 * *
5557 ************************************************************************/
5558static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5559 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005560 xmlNodePtr node,
5561 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005562static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5563 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005564 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005565 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005566 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005567static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5568 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005569 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005570 xmlNodePtr node,
5571 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005572static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5573 ctxt,
5574 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005575 xmlNodePtr node,
5576 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005577static xmlSchemaAttributeGroupPtr
5578xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005579 xmlSchemaPtr schema, xmlNodePtr node,
5580 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005581static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5582 xmlSchemaPtr schema,
5583 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005584static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005585xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5586 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005587
5588/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005589 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005590 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005591 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005592 * @ownerDes: the designation of the parent element
5593 * @ownerItem: the schema object owner if existent
5594 * @attr: the schema attribute node being validated
5595 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005596 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005597 *
5598 * Validates a value against the given built-in type.
5599 * This one is intended to be used internally for validation
5600 * of schema attribute values during parsing of the schema.
5601 *
5602 * Returns 0 if the value is valid, a positive error code
5603 * number otherwise and -1 in case of an internal or API error.
5604 */
5605static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005606xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5607 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5608 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005609 xmlAttrPtr attr,
5610 const xmlChar *value,
5611 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005612{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005613
5614 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005615
5616 /*
5617 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5618 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005619 */
5620 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005621 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005622 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5623 PERROR_INT("xmlSchemaPValAttrNodeValue",
5624 "the given type is not a built-in type");
5625 return (-1);
5626 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005627 switch (type->builtInType) {
5628 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005629 case XML_SCHEMAS_QNAME:
5630 case XML_SCHEMAS_ANYURI:
5631 case XML_SCHEMAS_TOKEN:
5632 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005633 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5634 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005635 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005636 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005637 PERROR_INT("xmlSchemaPValAttrNodeValue",
5638 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005639 return (-1);
5640 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005641 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005642 /*
5643 * TODO: Should we use the S4S error codes instead?
5644 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005645 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005646 PERROR_INT("xmlSchemaPValAttrNodeValue",
5647 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005648 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005649 } else if (ret > 0) {
5650 if (VARIETY_LIST(type))
5651 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5652 else
5653 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5654 xmlSchemaPSimpleTypeErr(pctxt,
5655 ret, ownerItem, (xmlNodePtr) attr,
5656 type, NULL, value, NULL, NULL, NULL);
5657 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005658 return (ret);
5659}
5660
5661/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005662 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005663 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005664 * @ctxt: a schema parser context
5665 * @ownerDes: the designation of the parent element
5666 * @ownerItem: the schema object owner if existent
5667 * @attr: the schema attribute node being validated
5668 * @type: the built-in type to be validated against
5669 * @value: the resulting value if any
5670 *
5671 * Extracts and validates a value against the given built-in type.
5672 * This one is intended to be used internally for validation
5673 * of schema attribute values during parsing of the schema.
5674 *
5675 * Returns 0 if the value is valid, a positive error code
5676 * number otherwise and -1 in case of an internal or API error.
5677 */
5678static int
5679xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5680 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005681 xmlSchemaTypePtr ownerItem,
5682 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005683 xmlSchemaTypePtr type,
5684 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005685{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005686 const xmlChar *val;
5687
5688 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005689 return (-1);
5690
Daniel Veillardc0826a72004-08-10 14:17:33 +00005691 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5692 if (value != NULL)
5693 *value = val;
5694
5695 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005696 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005697}
5698
5699/**
5700 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005701 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005702 * @ctxt: a schema parser context
5703 * @node: the element node of the attribute
5704 * @ownerDes: the designation of the parent element
5705 * @ownerItem: the schema object owner if existent
5706 * @ownerElem: the owner element node
5707 * @name: the name of the schema attribute node
5708 * @type: the built-in type to be validated against
5709 * @value: the resulting value if any
5710 *
5711 * Extracts and validates a value against the given built-in type.
5712 * This one is intended to be used internally for validation
5713 * of schema attribute values during parsing of the schema.
5714 *
5715 * Returns 0 if the value is valid, a positive error code
5716 * number otherwise and -1 in case of an internal or API error.
5717 */
5718static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005719xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005720 xmlChar **ownerDes,
5721 xmlSchemaTypePtr ownerItem,
5722 xmlNodePtr ownerElem,
5723 const char *name,
5724 xmlSchemaTypePtr type,
5725 const xmlChar **value)
5726{
5727 xmlAttrPtr attr;
5728
5729 if ((ctxt == NULL) || (type == NULL)) {
5730 if (value != NULL)
5731 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005732 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005733 }
5734 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5735 if (value != NULL)
5736 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005737 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005738 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005739 "Internal error: xmlSchemaPValAttr, the given "
5740 "type '%s' is not a built-in type.\n",
5741 type->name, NULL);
5742 return (-1);
5743 }
5744 attr = xmlSchemaGetPropNode(ownerElem, name);
5745 if (attr == NULL) {
5746 if (value != NULL)
5747 *value = NULL;
5748 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005749 }
5750 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005751 type, value));
5752}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005753
5754static int
5755xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5756 xmlSchemaPtr schema,
5757 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005758 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005759 const xmlChar *namespaceName)
5760{
5761 if (xmlStrEqual(schema->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005762 return (1);
5763 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5764 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005765 if (pctxt->localImports != NULL) {
5766 int i;
5767 for (i = 0; i < pctxt->nbLocalImports; i++)
5768 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5769 return (1);
5770 }
5771 if (namespaceName == NULL)
5772 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005773 NULL, (xmlSchemaTypePtr) item, node,
5774 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005775 "namespace are not valid, since not indicated by an import "
5776 "statement", NULL);
5777 else
5778 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005779 NULL, (xmlSchemaTypePtr) item, node,
5780 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005781 "namespace '%s' are not valid, since not indicated by an import "
5782 "statement", namespaceName);
5783 return (0);
5784}
5785
Daniel Veillardc0826a72004-08-10 14:17:33 +00005786/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005787 * xmlSchemaParseAttrDecls:
5788 * @ctxt: a schema validation context
5789 * @schema: the schema being built
5790 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005791 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005792 *
5793 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005794 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005795 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5796 */
5797static xmlNodePtr
5798xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5799 xmlNodePtr child, xmlSchemaTypePtr type)
5800{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005801 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005802
Daniel Veillard4255d502002-04-16 15:50:10 +00005803 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005804 (IS_SCHEMA(child, "attributeGroup"))) {
5805 attr = NULL;
5806 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005807 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005808 } else if (IS_SCHEMA(child, "attributeGroup")) {
5809 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005810 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005811 }
5812 if (attr != NULL) {
5813 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005814 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5815 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5816 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005817 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005818 lastattr = attr;
5819 } else {
5820 lastattr->next = attr;
5821 lastattr = attr;
5822 }
5823 }
5824 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005825 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005826 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005827}
5828
5829/**
5830 * xmlSchemaParseAnnotation:
5831 * @ctxt: a schema validation context
5832 * @schema: the schema being built
5833 * @node: a subtree containing XML Schema informations
5834 *
5835 * parse a XML schema Attrribute declaration
5836 * *WARNING* this interface is highly subject to change
5837 *
William M. Bracke7091952004-05-11 15:09:58 +00005838 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005839 * 1 in case of success.
5840 */
5841static xmlSchemaAnnotPtr
5842xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5843 xmlNodePtr node)
5844{
5845 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005846 xmlNodePtr child = NULL;
5847 xmlAttrPtr attr;
5848 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005849
Daniel Veillardc0826a72004-08-10 14:17:33 +00005850 /*
5851 * INFO: S4S completed.
5852 */
5853 /*
5854 * id = ID
5855 * {any attributes with non-schema namespace . . .}>
5856 * Content: (appinfo | documentation)*
5857 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005858 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5859 return (NULL);
5860 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005861 attr = node->properties;
5862 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005863 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005864 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005865 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005866 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005867
5868 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005869 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5870 NULL, NULL, attr);
5871 }
5872 attr = attr->next;
5873 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005874 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005875 /*
5876 * And now for the children...
5877 */
5878 child = node->children;
5879 while (child != NULL) {
5880 if (IS_SCHEMA(child, "appinfo")) {
5881 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005882 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005883 * source = anyURI
5884 * {any attributes with non-schema namespace . . .}>
5885 * Content: ({any})*
5886 */
5887 attr = child->properties;
5888 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005889 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005890 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005891 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005892 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005893
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005894 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005895 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5896 NULL, NULL, attr);
5897 }
5898 attr = attr->next;
5899 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005900 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5901 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005902 child = child->next;
5903 } else if (IS_SCHEMA(child, "documentation")) {
5904 /* TODO: make available the content of "documentation". */
5905 /*
5906 * source = anyURI
5907 * {any attributes with non-schema namespace . . .}>
5908 * Content: ({any})*
5909 */
5910 attr = child->properties;
5911 while (attr != NULL) {
5912 if (attr->ns == NULL) {
5913 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005914 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005915 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5916 NULL, NULL, attr);
5917 }
5918 } else {
5919 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5920 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5921 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005922
5923 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005924 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5925 NULL, NULL, attr);
5926 }
5927 }
5928 attr = attr->next;
5929 }
5930 /*
5931 * Attribute "xml:lang".
5932 */
5933 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5934 if (attr != NULL)
5935 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005936 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005937 child = child->next;
5938 } else {
5939 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005940 xmlSchemaPContentErr(ctxt,
5941 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005942 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5943 barked = 1;
5944 child = child->next;
5945 }
5946 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005947
Daniel Veillard4255d502002-04-16 15:50:10 +00005948 return (ret);
5949}
5950
5951/**
5952 * xmlSchemaParseFacet:
5953 * @ctxt: a schema validation context
5954 * @schema: the schema being built
5955 * @node: a subtree containing XML Schema informations
5956 *
5957 * parse a XML schema Facet declaration
5958 * *WARNING* this interface is highly subject to change
5959 *
5960 * Returns the new type structure or NULL in case of error
5961 */
5962static xmlSchemaFacetPtr
5963xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005964 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005965{
5966 xmlSchemaFacetPtr facet;
5967 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005968 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005969
5970 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5971 return (NULL);
5972
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005973 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005974 if (facet == NULL) {
5975 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5976 return (NULL);
5977 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005978 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005979 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005980 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005981 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5982 "Facet %s has no value\n", node->name, NULL);
5983 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005984 return (NULL);
5985 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005986 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005987 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005988 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005989 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005990 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005991 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005992 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005993 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005994 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005995 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005996 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005997 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005998 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005999 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006000 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006001 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006002 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006003 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006004 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006005 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006006 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006007 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6008 } else if (IS_SCHEMA(node, "minLength")) {
6009 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6010 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006011 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6012 "Unknown facet type %s\n", node->name, NULL);
6013 xmlSchemaFreeFacet(facet);
6014 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006015 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006016 xmlSchemaPValAttrID(ctxt, NULL,
6017 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006018 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006019 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6020 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6021 const xmlChar *fixed;
6022
6023 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6024 if (fixed != NULL) {
6025 if (xmlStrEqual(fixed, BAD_CAST "true"))
6026 facet->fixed = 1;
6027 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006028 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006029 child = node->children;
6030
6031 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006032 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6033 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006034 }
6035 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006036 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6037 "Facet %s has unexpected child content\n",
6038 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006039 }
6040 return (facet);
6041}
6042
6043/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006044 * xmlSchemaParseWildcardNs:
6045 * @ctxt: a schema parser context
6046 * @wildc: the wildcard, already created
6047 * @node: a subtree containing XML Schema informations
6048 *
6049 * Parses the attribute "processContents" and "namespace"
6050 * of a xsd:anyAttribute and xsd:any.
6051 * *WARNING* this interface is highly subject to change
6052 *
6053 * Returns 0 if everything goes fine, a positive error code
6054 * if something is not valid and -1 if an internal error occurs.
6055 */
6056static int
6057xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6058 xmlSchemaPtr schema,
6059 xmlSchemaWildcardPtr wildc,
6060 xmlNodePtr node)
6061{
6062 const xmlChar *pc, *ns, *dictnsItem;
6063 int ret = 0;
6064 xmlChar *nsItem;
6065 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6066 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006067
Daniel Veillardc0826a72004-08-10 14:17:33 +00006068 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6069 if ((pc == NULL)
6070 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6071 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6072 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6073 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6074 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6075 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6076 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006077 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006078 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006079 NULL, node,
6080 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006081 NULL, NULL, NULL);
6082 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006083 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006084 }
6085 /*
6086 * Build the namespace constraints.
6087 */
6088 attr = xmlSchemaGetPropNode(node, "namespace");
6089 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006090 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006091 wildc->any = 1;
6092 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6093 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006094 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006095 return (-1);
6096 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006097 wildc->negNsSet->value = schema->targetNamespace;
6098 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006099 const xmlChar *end, *cur;
6100
6101 cur = ns;
6102 do {
6103 while (IS_BLANK_CH(*cur))
6104 cur++;
6105 end = cur;
6106 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6107 end++;
6108 if (end == cur)
6109 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006110 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006111 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6112 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006113 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006114 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006115 NULL, (xmlNodePtr) attr,
6116 NULL,
6117 "((##any | ##other) | List of (xs:anyURI | "
6118 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006119 nsItem, NULL, NULL, NULL);
6120 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6121 } else {
6122 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6123 dictnsItem = schema->targetNamespace;
6124 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6125 dictnsItem = NULL;
6126 } else {
6127 /*
6128 * Validate the item (anyURI).
6129 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006130 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006131 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6132 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6133 }
6134 /*
6135 * Avoid dublicate namespaces.
6136 */
6137 tmp = wildc->nsSet;
6138 while (tmp != NULL) {
6139 if (dictnsItem == tmp->value)
6140 break;
6141 tmp = tmp->next;
6142 }
6143 if (tmp == NULL) {
6144 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6145 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006146 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006147 return (-1);
6148 }
6149 tmp->value = dictnsItem;
6150 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006151 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006152 wildc->nsSet = tmp;
6153 else
6154 lastNs->next = tmp;
6155 lastNs = tmp;
6156 }
6157
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006158 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006159 xmlFree(nsItem);
6160 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006161 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006162 }
6163 return (ret);
6164}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006165
6166static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006167xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6168 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006169 xmlNodePtr node,
6170 int minOccurs,
6171 int maxOccurs) {
6172
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006173 if ((maxOccurs == 0) && ( minOccurs == 0))
6174 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006175 if (maxOccurs != UNBOUNDED) {
6176 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006177 * TODO: Maybe we should better not create the particle,
6178 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006179 * content model.
6180 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006181 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006182 * 3.9.6 Schema Component Constraint: Particle Correct
6183 *
6184 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006185 if (maxOccurs < 1) {
6186 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006187 * 2.2 {max occurs} must be greater than or equal to 1.
6188 */
6189 xmlSchemaPCustomAttrErr(ctxt,
6190 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006191 NULL, NULL,
6192 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006193 "The value must be greater than or equal to 1");
6194 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6195 } else if (minOccurs > maxOccurs) {
6196 /*
6197 * 2.1 {min occurs} must not be greater than {max occurs}.
6198 */
6199 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006200 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006201 NULL, NULL,
6202 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006203 "The value must not be greater than the value of 'maxOccurs'");
6204 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6205 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006206 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006207 return (0);
6208}
6209
Daniel Veillardc0826a72004-08-10 14:17:33 +00006210/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006211 * xmlSchemaParseAny:
6212 * @ctxt: a schema validation context
6213 * @schema: the schema being built
6214 * @node: a subtree containing XML Schema informations
6215 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006216 * Parsea a XML schema <any> element. A particle and wildcard
6217 * will be created (except if minOccurs==maxOccurs==0, in this case
6218 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006219 * *WARNING* this interface is highly subject to change
6220 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006221 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006222 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006223static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006224xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6225 xmlNodePtr node)
6226{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006227 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006228 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006229 xmlSchemaWildcardPtr wild;
6230 int min, max;
6231 xmlAttrPtr attr;
6232 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006233
6234 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6235 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006236 /*
6237 * Check for illegal attributes.
6238 */
6239 attr = node->properties;
6240 while (attr != NULL) {
6241 if (attr->ns == NULL) {
6242 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6243 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6244 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6245 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6246 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006247 xmlSchemaPIllegalAttrErr(ctxt,
6248 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6249 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006250 }
6251 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006252 xmlSchemaPIllegalAttrErr(ctxt,
6253 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6254 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006255 }
6256 attr = attr->next;
6257 }
6258 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6259 /*
6260 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006261 */
6262 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6263 "(xs:nonNegativeInteger | unbounded)");
6264 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6265 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006266 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6267 /*
6268 * Create & parse the wildcard.
6269 */
6270 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6271 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006272 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006273 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006274 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006275 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006276 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006277 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006278 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006279 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006280 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006281 }
6282 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006283 xmlSchemaPContentErr(ctxt,
6284 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006285 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006286 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006287 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006288 /*
6289 * No component if minOccurs==maxOccurs==0.
6290 */
6291 if ((min == 0) && (max == 0)) {
6292 /* Don't free the wildcard, since it's already on the list. */
6293 return (NULL);
6294 }
6295 /*
6296 * Create the particle.
6297 */
6298 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6299 if (particle == NULL)
6300 return (NULL);
6301 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006302 wild->minOccurs = min;
6303 wild->maxOccurs = max;
6304 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006305
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006306 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006307}
6308
6309/**
6310 * xmlSchemaParseNotation:
6311 * @ctxt: a schema validation context
6312 * @schema: the schema being built
6313 * @node: a subtree containing XML Schema informations
6314 *
6315 * parse a XML schema Notation declaration
6316 *
6317 * Returns the new structure or NULL in case of error
6318 */
6319static xmlSchemaNotationPtr
6320xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006321 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006322{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006323 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006324 xmlSchemaNotationPtr ret;
6325 xmlNodePtr child = NULL;
6326
6327 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6328 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006329 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006330 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006331 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6332 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006333 return (NULL);
6334 }
6335 ret = xmlSchemaAddNotation(ctxt, schema, name);
6336 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006337 return (NULL);
6338 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006339 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006340
6341 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6342 node, BAD_CAST "id");
6343
6344 if (IS_SCHEMA(child, "annotation")) {
6345 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6346 child = child->next;
6347 }
6348
Daniel Veillard4255d502002-04-16 15:50:10 +00006349 child = node->children;
6350 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006351 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6352 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 }
6360
6361 return (ret);
6362}
6363
6364/**
6365 * xmlSchemaParseAnyAttribute:
6366 * @ctxt: a schema validation context
6367 * @schema: the schema being built
6368 * @node: a subtree containing XML Schema informations
6369 *
6370 * parse a XML schema AnyAttrribute declaration
6371 * *WARNING* this interface is highly subject to change
6372 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006373 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006374 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006375static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006376xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6377 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006378{
Daniel Veillard3646d642004-06-02 19:19:14 +00006379 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006380 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006381 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006382
6383 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6384 return (NULL);
6385
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006386 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6387 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006388 if (ret == NULL) {
6389 return (NULL);
6390 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006391 /*
6392 * Check for illegal attributes.
6393 */
6394 attr = node->properties;
6395 while (attr != NULL) {
6396 if (attr->ns == NULL) {
6397 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6398 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6399 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006400 xmlSchemaPIllegalAttrErr(ctxt,
6401 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6402 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006403 }
6404 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006405 xmlSchemaPIllegalAttrErr(ctxt,
6406 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6407 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006408 }
6409 attr = attr->next;
6410 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006411 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6412 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006413 /*
6414 * Parse the namespace list.
6415 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006416 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006417 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006418 /*
6419 * And now for the children...
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) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006427 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006428 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006429 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006430 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006431 }
6432
6433 return (ret);
6434}
6435
6436
6437/**
6438 * xmlSchemaParseAttribute:
6439 * @ctxt: a schema validation context
6440 * @schema: the schema being built
6441 * @node: a subtree containing XML Schema informations
6442 *
6443 * parse a XML schema Attrribute declaration
6444 * *WARNING* this interface is highly subject to change
6445 *
William M. Bracke7091952004-05-11 15:09:58 +00006446 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006447 */
6448static xmlSchemaAttributePtr
6449xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006450 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006451{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006452 const xmlChar *name, *attrValue;
6453 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006454 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006455 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006456 xmlAttrPtr attr, nameAttr;
6457 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006458
6459 /*
6460 * Note that the w3c spec assumes the schema to be validated with schema
6461 * for schemas beforehand.
6462 *
6463 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006464 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006465
6466 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6467 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006468 attr = xmlSchemaGetPropNode(node, "ref");
6469 nameAttr = xmlSchemaGetPropNode(node, "name");
6470
6471 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006472 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006473 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006474 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006475 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006476 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6477 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006478 "One of the attributes 'ref' or 'name' must be present");
6479 return (NULL);
6480 }
6481 if ((topLevel) || (attr == NULL)) {
6482 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006483 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6484 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006485 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006486 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006487 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006488 isRef = 1;
6489
Daniel Veillardc0826a72004-08-10 14:17:33 +00006490 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006491 char buf[50];
6492 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006493
6494 /*
6495 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006496 */
6497 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6498 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6499 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006500 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006501 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006502 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006503 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006504 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006505 if (ret == NULL) {
6506 if (repName != NULL)
6507 xmlFree(repName);
6508 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006509 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006510 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6511 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006512 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006513 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006514 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6515 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006516 /*
6517 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6518 */
6519 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006520 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6521 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006522 "ref", "name");
6523 /*
6524 * Check for illegal attributes.
6525 */
6526 attr = node->properties;
6527 while (attr != NULL) {
6528 if (attr->ns == NULL) {
6529 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6530 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006531 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006532 * 3.2.3 : 3.2
6533 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006534 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006535 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006536 xmlSchemaPIllegalAttrErr(ctxt,
6537 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006538 (xmlSchemaTypePtr) ret, attr);
6539 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6540 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6541 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006542 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6543 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006544 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006545 xmlSchemaPIllegalAttrErr(ctxt,
6546 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6547 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006548 }
6549 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006550 xmlSchemaPIllegalAttrErr(ctxt,
6551 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6552 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006553 }
6554 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006555 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006556 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006557 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006558
Daniel Veillardc0826a72004-08-10 14:17:33 +00006559 /*
6560 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006561 */
6562 if (xmlSchemaPValAttrNode(ctxt,
6563 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006564 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6565 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006566 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006567 /*
6568 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6569 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006570 /*
6571 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6572 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006573 */
6574 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006575 xmlSchemaPSimpleTypeErr(ctxt,
6576 XML_SCHEMAP_NO_XMLNS,
6577 NULL, (xmlNodePtr) nameAttr,
6578 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6579 "The value of type 'xs:NCName' must not match 'xmlns'",
6580 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006581 if (repName != NULL)
6582 xmlFree(repName);
6583 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006584 }
6585 /*
6586 * Evaluate the target namespace
6587 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006588 if (topLevel) {
6589 ns = schema->targetNamespace;
6590 } else {
6591 attr = xmlSchemaGetPropNode(node, "form");
6592 if (attr != NULL) {
6593 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6594 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6595 ns = schema->targetNamespace;
6596 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006597 xmlSchemaPSimpleTypeErr(ctxt,
6598 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6599 NULL, (xmlNodePtr) attr,
6600 NULL, "(qualified | unqualified)",
6601 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006602 }
6603 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006604 ns = schema->targetNamespace;
6605 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006606 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006607 if (ret == NULL) {
6608 if (repName != NULL)
6609 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006610 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006611 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006612 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006613 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006614 if (topLevel)
6615 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006616 /*
6617 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6618 * TODO: Move this to the component layer.
6619 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006620 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006621 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006622 XML_SCHEMAP_NO_XSI,
6623 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006624 "The target namespace must not match '%s'",
6625 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006626 }
6627 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006628 * Check for illegal attributes.
6629 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006630 attr = node->properties;
6631 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006632 if (attr->ns == NULL) {
6633 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6634 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6635 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006636 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6637 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006638 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006639 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6640 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006641 xmlSchemaPIllegalAttrErr(ctxt,
6642 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6643 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006644 }
6645 }
6646 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006647 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6648 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006649 }
6650 attr = attr->next;
6651 }
6652 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006653 node, "type", &ret->typeNs, &ret->typeName);
6654 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006655 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6656 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006657 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006658 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006659 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006660 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6661 if (ret->defValue != NULL)
6662 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006663 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006664 * Attribute "default".
6665 */
6666 attr = xmlSchemaGetPropNode(node, "default");
6667 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006668 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006669 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006670 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006671 */
6672 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6673 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6674 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6675 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006676 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6677 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006678 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006679 /*
6680 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006681 */
6682 attr = xmlSchemaGetPropNode(node, "use");
6683 if (attr != NULL) {
6684 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6685 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6686 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6687 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6688 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6689 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6690 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6691 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006692 xmlSchemaPSimpleTypeErr(ctxt,
6693 XML_SCHEMAP_INVALID_ATTR_USE,
6694 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6695 NULL, "(optional | prohibited | required)",
6696 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006697 } else
6698 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006699 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006700 * 3.2.3 : 2
6701 * If default and use are both present, use must have
6702 * the actual value optional.
6703 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006704 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6705 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006706 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006707 xmlSchemaPSimpleTypeErr(ctxt,
6708 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6709 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6710 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006711 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006712 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006713 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006714 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006715 /*
6716 * And now for the children...
6717 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006718 child = node->children;
6719 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006720 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6721 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006722 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006723 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006724 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006725 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006726 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006727 * 3.2.3 : 3.2
6728 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006729 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006730 */
6731 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6732 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6733 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006734 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006735 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6736 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006737 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006738 }
6739 } else {
6740 if (IS_SCHEMA(child, "simpleType")) {
6741 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006742 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006743 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006744 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006745 */
6746 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6747 &repName, (xmlSchemaTypePtr) ret, node, child,
6748 "The attribute 'type' and the <simpleType> child "
6749 "are mutually exclusive", NULL);
6750 } else
6751 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6752 child = child->next;
6753 }
6754 if (child != NULL)
6755 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6756 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6757 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006758 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006759 /*
6760 * Cleanup.
6761 */
6762 if (repName != NULL)
6763 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006764 return (ret);
6765}
6766
6767/**
6768 * xmlSchemaParseAttributeGroup:
6769 * @ctxt: a schema validation context
6770 * @schema: the schema being built
6771 * @node: a subtree containing XML Schema informations
6772 *
6773 * parse a XML schema Attribute Group declaration
6774 * *WARNING* this interface is highly subject to change
6775 *
6776 * Returns the attribute group or NULL in case of error.
6777 */
6778static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006779xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006780 xmlSchemaPtr schema, xmlNodePtr node,
6781 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006782{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006783 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006784 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006785 xmlNodePtr child = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006786 const xmlChar *oldcontainer;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006787 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006788
6789 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6790 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006791
6792 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006793 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006794 if ((topLevel) || (attr == NULL)) {
6795 /*
6796 * Parse as an attribute group definition.
6797 * Note that those are allowed at top level only.
6798 */
6799 if (nameAttr == NULL) {
6800 xmlSchemaPMissingAttrErr(ctxt,
6801 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006802 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006803 return (NULL);
6804 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006805 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006806 * (xmlNodePtr) nameAttr);
6807 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006808 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006809 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006810 */
6811 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006812 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006813 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6814 return (NULL);
6815 }
6816 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6817 if (ret == NULL)
6818 return (NULL);
6819 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6820 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6821 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006822 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006823 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006824 char buf[50];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006825 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006826
6827 /*
6828 * Parse as an attribute group definition reference.
6829 */
6830 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006831 xmlSchemaPMissingAttrErr(ctxt,
6832 XML_SCHEMAP_S4S_ATTR_MISSING,
6833 NULL, node, "ref", NULL);
6834 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006835 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006836 NULL, NULL, attr, &refNs,&ref);
6837
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006838 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006839 name = (const xmlChar *) buf;
6840 if (name == NULL) {
6841 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6842 "attribute group definition reference", node);
6843 return (NULL);
6844 }
6845 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6846 if (ret == NULL)
6847 return (NULL);
6848 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6849 ret->ref = ref;
6850 ret->refNs = refNs;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006851 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006852 xmlSchemaCheckReference(ctxt, schema, node,
6853 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006854 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006855 /*
6856 * Check for illegal attributes.
6857 */
6858 attr = node->properties;
6859 while (attr != NULL) {
6860 if (attr->ns == NULL) {
6861 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6862 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006863 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006864 {
6865 xmlSchemaPIllegalAttrErr(ctxt,
6866 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6867 NULL, NULL, attr);
6868 }
6869 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6870 xmlSchemaPIllegalAttrErr(ctxt,
6871 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6872 NULL, NULL, attr);
6873 }
6874 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006875 }
6876 /* TODO: Validate "id" ? */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006877 /*
6878 * And now for the children...
6879 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006880 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006881 ctxt->container = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006882 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006883 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006884 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6885 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006886 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006887 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006888 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006889 if (IS_SCHEMA(child, "anyAttribute")) {
6890 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6891 child = child->next;
6892 }
6893 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006894 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006895 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006896 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6897 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006898 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006899 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006900 ctxt->container = oldcontainer;
6901 return (ret);
6902}
6903
6904/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006905 * xmlSchemaPValAttrFormDefault:
6906 * @value: the value
6907 * @flags: the flags to be modified
6908 * @flagQualified: the specific flag for "qualified"
6909 *
6910 * Returns 0 if the value is valid, 1 otherwise.
6911 */
6912static int
6913xmlSchemaPValAttrFormDefault(const xmlChar *value,
6914 int *flags,
6915 int flagQualified)
6916{
6917 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6918 if ((*flags & flagQualified) == 0)
6919 *flags |= flagQualified;
6920 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006921 return (1);
6922
William M. Brack2f2a6632004-08-20 23:09:47 +00006923 return (0);
6924}
6925
6926/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006927 * xmlSchemaPValAttrBlockFinal:
6928 * @value: the value
6929 * @flags: the flags to be modified
6930 * @flagAll: the specific flag for "#all"
6931 * @flagExtension: the specific flag for "extension"
6932 * @flagRestriction: the specific flag for "restriction"
6933 * @flagSubstitution: the specific flag for "substitution"
6934 * @flagList: the specific flag for "list"
6935 * @flagUnion: the specific flag for "union"
6936 *
6937 * Validates the value of the attribute "final" and "block". The value
6938 * is converted into the specified flag values and returned in @flags.
6939 *
6940 * Returns 0 if the value is valid, 1 otherwise.
6941 */
6942
6943static int
6944xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006945 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006946 int flagAll,
6947 int flagExtension,
6948 int flagRestriction,
6949 int flagSubstitution,
6950 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006951 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006952{
6953 int ret = 0;
6954
6955 /*
6956 * TODO: This does not check for dublicate entries.
6957 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006958 if ((flags == NULL) || (value == NULL))
6959 return (-1);
6960 if (value[0] == 0)
6961 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006962 if (xmlStrEqual(value, BAD_CAST "#all")) {
6963 if (flagAll != -1)
6964 *flags |= flagAll;
6965 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006966 if (flagExtension != -1)
6967 *flags |= flagExtension;
6968 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006969 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006970 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006971 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006972 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006973 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006974 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006975 *flags |= flagUnion;
6976 }
6977 } else {
6978 const xmlChar *end, *cur = value;
6979 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006980
Daniel Veillardc0826a72004-08-10 14:17:33 +00006981 do {
6982 while (IS_BLANK_CH(*cur))
6983 cur++;
6984 end = cur;
6985 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6986 end++;
6987 if (end == cur)
6988 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006989 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006990 if (xmlStrEqual(item, BAD_CAST "extension")) {
6991 if (flagExtension != -1) {
6992 if ((*flags & flagExtension) == 0)
6993 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006994 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006995 ret = 1;
6996 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6997 if (flagRestriction != -1) {
6998 if ((*flags & flagRestriction) == 0)
6999 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007000 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007001 ret = 1;
7002 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7003 if (flagSubstitution != -1) {
7004 if ((*flags & flagSubstitution) == 0)
7005 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007006 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007007 ret = 1;
7008 } else if (xmlStrEqual(item, BAD_CAST "list")) {
7009 if (flagList != -1) {
7010 if ((*flags & flagList) == 0)
7011 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007012 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007013 ret = 1;
7014 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7015 if (flagUnion != -1) {
7016 if ((*flags & flagUnion) == 0)
7017 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007018 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007019 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007020 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007021 ret = 1;
7022 if (item != NULL)
7023 xmlFree(item);
7024 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007025 } while ((ret == 0) && (*cur != 0));
7026 }
7027
Daniel Veillardc0826a72004-08-10 14:17:33 +00007028 return (ret);
7029}
7030
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007031static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007032xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007033 xmlSchemaIDCPtr idc,
7034 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007035 xmlAttrPtr attr,
7036 int isField)
7037{
7038 xmlNodePtr node;
7039
7040 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007041 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007042 * Schema Component Constraint: Selector Value OK
7043 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007044 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007045 * in [XPath].
7046 */
7047 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007048 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007049 XML_SCHEMAP_INTERNAL,
7050 "Internal error: xmlSchemaCheckCSelectorXPath, "
7051 "the selector is not specified.\n", NULL, NULL);
7052 return (-1);
7053 }
7054 if (attr == NULL)
7055 node = idc->node;
7056 else
7057 node = (xmlNodePtr) attr;
7058 if (selector->xpath == NULL) {
7059 xmlSchemaPCustomErr(ctxt,
7060 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007061 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7062 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007063 "The XPath expression of the selector is not valid", NULL);
7064 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7065 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007066 const xmlChar **nsArray = NULL;
7067 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007068 /*
7069 * Compile the XPath expression.
7070 */
7071 /*
7072 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007073 * TODO: Call xmlPatterncompile with different options for selector/
7074 * field.
7075 */
7076 nsList = xmlGetNsList(attr->doc, attr->parent);
7077 /*
7078 * Build an array of prefixes and namespaces.
7079 */
7080 if (nsList != NULL) {
7081 int i, count = 0;
7082 xmlNsPtr ns;
7083
7084 for (i = 0; nsList[i] != NULL; i++)
7085 count++;
7086
7087 nsArray = (const xmlChar **) xmlMalloc(
7088 (count * 2 + 1) * sizeof(const xmlChar *));
7089 if (nsArray == NULL) {
7090 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
7091 NULL);
7092 return (-1);
7093 }
7094 for (i = 0; i < count; i++) {
7095 ns = nsList[i];
7096 nsArray[2 * i] = nsList[i]->href;
7097 nsArray[2 * i + 1] = nsList[i]->prefix;
7098 }
7099 nsArray[count * 2] = NULL;
7100 xmlFree(nsList);
7101 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007102 /*
7103 * TODO: Differentiate between "selector" and "field".
7104 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007105 if (isField)
7106 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00007107 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007108 else
7109 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00007110 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007111 if (nsArray != NULL)
7112 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007113
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00007114 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007115 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00007116 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007117 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7118 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007119 "The XPath expression '%s' could not be "
7120 "compiled", selector->xpath);
7121 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007122 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007123 }
7124 return (0);
7125}
7126
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007127#define ADD_ANNOTATION(annot) \
7128 xmlSchemaAnnotPtr cur = item->annot; \
7129 if (item->annot == NULL) { \
7130 item->annot = annot; \
7131 return (annot); \
7132 } \
7133 cur = item->annot; \
7134 if (cur->next != NULL) { \
7135 cur = cur->next; \
7136 } \
7137 cur->next = annot;
7138
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007139/**
7140 * xmlSchemaAssignAnnotation:
7141 * @item: the schema component
7142 * @annot: the annotation
7143 *
7144 * Adds the annotation to the given schema component.
7145 *
7146 * Returns the given annotaion.
7147 */
7148static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007149xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
7150 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007151{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007152 if ((annItem == NULL) || (annot == NULL))
7153 return (NULL);
7154 switch (annItem->type) {
7155 case XML_SCHEMA_TYPE_ELEMENT: {
7156 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
7157 ADD_ANNOTATION(annot)
7158 }
7159 break;
7160 case XML_SCHEMA_TYPE_ATTRIBUTE: {
7161 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
7162 ADD_ANNOTATION(annot)
7163 }
7164 break;
7165 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
7166 case XML_SCHEMA_TYPE_ANY: {
7167 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
7168 ADD_ANNOTATION(annot)
7169 }
7170 break;
7171 case XML_SCHEMA_TYPE_PARTICLE:
7172 case XML_SCHEMA_TYPE_IDC_KEY:
7173 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007174 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007175 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
7176 ADD_ANNOTATION(annot)
7177 }
7178 break;
7179 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
7180 xmlSchemaAttributeGroupPtr item =
7181 (xmlSchemaAttributeGroupPtr) annItem;
7182 ADD_ANNOTATION(annot)
7183 }
7184 break;
7185 case XML_SCHEMA_TYPE_NOTATION: {
7186 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7187 ADD_ANNOTATION(annot)
7188 }
7189 break;
7190 case XML_SCHEMA_FACET_MININCLUSIVE:
7191 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7192 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7193 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7194 case XML_SCHEMA_FACET_TOTALDIGITS:
7195 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7196 case XML_SCHEMA_FACET_PATTERN:
7197 case XML_SCHEMA_FACET_ENUMERATION:
7198 case XML_SCHEMA_FACET_WHITESPACE:
7199 case XML_SCHEMA_FACET_LENGTH:
7200 case XML_SCHEMA_FACET_MAXLENGTH:
7201 case XML_SCHEMA_FACET_MINLENGTH: {
7202 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7203 ADD_ANNOTATION(annot)
7204 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007205 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007206 case XML_SCHEMA_TYPE_SIMPLE:
7207 case XML_SCHEMA_TYPE_COMPLEX: {
7208 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7209 ADD_ANNOTATION(annot)
7210 }
7211 break;
7212 case XML_SCHEMA_TYPE_GROUP: {
7213 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7214 ADD_ANNOTATION(annot)
7215 }
7216 break;
7217 case XML_SCHEMA_TYPE_SEQUENCE:
7218 case XML_SCHEMA_TYPE_CHOICE:
7219 case XML_SCHEMA_TYPE_ALL: {
7220 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7221 ADD_ANNOTATION(annot)
7222 }
7223 break;
7224 default:
7225 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007226 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007227 NULL, NULL, NULL,
7228 "Internal error: xmlSchemaAddAnnotation, "
7229 "The item is not a annotated schema component", NULL);
7230 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007231 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007232 return (annot);
7233}
7234
7235/**
7236 * xmlSchemaParseIDCSelectorAndField:
7237 * @ctxt: a schema validation context
7238 * @schema: the schema being built
7239 * @node: a subtree containing XML Schema informations
7240 *
7241 * Parses a XML Schema identity-contraint definition's
7242 * <selector> and <field> elements.
7243 *
7244 * Returns the parsed identity-constraint definition.
7245 */
7246static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007247xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007248 xmlSchemaPtr schema,
7249 xmlSchemaIDCPtr idc,
7250 xmlNodePtr node,
7251 int isField)
7252{
7253 xmlSchemaIDCSelectPtr item;
7254 xmlNodePtr child = NULL;
7255 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007256
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007257 /*
7258 * Check for illegal attributes.
7259 */
7260 attr = node->properties;
7261 while (attr != NULL) {
7262 if (attr->ns == NULL) {
7263 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7264 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007265 xmlSchemaPIllegalAttrErr(ctxt,
7266 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7267 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007268 }
7269 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007270 xmlSchemaPIllegalAttrErr(ctxt,
7271 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7272 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007273 }
7274 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007275 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007276 /*
7277 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007278 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007279 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7280 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007281 xmlSchemaPErrMemory(ctxt,
7282 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007283 NULL);
7284 return (NULL);
7285 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007286 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007287 /*
7288 * Attribute "xpath" (mandatory).
7289 */
7290 attr = xmlSchemaGetPropNode(node, "xpath");
7291 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007292 xmlSchemaPMissingAttrErr(ctxt,
7293 XML_SCHEMAP_S4S_ATTR_MISSING,
7294 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007295 "name", NULL);
7296 } else {
7297 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7298 /*
7299 * URGENT TODO: "field"s have an other syntax than "selector"s.
7300 */
7301
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007302 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7303 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007304 xmlSchemaPErr(ctxt,
7305 (xmlNodePtr) attr,
7306 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007307 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007308 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007309 NULL, NULL);
7310 }
7311
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007312 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007313 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007314 /*
7315 * And now for the children...
7316 */
7317 child = node->children;
7318 if (IS_SCHEMA(child, "annotation")) {
7319 /*
7320 * Add the annotation to the parent IDC.
7321 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007322 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007323 xmlSchemaParseAnnotation(ctxt, schema, child));
7324 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007325 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007326 if (child != NULL) {
7327 xmlSchemaPContentErr(ctxt,
7328 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007329 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007330 NULL, "(annotation?)");
7331 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007332
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007333 return (item);
7334}
7335
7336/**
7337 * xmlSchemaParseIDC:
7338 * @ctxt: a schema validation context
7339 * @schema: the schema being built
7340 * @node: a subtree containing XML Schema informations
7341 *
7342 * Parses a XML Schema identity-contraint definition.
7343 *
7344 * Returns the parsed identity-constraint definition.
7345 */
7346static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007347xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007348 xmlSchemaPtr schema,
7349 xmlNodePtr node,
7350 xmlSchemaTypeType idcCategory,
7351 const xmlChar *targetNamespace)
7352{
7353 xmlSchemaIDCPtr item = NULL;
7354 xmlNodePtr child = NULL;
7355 xmlAttrPtr attr;
7356 const xmlChar *name = NULL;
7357 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7358 int resAdd;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007359
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007360 /*
7361 * Check for illegal attributes.
7362 */
7363 attr = node->properties;
7364 while (attr != NULL) {
7365 if (attr->ns == NULL) {
7366 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7367 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7368 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7369 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007370 xmlSchemaPIllegalAttrErr(ctxt,
7371 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7372 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007373 }
7374 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007375 xmlSchemaPIllegalAttrErr(ctxt,
7376 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7377 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007378 }
7379 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007380 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007381 /*
7382 * Attribute "name" (mandatory).
7383 */
7384 attr = xmlSchemaGetPropNode(node, "name");
7385 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007386 xmlSchemaPMissingAttrErr(ctxt,
7387 XML_SCHEMAP_S4S_ATTR_MISSING,
7388 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007389 "name", NULL);
7390 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007391 } else if (xmlSchemaPValAttrNode(ctxt,
7392 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007393 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7394 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007395 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007396 /*
7397 * Create the component.
7398 */
7399 if (schema->idcDef == NULL)
7400 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007401 if (schema->idcDef == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007402 return (NULL);
7403
7404 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7405 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007406 xmlSchemaPErrMemory(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007407 "allocating an identity-constraint definition", NULL);
7408 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007409 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007410 /*
7411 * Add the IDC to the list of IDCs on the schema component.
7412 */
7413 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007414 if (resAdd != 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007415 xmlSchemaPCustomErrExt(ctxt,
7416 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007417 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007418 "An identity-constraint definition with the name '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007419 "and targetNamespace '%s' does already exist",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007420 name, targetNamespace, NULL);
7421 xmlFree(item);
7422 return (NULL);
7423 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007424 memset(item, 0, sizeof(xmlSchemaIDC));
7425 item->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007426 item->type = idcCategory;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007427 item->node = node;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +00007428 if (ctxt->assemble != NULL)
7429 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007430 /*
7431 * The target namespace of the parent element declaration.
7432 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007433 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007434 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7435 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007436 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7437 /*
7438 * Attribute "refer" (mandatory).
7439 */
7440 attr = xmlSchemaGetPropNode(node, "refer");
7441 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007442 xmlSchemaPMissingAttrErr(ctxt,
7443 XML_SCHEMAP_S4S_ATTR_MISSING,
7444 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007445 "refer", NULL);
7446 } else {
7447 /*
7448 * Create a reference item.
7449 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007450 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007451 NULL, NULL);
7452 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007453 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007454 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007455 NULL, NULL, attr,
7456 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007457 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007458 xmlSchemaCheckReference(ctxt, schema, node,
7459 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007460 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007461 }
7462 }
7463 /*
7464 * And now for the children...
7465 */
7466 child = node->children;
7467 if (IS_SCHEMA(child, "annotation")) {
7468 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7469 child = child->next;
7470 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007471 if (child == NULL) {
7472 xmlSchemaPContentErr(ctxt,
7473 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007474 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007475 "A child element is missing",
7476 "(annotation?, (selector, field+))");
7477 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007478 /*
7479 * Child element <selector>.
7480 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007481 if (IS_SCHEMA(child, "selector")) {
7482 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007483 item, child, 0);
7484 child = child->next;
7485 /*
7486 * Child elements <field>.
7487 */
7488 if (IS_SCHEMA(child, "field")) {
7489 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007490 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007491 item, child, 1);
7492 if (field != NULL) {
7493 field->index = item->nbFields;
7494 item->nbFields++;
7495 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007496 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007497 else
7498 item->fields = field;
7499 lastField = field;
7500 }
7501 child = child->next;
7502 } while (IS_SCHEMA(child, "field"));
7503 } else {
7504 xmlSchemaPContentErr(ctxt,
7505 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007506 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007507 NULL, "(annotation?, (selector, field+))");
7508 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007509 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007510 if (child != NULL) {
7511 xmlSchemaPContentErr(ctxt,
7512 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007513 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007514 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007515 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007516
7517 return (item);
7518}
7519
Daniel Veillardc0826a72004-08-10 14:17:33 +00007520/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007521 * xmlSchemaParseElement:
7522 * @ctxt: a schema validation context
7523 * @schema: the schema being built
7524 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007525 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007526 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007527 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007528 * *WARNING* this interface is highly subject to change
7529 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007530 * Returns the element declaration or a particle; NULL in case
7531 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007532 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007533static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007534xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007535 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007536{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007537 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007538 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007539 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007540 xmlNodePtr child = NULL;
7541 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007542 int min, max, isRef = 0;
7543 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007544
7545 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7546 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007547
Daniel Veillard4255d502002-04-16 15:50:10 +00007548 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007549 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007550 /*
7551 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007552 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007553 * robust.
7554 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007555 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007556 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007557 if ((topLevel) || (attr == NULL)) {
7558 if (nameAttr == NULL) {
7559 xmlSchemaPMissingAttrErr(ctxt,
7560 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007561 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007562 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007563 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007564 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007565 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007566
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007567 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007568 child = node->children;
7569 if (IS_SCHEMA(child, "annotation")) {
7570 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7571 child = child->next;
7572 }
7573 /*
7574 * Skip particle part if a global declaration.
7575 */
7576 if (topLevel)
7577 goto declaration_part;
7578 /*
7579 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007580 */
7581 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7582 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7583 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007584 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7585 if (particle == NULL)
7586 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007587
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007588 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7589
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007590 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007591 const xmlChar *refNs = NULL, *ref = NULL;
7592 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007593 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007594 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007595 */
7596 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007597 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007598 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007599 /*
7600 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007601 */
7602 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007603 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007604 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007605 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007606 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007607 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007608 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007609 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007610 attr = node->properties;
7611 while (attr != NULL) {
7612 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007613 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7614 xmlStrEqual(attr->name, BAD_CAST "name") ||
7615 xmlStrEqual(attr->name, BAD_CAST "id") ||
7616 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7617 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7618 {
7619 attr = attr->next;
7620 continue;
7621 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007622 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007623 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007624 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007625 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007626 "Only the attributes 'minOccurs', 'maxOccurs' and "
7627 "'id' are allowed in addition to 'ref'");
7628 break;
7629 }
7630 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7631 xmlSchemaPIllegalAttrErr(ctxt,
7632 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007633 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007634 }
7635 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007636 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007637 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007638 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007639 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007640 if (child != NULL) {
7641 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7642 NULL, NULL, node, child, NULL, "(annotation?)");
7643 }
7644 if ((min == 0) && (max == 0))
7645 goto return_null;
7646 /*
7647 * Create the reference item.
7648 */
7649 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7650 ref, refNs);
7651 if (refer == NULL)
7652 goto return_null;
7653 particle->children = (xmlSchemaTreeItemPtr) refer;
7654 particle->annot = annot;
7655 /*
7656 * Add to assembled items; the reference need to be resolved.
7657 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007658 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007659 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7660
7661 return ((xmlSchemaBasicItemPtr) particle);
7662 }
7663 /*
7664 * The declaration part ===============================================
7665 */
7666declaration_part:
7667 {
7668 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7669 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7670
7671 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007672 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007673 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007674 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007675 * Evaluate the target namespace.
7676 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007677 if (topLevel) {
7678 ns = schema->targetNamespace;
7679 } else {
7680 attr = xmlSchemaGetPropNode(node, "form");
7681 if (attr != NULL) {
7682 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7683 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007684 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007685 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007686 xmlSchemaPSimpleTypeErr(ctxt,
7687 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7688 NULL, (xmlNodePtr) attr,
7689 NULL, "(qualified | unqualified)",
7690 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007691 }
7692 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007693 ns = schema->targetNamespace;
7694 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007695 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007696 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007697 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007698 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007699 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7700 decl->node = node;
7701 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007702 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007703 * Check for illegal attributes.
7704 */
William M. Bracke7091952004-05-11 15:09:58 +00007705 attr = node->properties;
7706 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007707 if (attr->ns == NULL) {
7708 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7709 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007710 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007711 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007712 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007713 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007714 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7715 {
7716 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007717 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007718 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007719 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007720 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007721 xmlSchemaPIllegalAttrErr(ctxt,
7722 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7723 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007724 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007725 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7726 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007727 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7728
7729 xmlSchemaPIllegalAttrErr(ctxt,
7730 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007731 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007732 }
7733 }
7734 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007735
Daniel Veillardc0826a72004-08-10 14:17:33 +00007736 xmlSchemaPIllegalAttrErr(ctxt,
7737 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007738 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007739 }
7740 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007741 }
William M. Bracke7091952004-05-11 15:09:58 +00007742 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007743 * Extract/validate attributes.
7744 */
7745 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007746 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007747 * Process top attributes of global element declarations here.
7748 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007749 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7750 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007751 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7752 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7753 &(decl->substGroupNs), &(decl->substGroup));
7754 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007755 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007756 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007757 /*
7758 * Attribute "final".
7759 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007760 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007761 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007762 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7763 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7764 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7765 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007766 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007767 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7768 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007769 -1,
7770 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7771 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007772 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007773 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007774 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7775 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007776 attrValue, NULL, NULL, NULL);
7777 }
7778 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007779 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007780 /*
7781 * Attribute "block".
7782 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007783 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007784 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007785 /*
7786 * Apply default "block" values.
7787 */
7788 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7789 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7790 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7791 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7792 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7793 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007794 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007795 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7796 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007797 -1,
7798 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007799 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007800 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7801 xmlSchemaPSimpleTypeErr(ctxt,
7802 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007803 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007804 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007805 "restriction | substitution))", attrValue,
7806 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007807 }
7808 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007809 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007810 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007811 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007812
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007813 attr = xmlSchemaGetPropNode(node, "type");
7814 if (attr != NULL) {
7815 xmlSchemaPValAttrNodeQName(ctxt, schema,
7816 NULL, (xmlSchemaTypePtr) decl, attr,
7817 &(decl->namedTypeNs), &(decl->namedType));
7818 xmlSchemaCheckReference(ctxt, schema, node,
7819 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7820 }
7821 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7822 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007823 if (attr != NULL) {
7824 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007825 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007826 /*
7827 * 3.3.3 : 1
7828 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007829 */
7830 xmlSchemaPMutualExclAttrErr(ctxt,
7831 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007832 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007833 "default", "fixed");
7834 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007835 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7836 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007837 }
William M. Bracke7091952004-05-11 15:09:58 +00007838 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007839 /*
7840 * And now for the children...
7841 */
7842 oldcontainer = ctxt->container;
7843 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007844 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007845 /*
7846 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007847 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007848 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007849 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007850 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007851 xmlSchemaPContentErr(ctxt,
7852 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007853 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007854 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007855 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007856 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007857 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007858 child = child->next;
7859 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007860 /*
7861 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007862 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007863 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007864 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007865 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007866 xmlSchemaPContentErr(ctxt,
7867 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007868 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007869 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007870 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007871 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007872 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007873 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007874 }
William M. Bracke7091952004-05-11 15:09:58 +00007875 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007876 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007877 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007878 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007879 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007880 } else if (IS_SCHEMA(child, "key")) {
7881 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007882 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007883 } else if (IS_SCHEMA(child, "keyref")) {
7884 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007885 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007886 }
7887 if (lastIDC != NULL)
7888 lastIDC->next = curIDC;
7889 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007890 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007891 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007892 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007893 }
7894 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007895 xmlSchemaPContentErr(ctxt,
7896 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007897 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007898 NULL, "(annotation?, ((simpleType | complexType)?, "
7899 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007900 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007901 ctxt->container = oldcontainer;
7902 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007903 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007904 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007905 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007906 * different layer.
7907 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007908 FREE_AND_NULL(des)
7909 if (topLevel)
7910 return ((xmlSchemaBasicItemPtr) decl);
7911 else {
7912 particle->children = (xmlSchemaTreeItemPtr) decl;
7913 return ((xmlSchemaBasicItemPtr) particle);
7914 }
7915
7916return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007917 FREE_AND_NULL(des);
7918 if (annot != NULL) {
7919 if (particle != NULL)
7920 particle->annot = NULL;
7921 if (decl != NULL)
7922 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007923 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007924 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007925 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007926}
7927
7928/**
7929 * xmlSchemaParseUnion:
7930 * @ctxt: a schema validation context
7931 * @schema: the schema being built
7932 * @node: a subtree containing XML Schema informations
7933 *
7934 * parse a XML schema Union definition
7935 * *WARNING* this interface is highly subject to change
7936 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007937 * Returns -1 in case of internal error, 0 in case of success and a positive
7938 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007939 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007940static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007941xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007942 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007943{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007944 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007945 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007946 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007947 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007948
7949 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007950 return (-1);
7951 /* Not a component, don't create it. */
7952 type = ctxt->ctxtType;
7953 /*
7954 * Mark the simple type as being of variety "union".
7955 */
7956 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007957 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007958 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7959 * then the ·simple ur-type definition·."
7960 */
7961 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007962 /*
7963 * Check for illegal attributes.
7964 */
7965 attr = node->properties;
7966 while (attr != NULL) {
7967 if (attr->ns == NULL) {
7968 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7969 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007970 xmlSchemaPIllegalAttrErr(ctxt,
7971 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7972 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007973 }
7974 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007975 xmlSchemaPIllegalAttrErr(ctxt,
7976 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7977 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007978 }
7979 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007980 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007981 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007982 /*
7983 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007984 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007985 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007986 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007987 if (attr != NULL) {
7988 const xmlChar *end;
7989 xmlChar *tmp;
7990 const xmlChar *localName, *nsName;
7991 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7992 xmlSchemaQNameRefPtr ref;
7993
7994 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007995 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007996 do {
7997 while (IS_BLANK_CH(*cur))
7998 cur++;
7999 end = cur;
8000 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8001 end++;
8002 if (end == cur)
8003 break;
8004 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008005 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
8006 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008007 /*
8008 * Create the member type link.
8009 */
8010 link = (xmlSchemaTypeLinkPtr)
8011 xmlMalloc(sizeof(xmlSchemaTypeLink));
8012 if (link == NULL) {
8013 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8014 "allocating a type link", NULL);
8015 return (-1);
8016 }
8017 link->type = NULL;
8018 link->next = NULL;
8019 if (lastLink == NULL)
8020 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008021 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008022 lastLink->next = link;
8023 lastLink = link;
8024 /*
8025 * Create a reference item.
8026 */
8027 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
8028 localName, nsName);
8029 if (ref == NULL) {
8030 FREE_AND_NULL(tmp)
8031 return (-1);
8032 }
8033 /*
8034 * Assign the reference to the link, it will be resolved
8035 * later during fixup of the union simple type.
8036 */
8037 link->type = (xmlSchemaTypePtr) ref;
8038 }
8039 FREE_AND_NULL(tmp)
8040 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008041 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008042
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008043 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008044 /*
8045 * And now for the children...
8046 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008047 child = node->children;
8048 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008049 /*
8050 * Add the annotation to the simple type ancestor.
8051 */
8052 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8053 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008054 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008055 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008056 if (IS_SCHEMA(child, "simpleType")) {
8057 xmlSchemaTypePtr subtype, last = NULL;
8058
8059 /*
8060 * Anchor the member types in the "subtypes" field of the
8061 * simple type.
8062 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008063 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008064 subtype = (xmlSchemaTypePtr)
8065 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8066 if (subtype != NULL) {
8067 if (last == NULL) {
8068 type->subtypes = subtype;
8069 last = subtype;
8070 } else {
8071 last->next = subtype;
8072 last = subtype;
8073 }
8074 last->next = NULL;
8075 }
8076 child = child->next;
8077 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008078 }
8079 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008080 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008081 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008082 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008083 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008084 if ((attr == NULL) && (type->subtypes == NULL)) {
8085 /*
8086 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008087 * Either the memberTypes [attribute] of the <union> element must
8088 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008089 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008090 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008091 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
8092 NULL, NULL, node,
8093 "Either the attribute 'memberTypes' or "
8094 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008095 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008096 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00008097}
8098
8099/**
8100 * xmlSchemaParseList:
8101 * @ctxt: a schema validation context
8102 * @schema: the schema being built
8103 * @node: a subtree containing XML Schema informations
8104 *
8105 * parse a XML schema List definition
8106 * *WARNING* this interface is highly subject to change
8107 *
William M. Bracke7091952004-05-11 15:09:58 +00008108 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008109 * 1 in case of success.
8110 */
8111static xmlSchemaTypePtr
8112xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008113 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008114{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008115 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008116 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008117 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008118
8119 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8120 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008121 /* Not a component, don't create it. */
8122 type = ctxt->ctxtType;
8123 /*
8124 * Mark the type as being of variety "list".
8125 */
8126 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008127 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008128 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8129 * then the ·simple ur-type definition·."
8130 */
8131 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008132 /*
8133 * Check for illegal attributes.
8134 */
8135 attr = node->properties;
8136 while (attr != NULL) {
8137 if (attr->ns == NULL) {
8138 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8139 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008140 xmlSchemaPIllegalAttrErr(ctxt,
8141 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8142 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008143 }
8144 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008145 xmlSchemaPIllegalAttrErr(ctxt,
8146 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8147 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008148 }
8149 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008150 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008151
8152 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8153
William M. Brack2f2a6632004-08-20 23:09:47 +00008154 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008155 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
8156 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00008157 */
8158 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008159 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00008160 /*
8161 * And now for the children...
8162 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008163 child = node->children;
8164 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008165 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8166 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008167 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008168 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008169 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008170 /*
8171 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008172 * Either the itemType [attribute] or the <simpleType> [child] of
8173 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008174 */
8175 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008176 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008177 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008178 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00008179 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008180 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008181 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008182 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008183 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008184 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008185 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008186 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008187 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008188 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008189 "Either the attribute 'itemType' or the <simpleType> child "
8190 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008191 }
8192 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008193 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008194 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008195 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008196 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008197 if ((type->ref == NULL) &&
8198 (type->subtypes == NULL) &&
8199 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008200 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008201 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008202 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008203 "Either the attribute 'itemType' or the <simpleType> child "
8204 "must be present", NULL);
8205 }
8206 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008207}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008208
Daniel Veillard4255d502002-04-16 15:50:10 +00008209/**
8210 * xmlSchemaParseSimpleType:
8211 * @ctxt: a schema validation context
8212 * @schema: the schema being built
8213 * @node: a subtree containing XML Schema informations
8214 *
8215 * parse a XML schema Simple Type definition
8216 * *WARNING* this interface is highly subject to change
8217 *
William M. Bracke7091952004-05-11 15:09:58 +00008218 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008219 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008220 */
8221static xmlSchemaTypePtr
8222xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008223 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008224{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008225 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008226 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008227 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008228 xmlAttrPtr attr;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008229 int hasRestriction = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008230
8231 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8232 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008233
Daniel Veillardc0826a72004-08-10 14:17:33 +00008234 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008235 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008236 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008237 xmlSchemaPMissingAttrErr(ctxt,
8238 XML_SCHEMAP_S4S_ATTR_MISSING,
8239 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008240 "name", NULL);
8241 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008242 } else {
8243 if (xmlSchemaPValAttrNode(ctxt,
8244 NULL, NULL, attr,
8245 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
8246 return (NULL);
8247 /*
8248 * Skip built-in types.
8249 */
8250 if (ctxt->isS4S) {
8251 xmlSchemaTypePtr biType;
8252
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008253 if (ctxt->isRedefine) {
8254 /*
8255 * REDEFINE: Disallow redefinition of built-in-types.
8256 * TODO: It seems that the spec does not say anything
8257 * about this case.
8258 */
8259 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
8260 NULL, NULL, node,
8261 "Redefinition of built-in simple types is not "
8262 "supported", NULL);
8263 return(NULL);
8264 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008265 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
8266 if (biType != NULL)
8267 return (biType);
8268 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008269 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008270 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008271
Daniel Veillardc0826a72004-08-10 14:17:33 +00008272 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008273 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008274
Daniel Veillard01fa6152004-06-29 17:04:39 +00008275 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008276 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008277 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008278 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008279 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL,
8280 node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008281 if (type == NULL)
8282 return (NULL);
8283 type->node = node;
8284 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008285 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008286 /*
8287 * Check for illegal attributes.
8288 */
8289 attr = node->properties;
8290 while (attr != NULL) {
8291 if (attr->ns == NULL) {
8292 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008293 xmlSchemaPIllegalAttrErr(ctxt,
8294 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8295 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008296 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008297 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008298 xmlSchemaPIllegalAttrErr(ctxt,
8299 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8300 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008301 }
8302 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008303 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008304 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008305 /*
8306 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008307 *
8308 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008309 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008310 type = xmlSchemaAddType(ctxt, schema, attrValue,
8311 schema->targetNamespace, node, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008312 if (type == NULL)
8313 return (NULL);
8314 type->node = node;
8315 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008316 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008317 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8318 /*
8319 * Check for illegal attributes.
8320 */
8321 attr = node->properties;
8322 while (attr != NULL) {
8323 if (attr->ns == NULL) {
8324 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8325 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008326 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008327 xmlSchemaPIllegalAttrErr(ctxt,
8328 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8329 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008330 }
8331 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008332 xmlSchemaPIllegalAttrErr(ctxt,
8333 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8334 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008335 }
8336 attr = attr->next;
8337 }
8338 /*
8339 * Attribute "final".
8340 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008341 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008342 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008343 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8344 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8345 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8346 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8347 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8348 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008349 } else {
8350 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008351 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8352 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008353 XML_SCHEMAS_TYPE_FINAL_LIST,
8354 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8355
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008356 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008357 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008358 type, (xmlNodePtr) attr,
8359 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008360 attrValue, NULL, NULL, NULL);
8361 }
8362 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008363 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008364 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008365 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008366 /*
8367 * And now for the children...
8368 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008369 oldCtxtType = ctxt->ctxtType;
8370 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008371 ctxt->ctxtType = type;
8372 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008373 child = node->children;
8374 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008375 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8376 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008377 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008378 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008379 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8380 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008381 "(annotation?, (restriction | list | union))");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008382 } else if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008383 xmlSchemaParseRestriction(ctxt, schema, child,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008384 XML_SCHEMA_TYPE_SIMPLE);
8385 hasRestriction = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008386 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008387 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008388 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008389 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008390 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008391 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008392 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008393 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008394 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008395 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8396 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008397 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008398 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008399 /*
8400 * REDEFINE: SPEC src-redefine (5)
8401 * "Within the [children], each <simpleType> must have a
8402 * <restriction> among its [children] ... the ·actual value· of whose
8403 * base [attribute] must be the same as the ·actual value· of its own
8404 * name attribute plus target namespace;"
8405 */
8406 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
8407 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
8408 NULL, NULL, node, "This is a redefinition, thus the "
8409 "<simpleType> must have a <restriction> child", NULL);
8410 }
8411
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008412 ctxt->parentItem = oldParentItem;
8413 ctxt->ctxtType = oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008414 return (type);
8415}
8416
Daniel Veillard4255d502002-04-16 15:50:10 +00008417/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008418 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008419 * @ctxt: a schema validation context
8420 * @schema: the schema being built
8421 * @node: a subtree containing XML Schema informations
8422 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008423 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008424 * *WARNING* this interface is highly subject to change
8425 *
William M. Bracke7091952004-05-11 15:09:58 +00008426 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008427 * 1 in case of success.
8428 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008429static xmlSchemaTreeItemPtr
8430xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8431 xmlSchemaPtr schema,
8432 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008433{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008434 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008435 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008436 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008437 const xmlChar *ref = NULL, *refNs = NULL;
8438 int min, max;
8439
8440 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008441 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008442
8443 attr = xmlSchemaGetPropNode(node, "ref");
8444 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008445 xmlSchemaPMissingAttrErr(ctxt,
8446 XML_SCHEMAP_S4S_ATTR_MISSING,
8447 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008448 "ref", NULL);
8449 return (NULL);
8450 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008451 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008452 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008453 }
8454 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008455 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008456 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008457 /*
8458 * Check for illegal attributes.
8459 */
8460 attr = node->properties;
8461 while (attr != NULL) {
8462 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008463 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008464 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8465 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8466 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008467 xmlSchemaPIllegalAttrErr(ctxt,
8468 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8469 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008470 }
8471 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008472 xmlSchemaPIllegalAttrErr(ctxt,
8473 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8474 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008475 }
8476 attr = attr->next;
8477 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008478 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008479 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8480 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008481 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008482 /*
8483 * Create a reference item as the term; it will be substituted for
8484 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008485 */
8486 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008487 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8488 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8489 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8490 /*
8491 * And now for the children...
8492 */
8493 child = node->children;
8494 /* TODO: Is annotation even allowed for a model group reference? */
8495 if (IS_SCHEMA(child, "annotation")) {
8496 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008497 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008498 */
8499 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8500 child = child->next;
8501 }
8502 if (child != NULL) {
8503 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008504 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008505 NULL, NULL, node, child, NULL,
8506 "(annotation?)");
8507 }
8508 /*
8509 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8510 */
8511 if ((min == 0) && (max == 0))
8512 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008513 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008514 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8515 return ((xmlSchemaTreeItemPtr) item);
8516}
8517
8518/**
8519 * xmlSchemaParseModelGroupDefinition:
8520 * @ctxt: a schema validation context
8521 * @schema: the schema being built
8522 * @node: a subtree containing XML Schema informations
8523 *
8524 * Parses a XML schema model group definition.
8525 * *WARNING* this interface is highly subject to change
8526 *
8527 * Returns -1 in case of error, 0 if the declaration is improper and
8528 * 1 in case of success.
8529 */
8530static xmlSchemaModelGroupDefPtr
8531xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8532 xmlSchemaPtr schema,
8533 xmlNodePtr node)
8534{
8535 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008536 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008537 xmlAttrPtr attr;
8538 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008539
8540 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008541 return (NULL);
8542
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008543 attr = xmlSchemaGetPropNode(node, "name");
8544 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008545 xmlSchemaPMissingAttrErr(ctxt,
8546 XML_SCHEMAP_S4S_ATTR_MISSING,
8547 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008548 "name", NULL);
8549 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008550 } else if (xmlSchemaPValAttrNode(ctxt,
8551 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008552 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8553 return (NULL);
8554 }
8555 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8556 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008557 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008558 /*
8559 * Check for illegal attributes.
8560 */
8561 attr = node->properties;
8562 while (attr != NULL) {
8563 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008564 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008565 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008566 xmlSchemaPIllegalAttrErr(ctxt,
8567 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8568 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008569 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008570 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008571 xmlSchemaPIllegalAttrErr(ctxt,
8572 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8573 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008574 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008575 attr = attr->next;
8576 }
8577 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8578 /*
8579 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008580 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008581 child = node->children;
8582 if (IS_SCHEMA(child, "annotation")) {
8583 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8584 child = child->next;
8585 }
8586 if (IS_SCHEMA(child, "all")) {
8587 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8588 XML_SCHEMA_TYPE_ALL, 0);
8589 child = child->next;
8590 } else if (IS_SCHEMA(child, "choice")) {
8591 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8592 XML_SCHEMA_TYPE_CHOICE, 0);
8593 child = child->next;
8594 } else if (IS_SCHEMA(child, "sequence")) {
8595 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8596 XML_SCHEMA_TYPE_SEQUENCE, 0);
8597 child = child->next;
8598 }
8599 if (child != NULL) {
8600 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008601 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8602 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008603 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008604 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008605
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008606 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008607}
8608
8609/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008610 * xmlSchemaCleanupDoc:
8611 * @ctxt: a schema validation context
8612 * @node: the root of the document.
8613 *
8614 * removes unwanted nodes in a schemas document tree
8615 */
8616static void
8617xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8618{
8619 xmlNodePtr delete, cur;
8620
8621 if ((ctxt == NULL) || (root == NULL)) return;
8622
8623 /*
8624 * Remove all the blank text nodes
8625 */
8626 delete = NULL;
8627 cur = root;
8628 while (cur != NULL) {
8629 if (delete != NULL) {
8630 xmlUnlinkNode(delete);
8631 xmlFreeNode(delete);
8632 delete = NULL;
8633 }
8634 if (cur->type == XML_TEXT_NODE) {
8635 if (IS_BLANK_NODE(cur)) {
8636 if (xmlNodeGetSpacePreserve(cur) != 1) {
8637 delete = cur;
8638 }
8639 }
8640 } else if ((cur->type != XML_ELEMENT_NODE) &&
8641 (cur->type != XML_CDATA_SECTION_NODE)) {
8642 delete = cur;
8643 goto skip_children;
8644 }
8645
8646 /*
8647 * Skip to next node
8648 */
8649 if (cur->children != NULL) {
8650 if ((cur->children->type != XML_ENTITY_DECL) &&
8651 (cur->children->type != XML_ENTITY_REF_NODE) &&
8652 (cur->children->type != XML_ENTITY_NODE)) {
8653 cur = cur->children;
8654 continue;
8655 }
8656 }
8657 skip_children:
8658 if (cur->next != NULL) {
8659 cur = cur->next;
8660 continue;
8661 }
8662
8663 do {
8664 cur = cur->parent;
8665 if (cur == NULL)
8666 break;
8667 if (cur == root) {
8668 cur = NULL;
8669 break;
8670 }
8671 if (cur->next != NULL) {
8672 cur = cur->next;
8673 break;
8674 }
8675 } while (cur != NULL);
8676 }
8677 if (delete != NULL) {
8678 xmlUnlinkNode(delete);
8679 xmlFreeNode(delete);
8680 delete = NULL;
8681 }
8682}
8683
William M. Brack2f2a6632004-08-20 23:09:47 +00008684
William M. Brack2f2a6632004-08-20 23:09:47 +00008685static void
8686xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8687{
8688 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8689 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8690
8691 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8692 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8693
8694 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8695 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8696 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8697 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8698 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8699 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8700 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8701 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8702
8703 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8704 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8705 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8706 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8707 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8708 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8709}
8710
8711static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008712xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008713 xmlSchemaPtr schema,
8714 xmlNodePtr node)
8715{
8716 xmlAttrPtr attr;
8717 const xmlChar *val;
8718
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008719 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8720 if (schema->version == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008721 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008722 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8723 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008724 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008725 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8726
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008727 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008728 if (attr != NULL) {
8729 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008730 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008731 XML_SCHEMAS_QUALIF_ELEM) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008732 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008733 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008734 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008735 "(qualified | unqualified)", val, NULL, NULL, NULL);
8736 }
8737 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008738
8739 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008740 if (attr != NULL) {
8741 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008742 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008743 XML_SCHEMAS_QUALIF_ATTR) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008744 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008745 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008746 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008747 "(qualified | unqualified)", val, NULL, NULL, NULL);
8748 }
8749 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008750
8751 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008752 if (attr != NULL) {
8753 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8754 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8755 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8756 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8757 -1,
8758 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8759 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8760 xmlSchemaPSimpleTypeErr(ctxt,
8761 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008762 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008763 "(#all | List of (extension | restriction | list | union))",
8764 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008765 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008766 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008767
8768 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008769 if (attr != NULL) {
8770 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8771 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8772 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8773 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8774 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8775 xmlSchemaPSimpleTypeErr(ctxt,
8776 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008777 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008778 "(#all | List of (extension | restriction | substitution))",
8779 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008780 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008781 }
8782}
8783
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008784/**
8785 * xmlSchemaParseSchemaTopLevel:
8786 * @ctxt: a schema validation context
8787 * @schema: the schemas
8788 * @nodes: the list of top level nodes
8789 *
8790 * Returns the internal XML Schema structure built from the resource or
8791 * NULL in case of error
8792 */
8793static void
8794xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8795 xmlSchemaPtr schema, xmlNodePtr nodes)
8796{
8797 xmlNodePtr child;
8798 xmlSchemaAnnotPtr annot;
8799
8800 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8801 return;
8802
8803 child = nodes;
8804 while ((IS_SCHEMA(child, "include")) ||
8805 (IS_SCHEMA(child, "import")) ||
8806 (IS_SCHEMA(child, "redefine")) ||
8807 (IS_SCHEMA(child, "annotation"))) {
8808 if (IS_SCHEMA(child, "annotation")) {
8809 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8810 if (schema->annot == NULL)
8811 schema->annot = annot;
8812 else
8813 xmlSchemaFreeAnnot(annot);
8814 } else if (IS_SCHEMA(child, "import")) {
8815 xmlSchemaParseImport(ctxt, schema, child);
8816 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008817 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008818 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008819 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008820 } else if (IS_SCHEMA(child, "redefine")) {
8821 TODO
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008822 /*
8823 xmlSchemaParseRedefine(ctxt, schema, child);
8824 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008825 }
8826 child = child->next;
8827 }
8828 while (child != NULL) {
8829 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008830 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008831 child = child->next;
8832 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008833 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008834 child = child->next;
8835 } else if (IS_SCHEMA(child, "element")) {
8836 xmlSchemaParseElement(ctxt, schema, child, 1);
8837 child = child->next;
8838 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008839 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008840 child = child->next;
8841 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008842 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008843 child = child->next;
8844 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008845 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008846 child = child->next;
8847 } else if (IS_SCHEMA(child, "notation")) {
8848 xmlSchemaParseNotation(ctxt, schema, child);
8849 child = child->next;
8850 } else {
8851 xmlSchemaPErr2(ctxt, NULL, child,
8852 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008853 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008854 child->name, NULL);
8855 child = child->next;
8856 }
8857 while (IS_SCHEMA(child, "annotation")) {
8858 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8859 if (schema->annot == NULL)
8860 schema->annot = annot;
8861 else
8862 xmlSchemaFreeAnnot(annot);
8863 child = child->next;
8864 }
8865 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008866 ctxt->parentItem = NULL;
8867 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008868}
8869
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008870static xmlSchemaImportPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008871xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008872 xmlHashTablePtr *imports,
8873 const xmlChar *nsName)
8874{
8875 xmlSchemaImportPtr ret;
8876
8877 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008878 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008879 if (*imports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008880 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008881 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8882 NULL, NULL, (xmlNodePtr) ctxt->doc,
8883 "Internal error: failed to build the import table",
8884 NULL);
8885 return (NULL);
8886 }
8887 }
8888 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8889 if (ret == NULL) {
8890 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8891 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008892 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008893 memset(ret, 0, sizeof(xmlSchemaImport));
8894 if (nsName == NULL)
8895 nsName = XML_SCHEMAS_NO_NAMESPACE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008896 xmlHashAddEntry(*imports, nsName, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008897
8898 return (ret);
8899}
8900
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008901#if 0
8902static xmlSchemaSchemaRefPtr
8903xmlSchemaNewSchemaRef(void)
8904{
8905 xmlSchemaSchemaRefPtr ret;
8906
8907 ret = (xmlSchemaSchemaRefPtr) xmlMalloc(sizeof(xmlSchemaSchemaRef));
8908 if (ret == NULL) {
8909 xmlSchemaPErrMemory(NULL, "allocating schema reference", NULL);
8910 return(NULL);
8911 }
8912 memset(ret, 0, sizeof(xmlSchemaSchemaRef));
8913 return(ret);
8914}
8915
8916static void
8917xmlSchemaFreeSchemaRef(xmlSchemaSchemaRefPtr ref)
8918{
8919 xmlFree(ref);
8920}
8921#endif
8922
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008923/**
8924 * xmlSchemaNewParserCtxtUseDict:
8925 * @URL: the location of the schema
8926 * @dict: the dictionary to be used
8927 *
8928 * Create an XML Schemas parse context for that file/resource expected
8929 * to contain an XML Schemas file.
8930 *
8931 * Returns the parser context or NULL in case of error
8932 */
8933static xmlSchemaParserCtxtPtr
8934xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8935{
8936 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008937
8938 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8939 if (ret == NULL) {
8940 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8941 NULL);
8942 return (NULL);
8943 }
8944 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8945 ret->dict = dict;
Daniel Veillard210536b2005-08-10 21:40:02 +00008946 ret->type = XML_SCHEMA_CTXT_PARSER;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008947 xmlDictReference(dict);
8948 if (URL != NULL)
8949 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
8950 ret->includes = 0;
8951 return (ret);
8952}
8953
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008954static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008955xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
8956{
8957 if (vctxt->pctxt == NULL) {
8958 if (vctxt->schema != NULL)
8959 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
8960 else
8961 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
8962 if (vctxt->pctxt == NULL) {
8963 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
8964 "failed to create a temp. parser context");
8965 return (-1);
8966 }
8967 /* TODO: Pass user data. */
8968 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
8969 }
8970 return (0);
8971}
8972
8973static int
8974xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008975 xmlSchemaPtr schema,
8976 xmlNodePtr node,
8977 const xmlChar *nsName,
8978 const xmlChar *location,
8979 xmlDocPtr *doc,
8980 const xmlChar **targetNamespace,
8981 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008982{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008983 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008984 xmlParserCtxtPtr parserCtxt;
8985 xmlSchemaImportPtr import;
8986 const xmlChar *ns;
8987 xmlNodePtr root;
8988
8989 /*
8990 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8991 * <xsi:noNamespaceSchemaLocation>.
8992 */
8993 *doc = NULL;
8994 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008995 * Given that the schemaLocation [attribute] is only a hint, it is open
8996 * to applications to ignore all but the first <import> for a given
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008997 * namespace, regardless of the ·actual value· of schemaLocation, but
8998 * such a strategy risks missing useful information when new
8999 * schemaLocations are offered.
9000 *
9001 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
9002 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
9003 * valid or not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009004 * We will follow XSV here.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009005 */
9006 if (location == NULL) {
9007 /*
9008 * Schema Document Location Strategy:
9009 *
9010 * 3 Based on the namespace name, identify an existing schema document,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009011 * either as a resource which is an XML document or a <schema> element
9012 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009013 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009014 * 5 Attempt to resolve the namespace name to locate such a resource.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009015 *
9016 * NOTE: Those stategies are not supported, so we will skip.
9017 */
9018 return (0);
9019 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009020 if (nsName == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009021 ns = XML_SCHEMAS_NO_NAMESPACE;
9022 else
9023 ns = nsName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009024
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009025 import = xmlHashLookup(schema->schemasImports, ns);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009026 if (import != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009027 /*
9028 * There was a valid resource for the specified namespace already
9029 * defined, so skip.
9030 * TODO: This might be changed someday to allow import of
9031 * components from multiple documents for a single target namespace.
9032 */
9033 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009034 }
9035 if (actxt->type == XML_SCHEMA_CTXT_PARSER)
9036 pctxt = (xmlSchemaParserCtxtPtr) actxt;
9037 else {
9038 xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
9039 pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
9040 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009041 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009042 * Schema Document Location Strategy:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009043 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009044 * 2 Based on the location URI, identify an existing schema document,
9045 * either as a resource which is an XML document or a <schema> element
9046 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009047 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009048 * 4 Attempt to resolve the location URI, to locate a resource on the
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009049 * web which is or contains or references a <schema> element;
9050 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
9051 *
9052 */
9053 if ((absolute == 0) && (node != NULL)) {
9054 xmlChar *base, *URI;
9055
9056 base = xmlNodeGetBase(node->doc, node);
9057 if (base == NULL) {
9058 URI = xmlBuildURI(location, node->doc->URL);
9059 } else {
9060 URI = xmlBuildURI(location, base);
9061 xmlFree(base);
9062 }
9063 if (URI != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009064 location = xmlDictLookup(pctxt->dict, URI, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009065 xmlFree(URI);
9066 }
9067 }
9068 parserCtxt = xmlNewParserCtxt();
9069 if (parserCtxt == NULL) {
9070 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
9071 "allocating a parser context", NULL);
9072 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009073 }
9074 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009075 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009076 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009077 xmlDictReference(parserCtxt->dict);
9078 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009079 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009080 NULL, SCHEMAS_PARSE_OPTIONS);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009081 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009082 * 2.1 The referent is (a fragment of) a resource which is an
9083 * XML document (see clause 1.1), which in turn corresponds to
9084 * a <schema> element information item in a well-formed information
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009085 * set, which in turn corresponds to a valid schema.
9086 * TODO: What to do with the "fragment" stuff?
9087 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009088 * 2.2 The referent is a <schema> element information item in
9089 * a well-formed information set, which in turn corresponds
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009090 * to a valid schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009091 * NOTE: 2.2 won't apply, since only XML documents will be processed
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009092 * here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009093 */
9094 if (*doc == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009095 xmlErrorPtr lerr;
9096 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009097 * It is *not* an error for the application schema reference
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009098 * strategy to fail.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009099 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009100 * If the doc is NULL and the parser error is an IO error we
9101 * will assume that the resource could not be located or accessed.
9102 *
9103 * TODO: Try to find specific error codes to react only on
9104 * localisation failures.
9105 *
9106 * TODO, FIXME: Check the spec: is a namespace added to the imported
9107 * namespaces, even if the schemaLocation did not provide
9108 * a resource? I guess so, since omitting the "schemaLocation"
9109 * attribute, imports a namespace as well.
9110 */
9111 lerr = xmlGetLastError();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009112 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009113 xmlFreeParserCtxt(parserCtxt);
9114 return(0);
9115 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009116 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009117 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009118 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009119 "Failed to parse the resource '%s' for import",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009120 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009121 xmlFreeParserCtxt(parserCtxt);
9122 return(XML_SCHEMAP_SRC_IMPORT_2_1);
9123 }
9124 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009125
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009126 root = xmlDocGetRootElement(*doc);
9127 if (root == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009128 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009129 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009130 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009131 "The XML document '%s' to be imported has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009132 "element", location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009133 xmlFreeDoc(*doc);
9134 *doc = NULL;
9135 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009136 }
9137
9138 xmlSchemaCleanupDoc(pctxt, root);
9139
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009140 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009141 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009142 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009143 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009144 "The XML document '%s' to be imported is not a XML schema document",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009145 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009146 xmlFreeDoc(*doc);
9147 *doc = NULL;
9148 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009149 }
9150 *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009151 /*
9152 * Schema Representation Constraint: Import Constraints and Semantics
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009153 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009154 if (nsName == NULL) {
9155 if (*targetNamespace != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009156 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009157 XML_SCHEMAP_SRC_IMPORT_3_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009158 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009159 "The XML schema to be imported is not expected "
9160 "to have a target namespace; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009161 "its target namespace of '%s'", *targetNamespace, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009162 xmlFreeDoc(*doc);
9163 *doc = NULL;
9164 return (XML_SCHEMAP_SRC_IMPORT_3_2);
9165 }
9166 } else {
9167 if (*targetNamespace == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009168 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009169 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009170 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009171 "The XML schema to be imported is expected to have a target "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009172 "namespace of '%s'", nsName, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009173 xmlFreeDoc(*doc);
9174 *doc = NULL;
9175 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9176 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009177 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009178 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009179 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009180 "The XML schema to be imported is expected to have a "
9181 "target namespace of '%s'; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009182 "its target namespace of '%s'",
9183 nsName, *targetNamespace);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009184 xmlFreeDoc(*doc);
9185 *doc = NULL;
9186 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9187 }
9188 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009189 import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009190 if (import == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009191 AERROR_INT("xmlSchemaAcquireSchemaDoc",
9192 "failed to build import table");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009193 xmlFreeDoc(*doc);
9194 *doc = NULL;
9195 return (-1);
9196 }
9197 import->schemaLocation = location;
9198 import->doc = *doc;
9199 return (0);
9200}
William M. Brack2f2a6632004-08-20 23:09:47 +00009201
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009202static void
9203xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9204 xmlSchemaPtr schema,
9205 const xmlChar *targetNamespace,
9206 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009207{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009208 const xmlChar *oldURL, **oldLocImps, *oldTNS;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009209 int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009210
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009211 /*
9212 * Save and reset the context & schema.
9213 */
9214 oldURL = pctxt->URL;
9215 /* TODO: Is using the doc->URL here correct? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009216 pctxt->URL = node->doc->URL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009217 oldLocImps = pctxt->localImports;
9218 pctxt->localImports = NULL;
9219 oldNumLocImps = pctxt->nbLocalImports;
9220 pctxt->nbLocalImports = 0;
9221 oldSizeLocImps = pctxt->sizeLocalImports;
9222 pctxt->sizeLocalImports = 0;
9223 oldFlags = schema->flags;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009224 oldIsS4S = pctxt->isS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009225 xmlSchemaClearSchemaDefaults(schema);
9226 oldTNS = schema->targetNamespace;
9227 schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009228 if ((targetNamespace != NULL) &&
9229 xmlStrEqual(targetNamespace, xmlSchemaNs)) {
9230 /*
9231 * We are parsing the schema for schema!
9232 */
9233 pctxt->isS4S = 1;
9234 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009235 /*
9236 * Parse the schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009237 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009238 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9239 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9240 /*
9241 * Restore the context & schema.
9242 */
9243 schema->flags = oldFlags;
9244 schema->targetNamespace = oldTNS;
9245 if (pctxt->localImports != NULL)
9246 xmlFree((xmlChar *) pctxt->localImports);
9247 pctxt->localImports = oldLocImps;
9248 pctxt->nbLocalImports = oldNumLocImps;
9249 pctxt->sizeLocalImports = oldSizeLocImps;
9250 pctxt->URL = oldURL;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009251 pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009252}
9253
William M. Brack2f2a6632004-08-20 23:09:47 +00009254/**
9255 * xmlSchemaParseImport:
9256 * @ctxt: a schema validation context
9257 * @schema: the schema being built
9258 * @node: a subtree containing XML Schema informations
9259 *
9260 * parse a XML schema Import definition
9261 * *WARNING* this interface is highly subject to change
9262 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009263 * Returns 0 in case of success, a positive error code if
9264 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009265 */
9266static int
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009267xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00009268 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009269{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009270 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009271 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009272 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009273 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009274 xmlAttrPtr attr;
9275 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009276 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009277
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009278 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
William M. Brack2f2a6632004-08-20 23:09:47 +00009279 return (-1);
9280
9281 /*
9282 * Check for illegal attributes.
9283 */
9284 attr = node->properties;
9285 while (attr != NULL) {
9286 if (attr->ns == NULL) {
9287 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9288 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9289 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009290 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009291 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9292 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009293 }
9294 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009295 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009296 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9297 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009298 }
9299 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009300 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009301 /*
9302 * Extract and validate attributes.
9303 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009304 if (xmlSchemaPValAttr(pctxt, NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009305 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009306 &namespaceName) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009307 xmlSchemaPSimpleTypeErr(pctxt,
9308 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009309 NULL, node,
9310 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009311 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009312 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +00009313 }
9314
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009315 if (xmlSchemaPValAttr(pctxt, NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009316 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009317 &schemaLocation) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009318 xmlSchemaPSimpleTypeErr(pctxt,
9319 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009320 NULL, node,
9321 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009322 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009323 return (pctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009324 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009325 /*
9326 * And now for the children...
9327 */
9328 child = node->children;
9329 if (IS_SCHEMA(child, "annotation")) {
9330 /*
9331 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009332 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009333 */
9334 child = child->next;
9335 }
9336 if (child != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009337 xmlSchemaPContentErr(pctxt,
9338 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
William M. Brack2f2a6632004-08-20 23:09:47 +00009339 NULL, NULL, node, child, NULL,
9340 "(annotation?)");
9341 }
9342 /*
9343 * Apply additional constraints.
9344 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009345 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009346 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009347 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9348 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009349 * targetNamespace [attribute].
9350 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009351 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009352 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009353 XML_SCHEMAP_SRC_IMPORT_1_1,
9354 NULL, NULL, node,
9355 "The value of the attribute 'namespace' must not match "
9356 "the target namespace '%s' of the importing schema",
9357 schema->targetNamespace);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009358 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +00009359 }
9360 } else {
9361 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009362 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009363 * <schema> must have a targetNamespace [attribute].
9364 */
9365 if (schema->targetNamespace == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009366 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009367 XML_SCHEMAP_SRC_IMPORT_1_2,
9368 NULL, NULL, node,
9369 "The attribute 'namespace' must be existent if "
9370 "the importing schema has no target namespace",
9371 NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009372 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +00009373 }
9374 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009375 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009376 * Add the namespace to the list of locally imported namespace.
9377 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009378 if (pctxt->localImports == NULL) {
9379 pctxt->localImports = (const xmlChar **) xmlMalloc(10 *
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009380 sizeof(const xmlChar*));
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009381 pctxt->sizeLocalImports = 10;
9382 pctxt->nbLocalImports = 0;
9383 } else if (pctxt->sizeLocalImports <= pctxt->nbLocalImports) {
9384 pctxt->sizeLocalImports *= 2;
9385 pctxt->localImports = (const xmlChar **) xmlRealloc(
9386 (xmlChar **) pctxt->localImports,
9387 pctxt->sizeLocalImports * sizeof(const xmlChar*));
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009388 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009389 pctxt->localImports[pctxt->nbLocalImports++] = namespaceName;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009390 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009391 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009392 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009393 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009394 schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009395 schemaLocation, &doc, &targetNamespace, 0);
9396 if (ret != 0) {
9397 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009398 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009399 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009400 } else if (doc != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009401 xmlSchemaParseForImpInc(pctxt, schema, targetNamespace,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009402 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009403 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009404
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009405 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009406}
9407
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009408/**
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009409 * xmlSchemaParseIncludedDoc:
9410 * @pctxt: a schema validation context
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009411 * @schema: the schema being built
9412 * @node: a subtree containing XML Schema informations
9413 *
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009414 * Parse an included (and to-be-redefined) XML schema document.
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009415 *
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009416 * Returns 0 on success, a positive error code on errors and
9417 * -1 in case of an internal or API error.
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009418 */
9419static int
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009420xmlSchemaParseIncludedDoc(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
9421 xmlNodePtr node, const xmlChar *schemaLocation)
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009422{
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009423 const xmlChar *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009424 xmlDocPtr doc = NULL;
9425 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009426 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009427 int wasConvertingNs = 0;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009428 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009429
9430
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009431 /*
9432 * Check if this one was already processed to avoid incorrect
9433 * duplicate component errors and infinite circular inclusion.
9434 */
9435 include = schema->includes;
9436 while (include != NULL) {
9437 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9438 targetNamespace = include->origTargetNamespace;
9439 if (targetNamespace == NULL) {
9440 /*
9441 * Chameleon include: skip only if it was build for
9442 * the targetNamespace of the including schema.
9443 */
9444 if (xmlStrEqual(schema->targetNamespace,
9445 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009446 goto check_targetNamespace;
9447 }
9448 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009449 goto check_targetNamespace;
9450 }
9451 }
9452 include = include->next;
9453 }
9454 /*
9455 * First step is to parse the input document into an DOM/Infoset
9456 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009457 */
9458 parserCtxt = xmlNewParserCtxt();
9459 if (parserCtxt == NULL) {
9460 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9461 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009462 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009463 }
9464
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009465 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009466 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009467 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009468 xmlDictReference(parserCtxt->dict);
9469 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009470
9471 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009472 NULL, SCHEMAS_PARSE_OPTIONS);
9473 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009474 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009475 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009476 * TODO: It is not an error for the ·actual value· of the
9477 * schemaLocation [attribute] to fail to resolve it all, in which
9478 * case no corresponding inclusion is performed.
William M. Brack2f2a6632004-08-20 23:09:47 +00009479 * So do we need a warning report here?
9480 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009481 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009482 XML_SCHEMAP_FAILED_LOAD,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009483 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009484 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009485 goto exit_error;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009486 }
9487
9488 /*
9489 * Then extract the root of the schema
9490 */
9491 root = xmlDocGetRootElement(doc);
9492 if (root == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009493 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009494 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009495 NULL, NULL, node,
9496 "The included document '%s' has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009497 "element", schemaLocation);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009498 goto exit_error;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009499 }
9500
9501 /*
9502 * Remove all the blank text nodes
9503 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009504 xmlSchemaCleanupDoc(pctxt, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009505
9506 /*
9507 * Check the schemas top level element
9508 */
9509 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009510 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009511 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009512 NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009513 "The document '%s' to be included is not a schema document",
William M. Brack2f2a6632004-08-20 23:09:47 +00009514 schemaLocation);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009515 goto exit_error;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009516 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009517
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009518 targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009519 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009520 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9521 * value· is identical to the ·actual value· of the targetNamespace
Daniel Veillardc0826a72004-08-10 14:17:33 +00009522 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9523 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009524check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009525 if (targetNamespace != NULL) {
9526 if (schema->targetNamespace == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009527 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009528 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009529 NULL, NULL, node,
9530 "The target namespace of the included schema "
9531 "'%s' has to be absent, since the including schema "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009532 "has no target namespace",
9533 schemaLocation);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009534 goto exit_error;
William M. Brack2f2a6632004-08-20 23:09:47 +00009535 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009536 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009537 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009538 NULL, NULL, node,
9539 "The target namespace '%s' of the included schema '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009540 "differs from '%s' of the including schema",
William M. Brack2f2a6632004-08-20 23:09:47 +00009541 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009542 goto exit_error;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009543 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009544 } else if (schema->targetNamespace != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009545 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009546 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009547 } else
9548 wasConvertingNs = 1;
9549 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009550
9551 if (include != NULL)
9552 goto exit;
9553
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009554 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009555 * URGENT TODO: If the schema is a chameleon-include then copy the
9556 * components into the including schema and modify the targetNamespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009557 * of those components, do nothing otherwise.
9558 * NOTE: This is currently worked-around by compiling the chameleon
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009559 * for every destinct including targetNamespace; thus not performant at
9560 * the moment.
9561 * TODO: Check when the namespace in wildcards for chameleons needs
9562 * to be converted: before we built wildcard intersections or after.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009563 * Answer: after!
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009564 */
9565 /*
9566 * Register the include.
9567 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009568 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9569 if (include == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009570 xmlSchemaPErrMemory(pctxt, "allocating include entry", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009571 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009572 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009573 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009574 include->next = schema->includes;
9575 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009576 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009577 * TODO: Use the resolved URI for the this location, since it might
9578 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009579 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009580 include->schemaLocation = schemaLocation;
9581 include->doc = doc;
9582 /*
9583 * In case of chameleons, the original target namespace will differ
9584 * from the resulting namespace.
9585 */
9586 include->origTargetNamespace = targetNamespace;
9587 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009588#ifdef DEBUG_INCLUDES
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009589 if (targetNamespace != schema->targetNamespace)
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009590 xmlGenericError(xmlGenericErrorContext,
9591 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9592 " into TNS '%s'\n", schemaLocation,
9593 targetNamespace, schema->targetNamespace);
9594 else
9595 xmlGenericError(xmlGenericErrorContext,
9596 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9597 targetNamespace);
9598#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009599 /*
9600 * Compile the included schema.
9601 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009602 xmlSchemaParseForImpInc(pctxt, schema, schema->targetNamespace, root);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009603
9604exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009605 /*
9606 * Remove the converting flag.
9607 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009608 if ((wasConvertingNs == 0) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00009609 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009610 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009611 return (0);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009612
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009613exit_error:
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009614 if (doc != NULL) {
9615 if (include != NULL)
9616 include->doc = NULL;
9617 xmlFreeDoc(doc);
9618 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009619 return (pctxt->err);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009620
9621exit_failure:
9622 if (doc != NULL) {
9623 if (include != NULL)
9624 include->doc = NULL;
9625 xmlFreeDoc(doc);
9626 }
9627 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009628}
9629
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009630
9631static int
9632xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
9633 xmlSchemaPtr schema,
9634 xmlNodePtr node,
9635 xmlChar **schemaLocation,
9636 int isRedefine)
9637{
9638 xmlAttrPtr attr;
9639
9640 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
9641 (schemaLocation == NULL))
9642 return (-1);
9643
9644 *schemaLocation = NULL;
9645 /*
9646 * Check for illegal attributes.
9647 * Applies for both <include> and <redefine>.
9648 */
9649 attr = node->properties;
9650 while (attr != NULL) {
9651 if (attr->ns == NULL) {
9652 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9653 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
9654 xmlSchemaPIllegalAttrErr(pctxt,
9655 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9656 NULL, NULL, attr);
9657 }
9658 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9659 xmlSchemaPIllegalAttrErr(pctxt,
9660 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9661 NULL, NULL, attr);
9662 }
9663 attr = attr->next;
9664 }
9665 xmlSchemaPValAttrID(pctxt, NULL, NULL, node, BAD_CAST "id");
9666 /*
9667 * Preliminary step, extract the URI-Reference and make an URI
9668 * from the base.
9669 */
9670 /*
9671 * Attribute "schemaLocation" is mandatory.
9672 */
9673 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9674 if (attr != NULL) {
9675 xmlChar *base = NULL;
9676 xmlChar *uri = NULL;
9677
9678 if (xmlSchemaPValAttrNode(pctxt, NULL, NULL, attr,
9679 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
9680 (const xmlChar **) schemaLocation) != 0)
9681 goto exit_error;
9682 base = xmlNodeGetBase(node->doc, node);
9683 if (base == NULL) {
9684 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
9685 } else {
9686 uri = xmlBuildURI(*schemaLocation, base);
9687 xmlFree(base);
9688 }
9689 if (uri == NULL) {
9690 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
9691 "could not build an URI from the schemaLocation")
9692 goto exit_failure;
9693 }
9694 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
9695 xmlFree(uri);
9696 } else {
9697 xmlSchemaPMissingAttrErr(pctxt,
9698 XML_SCHEMAP_S4S_ATTR_MISSING,
9699 NULL, node, "schemaLocation", NULL);
9700 goto exit_error;
9701 }
9702 /*
9703 * Report self-inclusion and self-redefinition.
9704 */
9705 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
9706 if (isRedefine) {
9707 xmlSchemaPCustomErr(pctxt,
9708 XML_SCHEMAP_SRC_REDEFINE,
9709 NULL, NULL, node,
9710 "The schema document '%s' cannot redefine itself.",
9711 *schemaLocation);
9712 } else {
9713 xmlSchemaPCustomErr(pctxt,
9714 XML_SCHEMAP_SRC_INCLUDE,
9715 NULL, NULL, node,
9716 "The schema document '%s' cannot include itself.",
9717 *schemaLocation);
9718 }
9719 goto exit_error;
9720 }
9721
9722 return(0);
9723exit_error:
9724 return(pctxt->err);
9725exit_failure:
9726 return(-1);
9727}
9728
9729static int
9730xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
9731 xmlSchemaPtr schema,
9732 xmlNodePtr node,
9733 int isRedefine)
9734{
9735 xmlNodePtr child = NULL;
9736 const xmlChar *schemaLocation = NULL;
9737 int res = 0;
9738
9739 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
9740 return (-1);
9741
9742 /*
9743 * Parse attributes.
9744 */
9745 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
9746 node, (xmlChar **) (&schemaLocation), isRedefine);
9747 if (res != 0)
9748 return(res);
9749
9750 /*
9751 * Include the schema.
9752 */
9753 res = xmlSchemaParseIncludedDoc(pctxt, schema, node, schemaLocation);
9754 if (res != 0)
9755 return(res);
9756 /*
9757 * And now for the children...
9758 */
9759 child = node->children;
9760
9761 if (isRedefine) {
9762 /*
9763 * Parse (simpleType | complexType | group | attributeGroup))*
9764 */
9765 pctxt->isRedefine = 1;
9766 while (IS_SCHEMA(child, "annotation") ||
9767 IS_SCHEMA(child, "simpleType") ||
9768 IS_SCHEMA(child, "complexType") ||
9769 IS_SCHEMA(child, "group") ||
9770 IS_SCHEMA(child, "attributeGroup")) {
9771 if (IS_SCHEMA(child, "annotation")) {
9772 /*
9773 * TODO: discard or not?
9774 */
9775 } else if (IS_SCHEMA(child, "simpleType")) {
9776 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
9777 } else if (IS_SCHEMA(child, "complexType")) {
9778 xmlSchemaParseComplexType(pctxt, schema, child, 1);
9779 } else if (IS_SCHEMA(child, "group")) {
9780 TODO
9781 /* xmlSchemaParseModelGroupDefinition(pctxt, schema, child); */
9782 } else if (IS_SCHEMA(child, "attributeGroup")) {
9783 TODO
9784 /* xmlSchemaParseAttributeGroup(pctxt, schema, child, 1); */
9785 }
9786 child = child->next;
9787 }
9788 pctxt->isRedefine = 0;
9789 } else {
9790 if (IS_SCHEMA(child, "annotation")) {
9791 /*
9792 * TODO: discard or not?
9793 */
9794 child = child->next;
9795 }
9796 }
9797 if (child != NULL) {
9798 if (isRedefine) {
9799 xmlSchemaPContentErr(pctxt,
9800 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9801 NULL, NULL, node, child, NULL,
9802 "(annotation | (simpleType | complexType | group | attributeGroup))*");
9803 } else {
9804 xmlSchemaPContentErr(pctxt,
9805 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9806 NULL, NULL, node, child, NULL,
9807 "(annotation?)");
9808 }
9809 return(pctxt->err);
9810 }
9811 return(0);
9812}
9813
9814#if 0
9815static int
9816xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
9817 xmlNodePtr node)
9818{
9819 int res;
9820
9821 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, 1);
9822 if (res != 0)
9823 return(res);
9824 return(0);
9825}
9826#endif
9827
9828static int
9829xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
9830 xmlNodePtr node)
9831{
9832 int res;
9833
9834 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, 0);
9835 if (res != 0)
9836 return(res);
9837 return(0);
9838}
9839
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009840/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009841 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009842 * @ctxt: a schema validation context
9843 * @schema: the schema being built
9844 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009845 * @type: the "compositor" type
9846 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009847 *
9848 * parse a XML schema Sequence definition
9849 * *WARNING* this interface is highly subject to change
9850 *
William M. Bracke7091952004-05-11 15:09:58 +00009851 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009852 * 1 in case of success.
9853 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009854static xmlSchemaTreeItemPtr
9855xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9856 xmlNodePtr node, xmlSchemaTypeType type,
9857 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009858{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009859 xmlSchemaModelGroupPtr item;
9860 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009861 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009862 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009863 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009864 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009865
9866 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009867 return (NULL);
9868 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009869 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009870 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009871 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9872 if (item == NULL)
9873 return (NULL);
9874
9875 if (withParticle) {
9876 if (type == XML_SCHEMA_TYPE_ALL) {
9877 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009878 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009879 } else {
9880 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009881 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9882 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9883 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009884 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009885 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
9886 /*
9887 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009888 */
9889 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9890 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009891 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009892 particle->children = (xmlSchemaTreeItemPtr) item;
9893 /*
9894 * Check for illegal attributes.
9895 */
9896 attr = node->properties;
9897 while (attr != NULL) {
9898 if (attr->ns == NULL) {
9899 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9900 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9901 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009902 xmlSchemaPIllegalAttrErr(ctxt,
9903 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9904 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009905 }
9906 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009907 xmlSchemaPIllegalAttrErr(ctxt,
9908 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9909 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009910 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009911 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009912 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009913 } else {
9914 /*
9915 * Check for illegal attributes.
9916 */
9917 attr = node->properties;
9918 while (attr != NULL) {
9919 if (attr->ns == NULL) {
9920 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009921 xmlSchemaPIllegalAttrErr(ctxt,
9922 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9923 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009924 }
9925 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009926 xmlSchemaPIllegalAttrErr(ctxt,
9927 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9928 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009929 }
9930 attr = attr->next;
9931 }
9932
William M. Brack2f2a6632004-08-20 23:09:47 +00009933 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009934
William M. Brack2f2a6632004-08-20 23:09:47 +00009935 /*
9936 * Extract and validate attributes.
9937 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009938 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009939 /*
9940 * And now for the children...
9941 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009942 child = node->children;
9943 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009944 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009945 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009946 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009947 oldcontainer = ctxt->container;
9948 ctxt->container = container;
9949 if (type == XML_SCHEMA_TYPE_ALL) {
9950 xmlSchemaParticlePtr part, last = NULL;
9951
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009952 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009953 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9954 schema, child, 0);
9955 if (part != NULL) {
9956 if (part->minOccurs > 1)
9957 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009958 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009959 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9960 if (part->maxOccurs > 1)
9961 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009962 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009963 "Invalid value for maxOccurs (must be 0 or 1)",
9964 NULL);
9965 if (last == NULL)
9966 item->children = (xmlSchemaTreeItemPtr) part;
9967 else
9968 last->next = (xmlSchemaTreeItemPtr) part;
9969 last = part;
9970 }
9971 child = child->next;
9972 }
9973 if (child != NULL) {
9974 xmlSchemaPContentErr(ctxt,
9975 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9976 NULL, NULL, node, child, NULL,
9977 "(annotation?, (annotation?, element*)");
9978 }
9979 } else {
9980 /* choice + sequence */
9981 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9982
9983 while ((IS_SCHEMA(child, "element")) ||
9984 (IS_SCHEMA(child, "group")) ||
9985 (IS_SCHEMA(child, "any")) ||
9986 (IS_SCHEMA(child, "choice")) ||
9987 (IS_SCHEMA(child, "sequence"))) {
9988
9989 if (IS_SCHEMA(child, "element")) {
9990 part = (xmlSchemaTreeItemPtr)
9991 xmlSchemaParseElement(ctxt, schema, child, 0);
9992 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009993 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009994 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9995 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009996 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009997 xmlSchemaParseAny(ctxt, schema, child);
9998 } else if (IS_SCHEMA(child, "choice")) {
9999 part = xmlSchemaParseModelGroup(ctxt, schema, child,
10000 XML_SCHEMA_TYPE_CHOICE, 1);
10001 } else if (IS_SCHEMA(child, "sequence")) {
10002 part = xmlSchemaParseModelGroup(ctxt, schema, child,
10003 XML_SCHEMA_TYPE_SEQUENCE, 1);
10004 }
10005 if (part != NULL) {
10006 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010007 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010008 else
10009 last->next = part;
10010 last = part;
10011 }
10012 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010013 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010014 if (child != NULL) {
10015 xmlSchemaPContentErr(ctxt,
10016 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10017 NULL, NULL, node, child, NULL,
10018 "(annotation?, (element | group | choice | sequence | any)*)");
10019 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010020 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010021 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010022 if (withParticle) {
10023 if ((min == 0) && (max == 0))
10024 return (NULL);
10025 else
10026 return ((xmlSchemaTreeItemPtr) particle);
10027 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010028 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +000010029}
10030
10031/**
10032 * xmlSchemaParseRestriction:
10033 * @ctxt: a schema validation context
10034 * @schema: the schema being built
10035 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +000010036 *
10037 * parse a XML schema Restriction definition
10038 * *WARNING* this interface is highly subject to change
10039 *
10040 * Returns the type definition or NULL in case of error
10041 */
10042static xmlSchemaTypePtr
10043xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010044 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010045{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010046 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010047 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010048 char buf[30];
10049 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +000010050 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010051
10052 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10053 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010054 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010055 type = ctxt->ctxtType;
10056 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010057
10058 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010059 * TODO: Is the container needed at all? the anonymous
10060 * items inside should generate unique names already.
10061 */
10062 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010063 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +000010064 /*
10065 * Check for illegal attributes.
10066 */
10067 attr = node->properties;
10068 while (attr != NULL) {
10069 if (attr->ns == NULL) {
10070 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10071 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010072 xmlSchemaPIllegalAttrErr(ctxt,
10073 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10074 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010075 }
10076 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010077 xmlSchemaPIllegalAttrErr(ctxt,
10078 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10079 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010080 }
10081 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010082 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010083 /*
10084 * Extract and validate attributes.
10085 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010086 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000010087 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010088 * Attribute
William M. Brack2f2a6632004-08-20 23:09:47 +000010089 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010090 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010091 * Extract the base type. The "base" attribute is mandatory if inside
10092 * a complex type or if redefining.
10093 *
10094 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010095 * among its [children]), the simple type definition which is
10096 * the {content type} of the type definition ·resolved· to by
10097 * the ·actual value· of the base [attribute]"
10098 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010099 if (xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010100 NULL, NULL, node, "base",
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010101 &(type->baseNs), &(type->base)) == 0)
10102 {
10103 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
10104 xmlSchemaPMissingAttrErr(ctxt,
10105 XML_SCHEMAP_S4S_ATTR_MISSING,
10106 type, node, "base", NULL);
10107 } else if ((ctxt->isRedefine) &&
10108 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
10109 {
10110 if (type->base == NULL) {
10111 xmlSchemaPMissingAttrErr(ctxt,
10112 XML_SCHEMAP_S4S_ATTR_MISSING,
10113 type, node, "base", NULL);
10114 } else if ((! xmlStrEqual(type->base, type->name)) ||
10115 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
10116 {
10117 xmlChar *str1 = NULL, *str2 = NULL;
10118 /*
10119 * REDEFINE: SPEC src-redefine (5)
10120 * "Within the [children], each <simpleType> must have a
10121 * <restriction> among its [children] ... the ·actual value· of
10122 * whose base [attribute] must be the same as the ·actual value·
10123 * of its own name attribute plus target namespace;"
10124 */
10125 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
10126 NULL, NULL, node, "This is a redefinition, but the QName "
10127 "value '%s' of the 'base' attribute does not match the "
10128 "type's designation '%s'",
10129 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
10130 xmlSchemaFormatQName(&str1, type->targetNamespace,
10131 type->name), NULL);
10132 FREE_AND_NULL(str1);
10133 FREE_AND_NULL(str2);
10134 }
10135 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010136 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010137 /*
10138 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010139 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010140 child = node->children;
10141 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010142 /*
10143 * Add the annotation to the simple type ancestor.
10144 */
10145 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10146 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010147 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010148 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010149 oldcontainer = ctxt->container;
10150 ctxt->container = container;
10151 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
10152 /*
10153 * Corresponds to <simpleType><restriction><simpleType>.
10154 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010155 if (IS_SCHEMA(child, "simpleType")) {
10156 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010157 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000010158 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010159 * Either the base [attribute] or the simpleType [child] of the
10160 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +000010161 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010162 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010163 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010164 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +000010165 "The attribute 'base' and the <simpleType> child are "
10166 "mutually exclusive", NULL);
10167 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010168 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +000010169 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010170 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010171 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010172 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010173 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010174 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
10175 NULL, NULL, node, child,
10176 "Either the attribute 'base' or a <simpleType> child "
10177 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000010178 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010179 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10180 /*
10181 * Corresponds to <complexType><complexContent><restriction>...
10182 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010183 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010184 * Model groups <all>, <choice> and <sequence>.
10185 */
10186 if (IS_SCHEMA(child, "all")) {
10187 type->subtypes = (xmlSchemaTypePtr)
10188 xmlSchemaParseModelGroup(ctxt, schema, child,
10189 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010190 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010191 } else if (IS_SCHEMA(child, "choice")) {
10192 type->subtypes = (xmlSchemaTypePtr)
10193 xmlSchemaParseModelGroup(ctxt,
10194 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
10195 child = child->next;
10196 } else if (IS_SCHEMA(child, "sequence")) {
10197 type->subtypes = (xmlSchemaTypePtr)
10198 xmlSchemaParseModelGroup(ctxt, schema, child,
10199 XML_SCHEMA_TYPE_SEQUENCE, 1);
10200 child = child->next;
10201 /*
10202 * Model group reference <group>.
10203 */
10204 } else if (IS_SCHEMA(child, "group")) {
10205 type->subtypes = (xmlSchemaTypePtr)
10206 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10207 child = child->next;
10208 }
10209 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010210 /*
10211 * Corresponds to <complexType><simpleContent><restriction>...
10212 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010213 * "1.1 the simple type definition corresponding to the <simpleType>
10214 * among the [children] of <restriction> if there is one;"
10215 */
10216 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010217 /*
10218 * We will store the to-be-restricted simple type in
10219 * type->contentTypeDef *temporarily*.
10220 */
10221 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010222 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010223 if ( type->contentTypeDef == NULL)
10224 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010225 child = child->next;
10226 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010227 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010228
10229 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010230 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010231 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010232 /*
10233 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010234 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010235 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010236
Daniel Veillard01fa6152004-06-29 17:04:39 +000010237 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010238 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010239 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010240 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010241 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
10242 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +000010243 * *Single Facet Value*
10244 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010245 while ((IS_SCHEMA(child, "minInclusive")) ||
10246 (IS_SCHEMA(child, "minExclusive")) ||
10247 (IS_SCHEMA(child, "maxInclusive")) ||
10248 (IS_SCHEMA(child, "maxExclusive")) ||
10249 (IS_SCHEMA(child, "totalDigits")) ||
10250 (IS_SCHEMA(child, "fractionDigits")) ||
10251 (IS_SCHEMA(child, "pattern")) ||
10252 (IS_SCHEMA(child, "enumeration")) ||
10253 (IS_SCHEMA(child, "whiteSpace")) ||
10254 (IS_SCHEMA(child, "length")) ||
10255 (IS_SCHEMA(child, "maxLength")) ||
10256 (IS_SCHEMA(child, "minLength"))) {
10257 facet = xmlSchemaParseFacet(ctxt, schema, child);
10258 if (facet != NULL) {
10259 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010260 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010261 else
10262 lastfacet->next = facet;
10263 lastfacet = facet;
10264 lastfacet->next = NULL;
10265 }
10266 child = child->next;
10267 }
10268 /*
10269 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010270 */
10271 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010272 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
10273
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010274 facet = type->facets;
10275 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010276 facetLink = (xmlSchemaFacetLinkPtr)
10277 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000010278 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010279 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010280 xmlFree(facetLink);
10281 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010282 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010283 facetLink->facet = facet;
10284 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010285 if (lastFacetLink == NULL)
10286 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010287 else
10288 lastFacetLink->next = facetLink;
10289 lastFacetLink = facetLink;
10290 facet = facet->next;
10291 } while (facet != NULL);
10292 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010293 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010294 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
10295 /*
10296 * Attribute uses/declarations.
10297 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010298 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010299 /*
10300 * Attribute wildcard.
10301 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010302 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010303 type->attributeWildcard =
10304 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010305 child = child->next;
10306 }
10307 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010308 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010309 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10310 xmlSchemaPContentErr(ctxt,
10311 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010312 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010313 "annotation?, (group | all | choice | sequence)?, "
10314 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010315 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010316 xmlSchemaPContentErr(ctxt,
10317 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010318 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010319 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10320 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10321 "length | minLength | maxLength | enumeration | whiteSpace | "
10322 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10323 } else {
10324 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010325 xmlSchemaPContentErr(ctxt,
10326 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010327 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010328 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10329 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10330 "length | minLength | maxLength | enumeration | whiteSpace | "
10331 "pattern)*))");
10332 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010333 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010334 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010335 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010336}
10337
10338/**
10339 * xmlSchemaParseExtension:
10340 * @ctxt: a schema validation context
10341 * @schema: the schema being built
10342 * @node: a subtree containing XML Schema informations
10343 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010344 * Parses an <extension>, which is found inside a
10345 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010346 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010347 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010348 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010349 */
10350static xmlSchemaTypePtr
10351xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010352 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010353{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010354 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010355 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010356 char buf[30];
10357 const xmlChar *oldcontainer, *container;
10358 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010359
10360 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10361 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010362 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010363 type = ctxt->ctxtType;
10364 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010365
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010366 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10367 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10368 /*
10369 * Check for illegal attributes.
10370 */
10371 attr = node->properties;
10372 while (attr != NULL) {
10373 if (attr->ns == NULL) {
10374 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10375 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010376 xmlSchemaPIllegalAttrErr(ctxt,
10377 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10378 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010379 }
10380 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010381 xmlSchemaPIllegalAttrErr(ctxt,
10382 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10383 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010384 }
10385 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010386 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010387
10388 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010389
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010390 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010391 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010392 */
10393 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010394 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10395 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010396 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010397 XML_SCHEMAP_S4S_ATTR_MISSING,
10398 NULL, node, "base", NULL);
10399 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010400 /*
10401 * And now for the children...
10402 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010403 child = node->children;
10404 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010405 /*
10406 * Add the annotation to the type ancestor.
10407 */
10408 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10409 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010410 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010411 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010412 oldcontainer = ctxt->container;
10413 ctxt->container = container;
10414 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10415 /*
10416 * Corresponds to <complexType><complexContent><extension>... and:
10417 *
10418 * Model groups <all>, <choice>, <sequence> and <group>.
10419 */
10420 if (IS_SCHEMA(child, "all")) {
10421 type->subtypes = (xmlSchemaTypePtr)
10422 xmlSchemaParseModelGroup(ctxt, schema,
10423 child, XML_SCHEMA_TYPE_ALL, 1);
10424 child = child->next;
10425 } else if (IS_SCHEMA(child, "choice")) {
10426 type->subtypes = (xmlSchemaTypePtr)
10427 xmlSchemaParseModelGroup(ctxt, schema,
10428 child, XML_SCHEMA_TYPE_CHOICE, 1);
10429 child = child->next;
10430 } else if (IS_SCHEMA(child, "sequence")) {
10431 type->subtypes = (xmlSchemaTypePtr)
10432 xmlSchemaParseModelGroup(ctxt, schema,
10433 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10434 child = child->next;
10435 } else if (IS_SCHEMA(child, "group")) {
10436 type->subtypes = (xmlSchemaTypePtr)
10437 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10438 child = child->next;
10439 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010440 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010441 if (child != NULL) {
10442 /*
10443 * Attribute uses/declarations.
10444 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010445 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010446 /*
10447 * Attribute wildcard.
10448 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010449 if (IS_SCHEMA(child, "anyAttribute")) {
10450 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010451 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10452 child = child->next;
10453 }
10454 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010455 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010456 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10457 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010458 xmlSchemaPContentErr(ctxt,
10459 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010460 NULL, NULL, node, child, NULL,
10461 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010462 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010463 } else {
10464 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010465 xmlSchemaPContentErr(ctxt,
10466 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010467 NULL, NULL, node, child, NULL,
10468 "(annotation?, ((attribute | attributeGroup)*, "
10469 "anyAttribute?))");
10470 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010471 }
10472 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010473 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010474}
10475
10476/**
10477 * xmlSchemaParseSimpleContent:
10478 * @ctxt: a schema validation context
10479 * @schema: the schema being built
10480 * @node: a subtree containing XML Schema informations
10481 *
10482 * parse a XML schema SimpleContent definition
10483 * *WARNING* this interface is highly subject to change
10484 *
10485 * Returns the type definition or NULL in case of error
10486 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010487static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010488xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010489 xmlSchemaPtr schema, xmlNodePtr node,
10490 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000010491{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010492 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010493 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010494 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010495
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010496 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
10497 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010498 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010499 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010500 /* Not a component, don't create it. */
10501 type = ctxt->ctxtType;
10502 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10503 /*
10504 * Check for illegal attributes.
10505 */
10506 attr = node->properties;
10507 while (attr != NULL) {
10508 if (attr->ns == NULL) {
10509 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010510 xmlSchemaPIllegalAttrErr(ctxt,
10511 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10512 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010513 }
10514 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010515 xmlSchemaPIllegalAttrErr(ctxt,
10516 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10517 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010518 }
10519 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010520 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010521
10522 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010523
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010524 /*
10525 * And now for the children...
10526 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010527 child = node->children;
10528 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010529 /*
10530 * Add the annotation to the complex type ancestor.
10531 */
10532 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10533 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010534 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010535 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010536 if (child == NULL) {
10537 xmlSchemaPContentErr(ctxt,
10538 XML_SCHEMAP_S4S_ELEM_MISSING,
10539 NULL, NULL, node, NULL, NULL,
10540 "(annotation?, (restriction | extension))");
10541 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010542 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010543 xmlSchemaParseRestriction(ctxt, schema, child,
10544 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010545 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010546 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010547 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010548 xmlSchemaParseExtension(ctxt, schema, child,
10549 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010550 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010551 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010552 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010553 if (child != NULL) {
10554 xmlSchemaPContentErr(ctxt,
10555 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010556 NULL, NULL, node, child, NULL,
10557 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010558 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010559 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010560}
10561
10562/**
10563 * xmlSchemaParseComplexContent:
10564 * @ctxt: a schema validation context
10565 * @schema: the schema being built
10566 * @node: a subtree containing XML Schema informations
10567 *
10568 * parse a XML schema ComplexContent definition
10569 * *WARNING* this interface is highly subject to change
10570 *
10571 * Returns the type definition or NULL in case of error
10572 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010573static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010574xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010575 xmlSchemaPtr schema, xmlNodePtr node,
10576 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000010577{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010578 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010579 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010580 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010581
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010582 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
10583 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010584 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010585 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010586 /* Not a component, don't create it. */
10587 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010588 /*
10589 * Check for illegal attributes.
10590 */
10591 attr = node->properties;
10592 while (attr != NULL) {
10593 if (attr->ns == NULL) {
10594 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010595 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010596 {
10597 xmlSchemaPIllegalAttrErr(ctxt,
10598 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10599 NULL, NULL, attr);
10600 }
10601 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10602 xmlSchemaPIllegalAttrErr(ctxt,
10603 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10604 NULL, NULL, attr);
10605 }
10606 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010607 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010608
10609 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10610
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010611 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010612 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010613 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010614 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10615 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10616 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010617 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010618 child = node->children;
10619 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010620 /*
10621 * Add the annotation to the complex type ancestor.
10622 */
10623 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10624 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010625 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010626 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010627 if (child == NULL) {
10628 xmlSchemaPContentErr(ctxt,
10629 XML_SCHEMAP_S4S_ELEM_MISSING,
10630 NULL, NULL, node, NULL,
10631 NULL, "(annotation?, (restriction | extension))");
10632 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010633 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010634 xmlSchemaParseRestriction(ctxt, schema, child,
10635 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010636 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010637 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010638 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010639 xmlSchemaParseExtension(ctxt, schema, child,
10640 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010641 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010642 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010643 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010644 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010645 xmlSchemaPContentErr(ctxt,
10646 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10647 NULL, NULL, node, child,
10648 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010649 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010650 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010651}
10652
10653/**
10654 * xmlSchemaParseComplexType:
10655 * @ctxt: a schema validation context
10656 * @schema: the schema being built
10657 * @node: a subtree containing XML Schema informations
10658 *
10659 * parse a XML schema Complex Type definition
10660 * *WARNING* this interface is highly subject to change
10661 *
10662 * Returns the type definition or NULL in case of error
10663 */
10664static xmlSchemaTypePtr
10665xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010666 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010667{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010668 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010669 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010670 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010671 xmlAttrPtr attr;
10672 const xmlChar *attrValue;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010673 char buf[40];
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010674 int final = 0, block = 0, hasRestrictionOrExtension = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010675
Daniel Veillard4255d502002-04-16 15:50:10 +000010676
10677 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10678 return (NULL);
10679
Daniel Veillard01fa6152004-06-29 17:04:39 +000010680 ctxtType = ctxt->ctxtType;
10681
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010682 if (topLevel) {
10683 attr = xmlSchemaGetPropNode(node, "name");
10684 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010685 xmlSchemaPMissingAttrErr(ctxt,
10686 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010687 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010688 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010689 NULL, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010690 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10691 return (NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010692 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010693 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010694
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010695 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010696 /*
10697 * Parse as local complex type definition.
10698 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010699 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010700 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL,
10701 node, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010702 if (type == NULL)
10703 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010704 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010705 type->node = node;
10706 type->type = XML_SCHEMA_TYPE_COMPLEX;
10707 /*
10708 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010709 */
10710 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010711 /*
10712 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010713 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010714 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace,
10715 node, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010716 if (type == NULL)
10717 return (NULL);
10718 type->node = node;
10719 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010720 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010721 }
10722 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010723 /*
10724 * Handle attributes.
10725 */
10726 attr = node->properties;
10727 while (attr != NULL) {
10728 if (attr->ns == NULL) {
10729 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10730 /*
10731 * Attribute "id".
10732 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010733 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10734 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010735 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10736 /*
10737 * Attribute "mixed".
10738 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010739 if (xmlSchemaPGetBoolNodeValue(ctxt, NULL, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010740 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010741 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10742 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010743 /*
10744 * Attributes of global complex type definitions.
10745 */
10746 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10747 /* Pass. */
10748 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10749 /*
10750 * Attribute "abstract".
10751 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010752 if (xmlSchemaPGetBoolNodeValue(ctxt, NULL, type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010753 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010754 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10755 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10756 /*
10757 * Attribute "final".
10758 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010759 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010760 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010761 if (xmlSchemaPValAttrBlockFinal(attrValue,
10762 &(type->flags),
10763 -1,
10764 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10765 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10766 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010767 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010768 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010769 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010770 type, (xmlNodePtr) attr, NULL,
10771 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010772 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010773 } else
10774 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010775 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10776 /*
10777 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010778 */
10779 attrValue = xmlSchemaGetNodeContent(ctxt,
10780 (xmlNodePtr) attr);
10781 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010782 -1,
10783 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010784 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010785 -1, -1, -1) != 0) {
10786 xmlSchemaPSimpleTypeErr(ctxt,
10787 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010788 type, (xmlNodePtr) attr, NULL,
10789 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010790 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010791 } else
10792 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010793 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010794 xmlSchemaPIllegalAttrErr(ctxt,
10795 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010796 NULL, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010797 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010798 } else {
10799 xmlSchemaPIllegalAttrErr(ctxt,
10800 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010801 NULL, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010802 }
10803 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010804 xmlSchemaPIllegalAttrErr(ctxt,
10805 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010806 NULL, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010807 }
10808 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010809 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010810 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010811 /*
10812 * Apply default "block" values.
10813 */
10814 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10815 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10816 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10817 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10818 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010819 if (! final) {
10820 /*
10821 * Apply default "block" values.
10822 */
10823 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
10824 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
10825 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
10826 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
10827 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010828 /*
10829 * And now for the children...
10830 */
10831 oldcontainer = ctxt->container;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010832 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010833 child = node->children;
10834 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010835 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10836 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010837 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010838 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010839 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010840 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010841 * <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010842 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010843 * Specifying mixed='true' when the <simpleContent>
10844 * alternative is chosen has no effect
10845 */
William M. Bracke7091952004-05-11 15:09:58 +000010846 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10847 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010848 xmlSchemaParseSimpleContent(ctxt, schema, child,
10849 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010850 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010851 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010852 /*
10853 * <complexType><complexContent>...
10854 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010855 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010856 xmlSchemaParseComplexContent(ctxt, schema, child,
10857 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010858 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010859 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010860 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010861 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
10862 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010863 * SPEC
10864 * "...the third alternative (neither <simpleContent> nor
10865 * <complexContent>) is chosen. This case is understood as shorthand
10866 * for complex content restricting the ·ur-type definition·, and the
10867 * details of the mappings should be modified as necessary.
10868 */
10869 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10870 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010871 /*
10872 * Parse model groups.
10873 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010874 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010875 type->subtypes = (xmlSchemaTypePtr)
10876 xmlSchemaParseModelGroup(ctxt, schema, child,
10877 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010878 child = child->next;
10879 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010880 type->subtypes = (xmlSchemaTypePtr)
10881 xmlSchemaParseModelGroup(ctxt, schema, child,
10882 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010883 child = child->next;
10884 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010885 type->subtypes = (xmlSchemaTypePtr)
10886 xmlSchemaParseModelGroup(ctxt, schema, child,
10887 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010888 child = child->next;
10889 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010890 type->subtypes = (xmlSchemaTypePtr)
10891 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010892 child = child->next;
10893 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010894 /*
10895 * Parse attribute decls/refs.
10896 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010897 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010898 /*
10899 * Parse attribute wildcard.
10900 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010901 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010902 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10903 child = child->next;
10904 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010905 }
10906 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010907 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010908 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010909 NULL, type, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010910 NULL, "(annotation?, (simpleContent | complexContent | "
10911 "((group | all | choice | sequence)?, ((attribute | "
10912 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010913 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010914 /*
10915 * REDEFINE: SPEC src-redefine (5)
10916 */
10917 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
10918 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
10919 NULL, NULL, node, "This is a redefinition, thus the "
10920 "<complexType> must have a <restriction> or <extension> "
10921 "grand-child", NULL);
10922 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010923 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010924 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010925 return (type);
10926}
10927
Daniel Veillard4255d502002-04-16 15:50:10 +000010928/**
10929 * xmlSchemaParseSchema:
10930 * @ctxt: a schema validation context
10931 * @node: a subtree containing XML Schema informations
10932 *
10933 * parse a XML schema definition from a node set
10934 * *WARNING* this interface is highly subject to change
10935 *
10936 * Returns the internal XML Schema structure built from the resource or
10937 * NULL in case of error
10938 */
10939static xmlSchemaPtr
10940xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10941{
10942 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010943 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010944 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010945 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010946
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010947 /*
10948 * This one is called by xmlSchemaParse only and is used if
10949 * the schema to be parsed was specified via the API; i.e. not
10950 * automatically by the validated instance document.
10951 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010952 if ((ctxt == NULL) || (node == NULL))
10953 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010954 nberrors = ctxt->nberrors;
10955 ctxt->nberrors = 0;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010956 ctxt->isS4S = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010957 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010958 xmlSchemaImportPtr import;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010959 /* xmlSchemaSchemaRefPtr ref; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010960
Daniel Veillard4255d502002-04-16 15:50:10 +000010961 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010962 if (schema == NULL)
10963 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010964 attr = xmlSchemaGetPropNode(node, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +000010965 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010966 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010967 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10968 /*
10969 * TODO: Should we proceed with an invalid target namespace?
10970 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010971 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010972 if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
10973 /*
10974 * We are parsing the schema for schema!
10975 */
10976 ctxt->isS4S = 1;
10977 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010978 } else {
10979 schema->targetNamespace = NULL;
10980 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010981 /*
10982 * Add the current ns name and location to the import table;
10983 * this is needed to have a consistent mechanism, regardless
10984 * if all schemata are constructed dynamically fired by the
10985 * instance or if the schema to be used was specified via
10986 * the API.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010987 * TODO
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010988 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010989 /*
10990 ref = xmlSchemaNewSchemaRef();
10991 if (ref == NULL) {
10992 xmlSchemaFree(schema);
10993 schema = NULL;
10994 return NULL;
10995 }
10996 */
10997
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010998 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10999 schema->targetNamespace);
11000 if (import == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011001 xmlSchemaPInternalErr(ctxt, "xmlSchemaParseSchema",
11002 "failed to add an import entry", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011003 xmlSchemaFree(schema);
11004 schema = NULL;
11005 return (NULL);
11006 }
11007 import->schemaLocation = ctxt->URL;
11008 /*
11009 * NOTE: We won't set the doc here, otherwise it will be freed
11010 * if the import struct is freed.
11011 * import->doc = ctxt->doc;
11012 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011013 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011014 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
11015 } else {
11016 xmlDocPtr doc;
11017
11018 doc = node->doc;
11019
11020 if ((doc != NULL) && (doc->URL != NULL)) {
11021 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
11022 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011023 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011024 } else {
11025 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
11026 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011027 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011028 }
11029 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011030 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011031 if (ctxt->nberrors != 0) {
11032 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011033 xmlSchemaFree(schema);
11034 schema = NULL;
11035 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011036 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011037 if (schema != NULL)
11038 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011039 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000011040#ifdef DEBUG
11041 if (schema == NULL)
11042 xmlGenericError(xmlGenericErrorContext,
11043 "xmlSchemaParse() failed\n");
11044#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000011045 return (schema);
11046}
11047
11048/************************************************************************
11049 * *
11050 * Validating using Schemas *
11051 * *
11052 ************************************************************************/
11053
11054/************************************************************************
11055 * *
11056 * Reading/Writing Schemas *
11057 * *
11058 ************************************************************************/
11059
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011060#if 0 /* Will be enabled if it is clear what options are needed. */
11061/**
11062 * xmlSchemaParserCtxtSetOptions:
11063 * @ctxt: a schema parser context
11064 * @options: a combination of xmlSchemaParserOption
11065 *
11066 * Sets the options to be used during the parse.
11067 *
11068 * Returns 0 in case of success, -1 in case of an
11069 * API error.
11070 */
11071static int
11072xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
11073 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011074
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011075{
11076 int i;
11077
11078 if (ctxt == NULL)
11079 return (-1);
11080 /*
11081 * WARNING: Change the start value if adding to the
11082 * xmlSchemaParseOption.
11083 */
11084 for (i = 1; i < (int) sizeof(int) * 8; i++) {
11085 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011086 return (-1);
11087 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011088 }
11089 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011090 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011091}
11092
11093/**
11094 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011095 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011096 *
11097 * Returns the option combination of the parser context.
11098 */
11099static int
11100xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011101
11102{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011103 if (ctxt == NULL)
11104 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011105 else
11106 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011107}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011108#endif
11109
Daniel Veillard4255d502002-04-16 15:50:10 +000011110/**
11111 * xmlSchemaNewParserCtxt:
11112 * @URL: the location of the schema
11113 *
11114 * Create an XML Schemas parse context for that file/resource expected
11115 * to contain an XML Schemas file.
11116 *
11117 * Returns the parser context or NULL in case of error
11118 */
11119xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011120xmlSchemaNewParserCtxt(const char *URL)
11121{
Daniel Veillard4255d502002-04-16 15:50:10 +000011122 xmlSchemaParserCtxtPtr ret;
11123
11124 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011125 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011126
11127 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
11128 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011129 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011130 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011131 return (NULL);
11132 }
11133 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011134 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011135 ret->dict = xmlDictCreate();
11136 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000011137 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011138 return (ret);
11139}
11140
11141/**
Daniel Veillard6045c902002-10-09 21:13:59 +000011142 * xmlSchemaNewMemParserCtxt:
11143 * @buffer: a pointer to a char array containing the schemas
11144 * @size: the size of the array
11145 *
11146 * Create an XML Schemas parse context for that memory buffer expected
11147 * to contain an XML Schemas file.
11148 *
11149 * Returns the parser context or NULL in case of error
11150 */
11151xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011152xmlSchemaNewMemParserCtxt(const char *buffer, int size)
11153{
Daniel Veillard6045c902002-10-09 21:13:59 +000011154 xmlSchemaParserCtxtPtr ret;
11155
11156 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011157 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000011158
11159 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
11160 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011161 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011162 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000011163 return (NULL);
11164 }
11165 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
11166 ret->buffer = buffer;
11167 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000011168 ret->dict = xmlDictCreate();
Daniel Veillard210536b2005-08-10 21:40:02 +000011169 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillard6045c902002-10-09 21:13:59 +000011170 return (ret);
11171}
11172
11173/**
Daniel Veillard9d751502003-10-29 13:21:47 +000011174 * xmlSchemaNewDocParserCtxt:
11175 * @doc: a preparsed document tree
11176 *
11177 * Create an XML Schemas parse context for that document.
11178 * NB. The document may be modified during the parsing process.
11179 *
11180 * Returns the parser context or NULL in case of error
11181 */
11182xmlSchemaParserCtxtPtr
11183xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
11184{
11185 xmlSchemaParserCtxtPtr ret;
11186
11187 if (doc == NULL)
11188 return (NULL);
11189
11190 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
11191 if (ret == NULL) {
11192 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
11193 NULL);
11194 return (NULL);
11195 }
11196 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
11197 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000011198 ret->dict = xmlDictCreate();
Daniel Veillard210536b2005-08-10 21:40:02 +000011199 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillarddda22c12004-01-24 08:31:30 +000011200 /* The application has responsibility for the document */
11201 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000011202
11203 return (ret);
11204}
11205
11206/**
Daniel Veillard4255d502002-04-16 15:50:10 +000011207 * xmlSchemaFreeParserCtxt:
11208 * @ctxt: the schema parser context
11209 *
11210 * Free the resources associated to the schema parser context
11211 */
11212void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011213xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
11214{
Daniel Veillard4255d502002-04-16 15:50:10 +000011215 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011216 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000011217 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011218 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011219 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011220 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011221 xmlFree(ctxt->assemble);
11222 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011223 if (ctxt->vctxt != NULL) {
11224 xmlSchemaFreeValidCtxt(ctxt->vctxt);
11225 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000011226 if (ctxt->localImports != NULL)
11227 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011228 if (ctxt->substGroups != NULL)
11229 xmlHashFree(ctxt->substGroups,
11230 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011231 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000011232 xmlFree(ctxt);
11233}
11234
11235/************************************************************************
11236 * *
11237 * Building the content models *
11238 * *
11239 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011240
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011241static void
11242xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011243 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011244{
Daniel Veillarda980bef2005-07-18 21:34:03 +000011245 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011246 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011247 xmlSchemaSubstGroupPtr substGroup;
11248 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011249
11250 elemDecl = (xmlSchemaElementPtr) particle->children;
11251 /*
11252 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011253 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011254 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000011255 if (end == NULL)
11256 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011257 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
11258 if (substGroup == NULL) {
11259 xmlSchemaPErr(pctxt, GET_NODE(particle),
11260 XML_SCHEMAP_INTERNAL,
11261 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
11262 "declaration is marked having a subst. group but none "
11263 "available.\n", elemDecl->name, NULL);
11264 return;
11265 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000011266 if (counter >= 0) {
11267 /*
11268 * NOTE that we put the declaration in, even if it's abstract,
11269 */
11270 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
11271 xmlAutomataNewTransition2(pctxt->am, tmp, end,
11272 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11273 /*
11274 * Add subst. group members.
11275 */
11276 for (i = 0; i < substGroup->members->nbItems; i++) {
11277 member = (xmlSchemaElementPtr) substGroup->members->items[i];
11278 xmlAutomataNewTransition2(pctxt->am, tmp, end,
11279 member->name, member->targetNamespace, member);
11280 }
11281 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011282 /*
11283 * NOTE that we put the declaration in, even if it's abstract,
11284 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011285 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011286 xmlAutomataNewTransition2(pctxt->am,
11287 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011288 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
11289 /*
11290 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011291 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011292 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011293 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000011294 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
11295 member->name, member->targetNamespace,
11296 1, 1, member);
11297 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011298 }
11299 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011300 xmlAutomataStatePtr hop;
11301 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11302 UNBOUNDED : particle->maxOccurs - 1;
11303 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
11304
11305 counter =
11306 xmlAutomataNewCounter(pctxt->am, minOccurs,
11307 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011308 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011309
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011310 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011311 xmlAutomataNewTransition2(pctxt->am,
11312 start, NULL,
11313 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011314 hop);
11315 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000011316 * Add subst. group members.
11317 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011318 for (i = 0; i < substGroup->members->nbItems; i++) {
11319 member = (xmlSchemaElementPtr) substGroup->members->items[i];
11320 xmlAutomataNewEpsilon(pctxt->am,
11321 xmlAutomataNewTransition2(pctxt->am,
11322 start, NULL,
11323 member->name, member->targetNamespace, member),
11324 hop);
11325 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011326 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
11327 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
11328 }
11329 if (particle->minOccurs == 0)
11330 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011331 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011332}
11333
11334static void
11335xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
11336 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011337{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011338 if (((xmlSchemaElementPtr) particle->children)->flags &
11339 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011340 /*
11341 * Substitution groups.
11342 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000011343 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011344 } else {
11345 xmlSchemaElementPtr elemDecl;
11346 xmlAutomataStatePtr start;
11347
11348 elemDecl = (xmlSchemaElementPtr) particle->children;
11349
11350 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011351 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011352 if (particle->maxOccurs == 1) {
11353 start = ctxt->state;
11354 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011355 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11356 } else if ((particle->maxOccurs >= UNBOUNDED) &&
11357 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011358 /* Special case. */
11359 start = ctxt->state;
11360 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11361 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011362 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011363 } else {
11364 int counter;
11365 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11366 UNBOUNDED : particle->maxOccurs - 1;
11367 int minOccurs = particle->minOccurs < 1 ?
11368 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011369
11370 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011371 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11372 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11373 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11374 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
11375 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
11376 NULL, counter);
11377 }
11378 if (particle->minOccurs == 0)
11379 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
11380 }
11381}
11382
Daniel Veillard4255d502002-04-16 15:50:10 +000011383/**
11384 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011385 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011386 * @particle: the particle component
11387 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011388 *
11389 * Generate the automata sequence needed for that type
11390 */
11391static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011392xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011393 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011394 const xmlChar * name)
11395{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011396 if (particle == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011397 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011398 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011399 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011400 if (particle->children == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011401 PERROR_INT("xmlSchemaBuildAContentModel", "no term on particle");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011402 return;
11403 }
11404
11405 switch (particle->children->type) {
11406 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011407 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011408 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011409 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011410
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011411 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011412
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011413 start = pctxt->state;
11414 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011415
11416 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011417 if (wild->any == 1) {
11418 /*
11419 * We need to add both transitions:
11420 *
11421 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011422 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011423 pctxt->state =
11424 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011425 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011426 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011427 /*
11428 * 2. the {"*"} for elements in no namespace.
11429 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011430 pctxt->state =
11431 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011432 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011433 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011434
11435 } else if (wild->nsSet != NULL) {
11436 ns = wild->nsSet;
11437 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011438 pctxt->state = start;
11439 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
11440 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
11441 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011442 ns = ns->next;
11443 } while (ns != NULL);
11444
11445 } else if (wild->negNsSet != NULL) {
Daniel Veillard6e65e152005-08-09 11:09:52 +000011446 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
11447 start, end, BAD_CAST "*", wild->negNsSet->value,
11448 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011449 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011450 } else {
11451 int counter;
11452 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011453 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011454 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011455 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011456 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011457
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011458 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
11459 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011460 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011461 pctxt->state =
11462 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011463 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011464 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
11465 pctxt->state =
11466 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011467 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011468 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011469 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011470 ns = wild->nsSet;
11471 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011472 pctxt->state =
11473 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011474 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011475 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011476 ns = ns->next;
11477 } while (ns != NULL);
11478
11479 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011480 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000011481 start, hop, BAD_CAST "*", wild->negNsSet->value,
11482 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011483 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011484 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
11485 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011486 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011487 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011488 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011489 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011490 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011491 break;
11492 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011493 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011494 xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011495 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011496 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011497 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011498
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011499 /*
11500 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011501 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011502 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011503 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11504 sub = particle->children->children;
11505 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011506 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011507 (xmlSchemaParticlePtr) sub, name);
11508 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011509 }
11510 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011511 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011512
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011513 if (particle->maxOccurs >= UNBOUNDED) {
11514 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011515 xmlAutomataStatePtr tmp;
11516 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011517
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011518 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011519 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011520 oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011521
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011522 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011523 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011524
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011525 sub = particle->children->children;
11526 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011527 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011528 (xmlSchemaParticlePtr) sub, name);
11529 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011530 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011531 tmp = pctxt->state;
11532 xmlAutomataNewCountedTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011533 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011534 pctxt->state =
11535 xmlAutomataNewCounterTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011536 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011537
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011538 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011539 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillardafc05b62005-07-17 06:11:19 +000011540 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011541 oldstate = pctxt->state;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011542
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011543 sub = particle->children->children;
11544 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011545 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011546 (xmlSchemaParticlePtr) sub, name);
11547 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011548 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011549 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011550 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011551 /*
11552 * epsilon needed to block previous trans from
11553 * being allowed to enter back from another
11554 * construct
11555 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011556 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
11557 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011558 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011559 xmlAutomataNewEpsilon(pctxt->am,
11560 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011561 }
11562 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011563 } else if ((particle->maxOccurs > 1)
11564 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011565 xmlAutomataStatePtr tmp;
11566 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011567
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011568 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011569 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011570 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011571
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011572 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011573 particle->minOccurs - 1,
11574 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011575
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011576 sub = particle->children->children;
11577 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011578 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011579 (xmlSchemaParticlePtr) sub, name);
11580 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011581 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011582 tmp = pctxt->state;
11583 xmlAutomataNewCountedTrans(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011584 tmp, oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011585 pctxt->state =
11586 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011587 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011588 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011589 xmlAutomataNewEpsilon(pctxt->am,
11590 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011591 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011592 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011593 sub = particle->children->children;
11594 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011595 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011596 (xmlSchemaParticlePtr) sub, name);
11597 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011598 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011599 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011600 xmlAutomataNewEpsilon(pctxt->am, oldstate,
11601 pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011602 }
11603 }
11604 }
11605 break;
11606 }
11607 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011608 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011609 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011610
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011611 start = pctxt->state;
11612 end = xmlAutomataNewState(pctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011613
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011614 /*
11615 * iterate over the subtypes and remerge the end with an
11616 * epsilon transition
11617 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011618 if (particle->maxOccurs == 1) {
11619 sub = particle->children->children;
11620 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011621 pctxt->state = start;
11622 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011623 (xmlSchemaParticlePtr) sub, name);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011624 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011625 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011626 }
11627 } else {
11628 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011629 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011630 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11631 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011632 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011633 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011634
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011635 /*
11636 * use a counter to keep track of the number of transtions
11637 * which went through the choice.
11638 */
11639 counter =
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011640 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
11641 hop = xmlAutomataNewState(pctxt->am);
11642 base = xmlAutomataNewState(pctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011643
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011644 sub = particle->children->children;
11645 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011646 pctxt->state = base;
11647 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011648 (xmlSchemaParticlePtr) sub, name);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011649 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011650 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000011651 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011652 xmlAutomataNewEpsilon(pctxt->am, start, base);
11653 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
11654 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011655 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011656 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011657 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011658 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011659 pctxt->state = end;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011660 break;
11661 }
11662 case XML_SCHEMA_TYPE_ALL:{
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +000011663 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011664 xmlSchemaParticlePtr sub;
11665 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011666 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011667
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011668 sub = (xmlSchemaParticlePtr) particle->children->children;
11669 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011670 break;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011671 start = pctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011672 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011673 pctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011674
11675 elemDecl = (xmlSchemaElementPtr) sub->children;
11676 if (elemDecl == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011677 PERROR_INT("xmlSchemaBuildAContentModel",
11678 "<element> particle has no term");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011679 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011680 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011681 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011682 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011683 * {particles} of the group must be 0 or 1; this is
11684 * already ensured during the parse of the content of
11685 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011686 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000011687 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
11688 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011689
Daniel Veillarda980bef2005-07-18 21:34:03 +000011690 /*
11691 * This is an abstract group, we need to share
11692 * the same counter for all the element transitions
11693 * derived from the group
11694 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011695 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011696 sub->minOccurs, sub->maxOccurs);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011697 xmlSchemaBuildContentModelForSubstGroup(pctxt,
11698 sub, counter, pctxt->state);
Daniel Veillarda980bef2005-07-18 21:34:03 +000011699 } else {
11700 if ((sub->minOccurs == 1) &&
11701 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011702 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
11703 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011704 elemDecl->name,
11705 elemDecl->targetNamespace,
11706 1, 1, elemDecl);
11707 } else if ((sub->minOccurs == 0) &&
11708 (sub->maxOccurs == 1)) {
11709
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011710 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
11711 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011712 elemDecl->name,
11713 elemDecl->targetNamespace,
11714 0,
11715 1,
11716 elemDecl);
11717 }
11718 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011719 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011720 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011721 lax = particle->minOccurs == 0;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011722 pctxt->state =
11723 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011724 break;
11725 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011726 case XML_SCHEMA_TYPE_GROUP:
11727 /*
11728 * If we hit a model group definition, then this means that
11729 * it was empty, thus was not substituted for the containing
11730 * model group. Just do nothing in this case.
11731 */
11732 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011733 default:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011734 xmlSchemaPInternalErr(pctxt, "xmlSchemaBuildAContentModel",
11735 "found unexpected term of type '%s' in content model of complex "
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +000011736 "type '%s'",
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011737 xmlSchemaCompTypeToString(particle->children->type), name);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +000011738 xmlGenericError(xmlGenericErrorContext,
11739 "Unexpected type: %d\n", particle->children->type);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011740 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011741 }
11742}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011743
Daniel Veillard4255d502002-04-16 15:50:10 +000011744/**
11745 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011746 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011747 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011748 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011749 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011750 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011751 */
11752static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011753xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011754 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011755 const xmlChar * name)
11756{
Daniel Veillard4255d502002-04-16 15:50:10 +000011757 xmlAutomataStatePtr start;
11758
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011759 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11760 (type->contModel != NULL) ||
11761 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11762 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011763 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011764
11765#ifdef DEBUG_CONTENT
11766 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011767 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011768#endif
11769
Daniel Veillard4255d502002-04-16 15:50:10 +000011770 ctxt->am = xmlNewAutomata();
11771 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011772 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011773 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011774 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011775 }
11776 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011777 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011778 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011779 type->contModel = xmlAutomataCompile(ctxt->am);
11780 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011781 xmlSchemaPCustomErr(ctxt,
11782 XML_SCHEMAP_INTERNAL,
11783 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011784 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011785 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011786 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011787 XML_SCHEMAP_NOT_DETERMINISTIC,
11788 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011789 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011790 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011791 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011792#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011793 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011794 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011795 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011796#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011797 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011798 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011799 xmlFreeAutomata(ctxt->am);
11800 ctxt->am = NULL;
11801}
11802
11803/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011804 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011805 * @elem: the schema element context
11806 * @ctxt: the schema parser context
11807 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011808 * Resolves the references of an element declaration
11809 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011810 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011811 */
11812static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011813xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011814 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011815 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011816 const xmlChar * context ATTRIBUTE_UNUSED,
11817 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011818{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011819 if ((ctxt == NULL) || (elemDecl == NULL) ||
11820 ((elemDecl != NULL) &&
11821 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011822 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011823 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011824
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011825 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011826 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011827
11828 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011829 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011830 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011831 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011832 elemDecl->namedTypeNs);
11833 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011834 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011835 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011836 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011837 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011838 XML_SCHEMA_TYPE_BASIC, "type definition");
11839 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011840 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011841 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011842 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011843 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011844
Daniel Veillardc0826a72004-08-10 14:17:33 +000011845 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011846 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011847 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011848 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011849 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11850 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011851 if (substHead == NULL) {
11852 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011853 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011854 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011855 "substitutionGroup", elemDecl->substGroup,
11856 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011857 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011858 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011859 /*
11860 * Set the "substitution group affiliation".
11861 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011862 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011863 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011864 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011865 * (type definition)...otherwise the {type definition} of the
11866 * element declaration ·resolved· to by the ·actual value· of
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011867 * the substitutionGroup [attribute], if present
11868 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011869 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011870 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011871 }
11872 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011873 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11874 (elemDecl->substGroup == NULL))
11875 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011876}
11877
11878/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011879 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011880 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011881 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011882 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011883 * Checks and builds the "member type definitions" property of the union
11884 * simple type. This handles part (1), part (2) is done in
11885 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11886 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011887 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011888 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011889static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011890xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11891 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011892{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011893
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011894 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011895 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011896
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011897 /*
11898 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
11899 * define the explicit members as the type definitions ·resolved·
11900 * to by the items in the ·actual value· of the memberTypes [attribute],
11901 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011902 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011903 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011904 /*
11905 * Resolve references.
11906 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011907 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011908 lastLink = NULL;
11909 while (link != NULL) {
11910 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011911
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011912 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11913 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11914
11915 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11916 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11917 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011918 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011919 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11920 /*
11921 * Remove the member type link.
11922 */
11923 if (lastLink == NULL)
11924 type->memberTypes = link->next;
11925 else
11926 lastLink->next = link->next;
11927 newLink = link;
11928 link = link->next;
11929 xmlFree(newLink);
11930 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011931 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011932 lastLink = link;
11933 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011934 }
11935 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011936 /*
11937 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011938 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011939 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011940 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011941 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11942 if (link == NULL) {
11943 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11944 return (-1);
11945 }
11946 link->type = memberType;
11947 link->next = NULL;
11948 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011949 type->memberTypes = link;
11950 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000011951 lastLink->next = link;
11952 lastLink = link;
11953 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011954 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011955 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011956}
11957
Daniel Veillard4255d502002-04-16 15:50:10 +000011958/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011959 * xmlSchemaIsDerivedFromBuiltInType:
11960 * @ctxt: the schema parser context
11961 * @type: the type definition
11962 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011963 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011964 *
11965 * Returns 1 if the type has the given value type, or
11966 * is derived from such a type.
11967 */
William M. Brack803812b2004-06-03 02:11:24 +000011968static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011969xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011970{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011971 if (type == NULL)
11972 return (0);
11973 if (IS_COMPLEX_TYPE(type))
11974 return (0);
11975 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11976 if (type->builtInType == valType)
11977 return(1);
11978 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11979 (type->builtInType == XML_SCHEMAS_ANYTYPE))
11980 return (0);
11981 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11982 } else
11983 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000011984
11985 return (0);
11986}
11987
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011988#if 0
11989/**
11990 * xmlSchemaIsDerivedFromBuiltInType:
11991 * @ctxt: the schema parser context
11992 * @type: the type definition
11993 * @valType: the value type
11994 *
11995 *
11996 * Returns 1 if the type has the given value type, or
11997 * is derived from such a type.
11998 */
11999static int
12000xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
12001{
12002 if (type == NULL)
12003 return (0);
12004 if (IS_COMPLEX_TYPE(type))
12005 return (0);
12006 if (type->type == XML_SCHEMA_TYPE_BASIC) {
12007 if (type->builtInType == valType)
12008 return(1);
12009 return (0);
12010 } else
12011 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
12012
12013 return (0);
12014}
12015#endif
12016
12017static xmlSchemaTypePtr
12018xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
12019{
12020 if (type == NULL)
12021 return (NULL);
12022 if (IS_COMPLEX_TYPE(type))
12023 return (NULL);
12024 if (type->type == XML_SCHEMA_TYPE_BASIC)
12025 return(type);
12026 else
12027 return(xmlSchemaQueryBuiltInType(type->subtypes));
12028
12029 return (NULL);
12030}
12031
Daniel Veillard3646d642004-06-02 19:19:14 +000012032/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000012033 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000012034 * @type: the simpleType definition
12035 *
12036 * Returns the primitive type of the given type or
12037 * NULL in case of error.
12038 */
12039static xmlSchemaTypePtr
12040xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
12041{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000012042
Daniel Veillard01fa6152004-06-29 17:04:39 +000012043 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000012044 /*
12045 * Note that anySimpleType is actually not a primitive type
12046 * but we need that here.
12047 */
12048 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
12049 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012050 return (type);
12051 type = type->baseType;
12052 }
12053
12054 return (NULL);
12055}
12056
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000012057#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000012058/**
12059 * xmlSchemaGetBuiltInTypeAncestor:
12060 * @type: the simpleType definition
12061 *
12062 * Returns the primitive type of the given type or
12063 * NULL in case of error.
12064 */
12065static xmlSchemaTypePtr
12066xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
12067{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012068 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000012069 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000012070 while (type != NULL) {
12071 if (type->type == XML_SCHEMA_TYPE_BASIC)
12072 return (type);
12073 type = type->baseType;
12074 }
12075
12076 return (NULL);
12077}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000012078#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000012079
Daniel Veillard01fa6152004-06-29 17:04:39 +000012080/**
Daniel Veillard3646d642004-06-02 19:19:14 +000012081 * xmlSchemaBuildAttributeUsesOwned:
12082 * @ctxt: the schema parser context
12083 * @type: the complex type definition
12084 * @cur: the attribute declaration list
12085 * @lastUse: the top of the attribute use list
12086 *
12087 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012088 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000012089 * xmlSchemaBuildAttributeValidation only.
12090 */
12091static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012092xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012093 xmlSchemaAttributePtr cur,
12094 xmlSchemaAttributeLinkPtr *uses,
12095 xmlSchemaAttributeLinkPtr *lastUse)
12096{
12097 xmlSchemaAttributeLinkPtr tmp;
12098 while (cur != NULL) {
12099 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012100 /*
12101 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
12102 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000012103 * <attributeGroup> [children], if any."
12104 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012105 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
12106 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Daniel Veillard3646d642004-06-02 19:19:14 +000012107 lastUse) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012108 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012109 }
12110 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012111 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000012112 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012113 */
12114 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000012115 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12116 if (tmp == NULL) {
12117 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
12118 return (-1);
12119 }
12120 tmp->attr = cur;
12121 tmp->next = NULL;
12122 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012123 *uses = tmp;
12124 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012125 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012126 *lastUse = tmp;
12127 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012128 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012129 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012130 return (0);
12131}
12132
Daniel Veillard50355f02004-06-08 17:52:16 +000012133/**
12134 * xmlSchemaCloneWildcardNsConstraints:
12135 * @ctxt: the schema parser context
12136 * @dest: the destination wildcard
12137 * @source: the source wildcard
12138 *
12139 * Clones the namespace constraints of source
12140 * and assignes them to dest.
12141 * Returns -1 on internal error, 0 otherwise.
12142 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012143static int
12144xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
12145 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012146 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000012147{
12148 xmlSchemaWildcardNsPtr cur, tmp, last;
12149
12150 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012151 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012152 (*dest)->any = source->any;
12153 cur = source->nsSet;
12154 last = NULL;
12155 while (cur != NULL) {
12156 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
12157 if (tmp == NULL)
12158 return(-1);
12159 tmp->value = cur->value;
12160 if (last == NULL)
12161 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012162 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012163 last->next = tmp;
12164 last = tmp;
12165 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012166 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012167 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012168 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000012169 if (source->negNsSet != NULL) {
12170 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12171 if ((*dest)->negNsSet == NULL)
12172 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012173 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012174 } else
12175 (*dest)->negNsSet = NULL;
12176 return(0);
12177}
12178
Daniel Veillard50355f02004-06-08 17:52:16 +000012179/**
12180 * xmlSchemaUnionWildcards:
12181 * @ctxt: the schema parser context
12182 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012183 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012184 *
12185 * Unions the namespace constraints of the given wildcards.
12186 * @completeWild will hold the resulting union.
12187 * Returns a positive error code on failure, -1 in case of an
12188 * internal error, 0 otherwise.
12189 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012190static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012191xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012192 xmlSchemaWildcardPtr completeWild,
12193 xmlSchemaWildcardPtr curWild)
12194{
12195 xmlSchemaWildcardNsPtr cur, curB, tmp;
12196
12197 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012198 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012199 * value.
12200 */
12201 if ((completeWild->any == curWild->any) &&
12202 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12203 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012204
Daniel Veillard3646d642004-06-02 19:19:14 +000012205 if ((completeWild->negNsSet == NULL) ||
12206 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012207
Daniel Veillard3646d642004-06-02 19:19:14 +000012208 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012209 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012210
12211 /*
12212 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012213 */
12214 cur = completeWild->nsSet;
12215 while (cur != NULL) {
12216 found = 0;
12217 curB = curWild->nsSet;
12218 while (curB != NULL) {
12219 if (cur->value == curB->value) {
12220 found = 1;
12221 break;
12222 }
12223 curB = curB->next;
12224 }
12225 if (!found)
12226 break;
12227 cur = cur->next;
12228 }
12229 if (found)
12230 return(0);
12231 } else
12232 return(0);
12233 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012234 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012235 /*
12236 * 2 If either O1 or O2 is any, then any must be the value
12237 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012238 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012239 if (completeWild->any == 0) {
12240 completeWild->any = 1;
12241 if (completeWild->nsSet != NULL) {
12242 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12243 completeWild->nsSet = NULL;
12244 }
12245 if (completeWild->negNsSet != NULL) {
12246 xmlFree(completeWild->negNsSet);
12247 completeWild->negNsSet = NULL;
12248 }
12249 }
Daniel Veillard50355f02004-06-08 17:52:16 +000012250 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012251 }
12252 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012253 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012254 * then the union of those sets must be the value.
12255 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012256 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012257 int found;
12258 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012259
Daniel Veillard3646d642004-06-02 19:19:14 +000012260 cur = curWild->nsSet;
12261 start = completeWild->nsSet;
12262 while (cur != NULL) {
12263 found = 0;
12264 curB = start;
12265 while (curB != NULL) {
12266 if (cur->value == curB->value) {
12267 found = 1;
12268 break;
12269 }
12270 curB = curB->next;
12271 }
12272 if (!found) {
12273 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012274 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012275 return (-1);
12276 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012277 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000012278 completeWild->nsSet = tmp;
12279 }
12280 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012281 }
12282
Daniel Veillard3646d642004-06-02 19:19:14 +000012283 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012284 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012285 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012286 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000012287 * or ·absent·), then a pair of not and ·absent· must be the value.
12288 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012289 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012290 (curWild->negNsSet != NULL) &&
12291 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
12292 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000012293
12294 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012295 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012296 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012297 * 5.
12298 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012299 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012300 (completeWild->negNsSet->value != NULL) &&
12301 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012302 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012303 (curWild->negNsSet->value != NULL) &&
12304 (completeWild->nsSet != NULL))) {
12305
12306 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012307
Daniel Veillard3646d642004-06-02 19:19:14 +000012308 if (completeWild->nsSet != NULL) {
12309 cur = completeWild->nsSet;
12310 curB = curWild->negNsSet;
12311 } else {
12312 cur = curWild->nsSet;
12313 curB = completeWild->negNsSet;
12314 }
12315 nsFound = 0;
12316 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012317 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012318 absentFound = 1;
12319 else if (cur->value == curB->value)
12320 nsFound = 1;
12321 if (nsFound && absentFound)
12322 break;
12323 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012324 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012325
12326 if (nsFound && absentFound) {
12327 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012328 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000012329 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012330 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012331 completeWild->any = 1;
12332 if (completeWild->nsSet != NULL) {
12333 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12334 completeWild->nsSet = NULL;
12335 }
12336 if (completeWild->negNsSet != NULL) {
12337 xmlFree(completeWild->negNsSet);
12338 completeWild->negNsSet = NULL;
12339 }
12340 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012341 /*
12342 * 5.2 If the set S includes the negated namespace name
12343 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000012344 * be the value.
12345 */
12346 if (completeWild->nsSet != NULL) {
12347 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12348 completeWild->nsSet = NULL;
12349 }
12350 if (completeWild->negNsSet == NULL) {
12351 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12352 if (completeWild->negNsSet == NULL)
12353 return (-1);
12354 }
12355 completeWild->negNsSet->value = NULL;
12356 } else if ((!nsFound) && absentFound) {
12357 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012358 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000012359 * namespace name, then the union is not expressible.
12360 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012361 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000012362 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012363 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012364 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012365 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012366 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012367 /*
12368 * 5.4 If the set S does not include either the negated namespace
12369 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012370 * and a namespace name must be the value.
12371 */
12372 if (completeWild->negNsSet == NULL) {
12373 if (completeWild->nsSet != NULL) {
12374 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12375 completeWild->nsSet = NULL;
12376 }
12377 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12378 if (completeWild->negNsSet == NULL)
12379 return (-1);
12380 completeWild->negNsSet->value = curWild->negNsSet->value;
12381 }
12382 }
12383 return (0);
12384 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012385 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012386 * 6.
12387 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012388 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012389 (completeWild->negNsSet->value == NULL) &&
12390 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012391 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012392 (curWild->negNsSet->value == NULL) &&
12393 (completeWild->nsSet != NULL))) {
12394
12395 if (completeWild->nsSet != NULL) {
12396 cur = completeWild->nsSet;
12397 } else {
12398 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012399 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012400 while (cur != NULL) {
12401 if (cur->value == NULL) {
12402 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012403 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012404 * value.
12405 */
12406 completeWild->any = 1;
12407 if (completeWild->nsSet != NULL) {
12408 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12409 completeWild->nsSet = NULL;
12410 }
12411 if (completeWild->negNsSet != NULL) {
12412 xmlFree(completeWild->negNsSet);
12413 completeWild->negNsSet = NULL;
12414 }
12415 return (0);
12416 }
12417 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012418 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012419 if (completeWild->negNsSet == NULL) {
12420 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012421 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012422 * and ·absent· must be the value.
12423 */
12424 if (completeWild->nsSet != NULL) {
12425 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12426 completeWild->nsSet = NULL;
12427 }
12428 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12429 if (completeWild->negNsSet == NULL)
12430 return (-1);
12431 completeWild->negNsSet->value = NULL;
12432 }
12433 return (0);
12434 }
12435 return (0);
12436
12437}
12438
Daniel Veillard50355f02004-06-08 17:52:16 +000012439/**
12440 * xmlSchemaIntersectWildcards:
12441 * @ctxt: the schema parser context
12442 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012443 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012444 *
12445 * Intersects the namespace constraints of the given wildcards.
12446 * @completeWild will hold the resulting intersection.
12447 * Returns a positive error code on failure, -1 in case of an
12448 * internal error, 0 otherwise.
12449 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012450static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012451xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012452 xmlSchemaWildcardPtr completeWild,
12453 xmlSchemaWildcardPtr curWild)
12454{
William M. Brack803812b2004-06-03 02:11:24 +000012455 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012456
12457 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012458 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012459 * value.
12460 */
12461 if ((completeWild->any == curWild->any) &&
12462 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12463 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012464
Daniel Veillard3646d642004-06-02 19:19:14 +000012465 if ((completeWild->negNsSet == NULL) ||
12466 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012467
Daniel Veillard3646d642004-06-02 19:19:14 +000012468 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012469 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012470
12471 /*
12472 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012473 */
12474 cur = completeWild->nsSet;
12475 while (cur != NULL) {
12476 found = 0;
12477 curB = curWild->nsSet;
12478 while (curB != NULL) {
12479 if (cur->value == curB->value) {
12480 found = 1;
12481 break;
12482 }
12483 curB = curB->next;
12484 }
12485 if (!found)
12486 break;
12487 cur = cur->next;
12488 }
12489 if (found)
12490 return(0);
12491 } else
12492 return(0);
12493 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012494 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012495 /*
12496 * 2 If either O1 or O2 is any, then the other must be the value.
12497 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012498 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012499 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012500 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012501 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012502 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012503 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012504 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12505 * name or ·absent·) and the other is a set of (namespace names or
12506 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012507 * the set, minus ·absent· if it was in the set, must be the value.
12508 */
12509 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12510 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12511 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012512
Daniel Veillard3646d642004-06-02 19:19:14 +000012513 if (completeWild->nsSet == NULL) {
12514 neg = completeWild->negNsSet->value;
12515 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12516 return(-1);
12517 } else
12518 neg = curWild->negNsSet->value;
12519 /*
12520 * Remove absent and negated.
12521 */
12522 prev = NULL;
12523 cur = completeWild->nsSet;
12524 while (cur != NULL) {
12525 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012526 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012527 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012528 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012529 prev->next = cur->next;
12530 xmlFree(cur);
12531 break;
12532 }
12533 prev = cur;
12534 cur = cur->next;
12535 }
12536 if (neg != NULL) {
12537 prev = NULL;
12538 cur = completeWild->nsSet;
12539 while (cur != NULL) {
12540 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012541 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012542 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012543 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012544 prev->next = cur->next;
12545 xmlFree(cur);
12546 break;
12547 }
12548 prev = cur;
12549 cur = cur->next;
12550 }
12551 }
12552
12553 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012554 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012555 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012556 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012557 * then the intersection of those sets must be the value.
12558 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012559 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012560 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012561
Daniel Veillard3646d642004-06-02 19:19:14 +000012562 cur = completeWild->nsSet;
12563 prev = NULL;
12564 while (cur != NULL) {
12565 found = 0;
12566 curB = curWild->nsSet;
12567 while (curB != NULL) {
12568 if (cur->value == curB->value) {
12569 found = 1;
12570 break;
12571 }
12572 curB = curB->next;
12573 }
12574 if (!found) {
12575 if (prev == NULL)
12576 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012577 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012578 prev->next = cur->next;
12579 tmp = cur->next;
12580 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012581 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012582 continue;
12583 }
12584 prev = cur;
12585 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012586 }
12587
Daniel Veillard3646d642004-06-02 19:19:14 +000012588 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012589 }
12590 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012591 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012592 */
12593 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012594 (curWild->negNsSet != NULL) &&
12595 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012596 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012597 (curWild->negNsSet->value != NULL)) {
12598
12599 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012600 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012601 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012602 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012603 }
12604 /*
12605 * 6 If the one is a negation of a namespace name and the other
12606 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012607 * of a namespace name must be the value.
12608 */
12609 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12610 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012611 (completeWild->negNsSet->value == NULL)) {
12612 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012613 }
12614 return(0);
12615}
12616
Daniel Veillard50355f02004-06-08 17:52:16 +000012617/**
12618 * xmlSchemaIsWildcardNsConstraintSubset:
12619 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012620 * @sub: the first wildcard
12621 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012622 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012623 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12624 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012625 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012626 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012627 */
12628static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012629xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12630 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012631{
Daniel Veillard50355f02004-06-08 17:52:16 +000012632 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012633 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012634 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012635 if (super->any)
12636 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012637 /*
12638 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12639 * 2.2 super must be a pair of not and the same value.
12640 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012641 if ((sub->negNsSet != NULL) &&
12642 (super->negNsSet != NULL) &&
12643 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012644 return (0);
12645 /*
12646 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012647 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012648 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012649 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012650 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012651 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012652 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012653 xmlSchemaWildcardNsPtr cur, curB;
12654 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012655
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012656 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012657 while (cur != NULL) {
12658 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012659 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012660 while (curB != NULL) {
12661 if (cur->value == curB->value) {
12662 found = 1;
12663 break;
12664 }
12665 curB = curB->next;
12666 }
12667 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012668 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012669 cur = cur->next;
12670 }
12671 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012672 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012673 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012674 xmlSchemaWildcardNsPtr cur;
12675 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012676 * 3.2.2 super must be a pair of not and a namespace name or
12677 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012678 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012679 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012680 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012681 if (cur->value == super->negNsSet->value)
12682 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012683 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012684 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012685 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012686 }
12687 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012688 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012689}
12690
12691/**
12692 * xmlSchemaBuildCompleteAttributeWildcard:
12693 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012694 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000012695 * @completeWild: the resulting complete wildcard
12696 *
12697 * Returns -1 in case of an internal error, 0 otherwise.
12698 */
12699static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012700xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012701 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012702 xmlSchemaWildcardPtr *completeWild)
12703{
Daniel Veillard3646d642004-06-02 19:19:14 +000012704 while (attrs != NULL) {
12705 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12706 xmlSchemaAttributeGroupPtr group;
12707
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012708 group = (xmlSchemaAttributeGroupPtr) attrs;
12709 /*
12710 * Handle attribute group references.
12711 */
12712 if (group->ref != NULL) {
12713 if (group->refItem == NULL) {
12714 /*
12715 * TODO: Should we raise a warning here?
12716 */
12717 /*
12718 * The referenced attribute group definition could not
12719 * be resolved beforehand, so skip.
12720 */
12721 attrs = attrs->next;
12722 continue;
12723 } else
12724 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012725 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012726 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012727 * For every attribute group definition, an intersected wildcard
12728 * will be created (assumed that a wildcard exists on the
12729 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012730 * at all).
12731 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12732 * that the intersection will be performed only once.
12733 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012734 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12735 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012736 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012737 group->attributes, &group->attributeWildcard) == -1)
12738 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012739 }
12740 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012741 }
12742 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012743 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012744 /*
12745 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012746 *
12747 * Although the complete wildcard might not correspond to any
12748 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012749 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012750 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12751 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12752 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012753 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012754 completeWild, group->attributeWildcard) == -1)
12755 return (-1);
12756 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012757 (*completeWild)->node = group->attributeWildcard->node;
12758 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012759 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012760 }
12761 }
12762 attrs = attrs->next;
12763 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012764
12765 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012766}
12767
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012768static int
12769xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12770 int *fixed,
12771 const xmlChar **value,
12772 xmlSchemaValPtr *val)
12773{
12774 *fixed = 0;
12775 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012776 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012777 *val = NULL;
12778
12779 if (item->defValue == NULL)
12780 item = item->refDecl;
12781
12782 if (item == NULL)
12783 return (0);
12784
12785 if (item->defValue != NULL) {
12786 *value = item->defValue;
12787 if (val != 0)
12788 *val = item->defVal;
12789 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12790 *fixed = 1;
12791 return (1);
12792 }
12793 return (0);
12794}
Daniel Veillard3646d642004-06-02 19:19:14 +000012795/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012796 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000012797 * @wild: the wildcard
12798 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012799 *
12800 * Validation Rule: Wildcard allows Namespace Name
12801 * (cvc-wildcard-namespace)
12802 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012803 *
12804 * Returns 1 if the given namespace matches the wildcard,
12805 * 0 otherwise.
12806 */
12807static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012808xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
12809 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000012810{
12811 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012812 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012813
12814 if (wild->any)
12815 return(1);
12816 else if (wild->nsSet != NULL) {
12817 xmlSchemaWildcardNsPtr cur;
12818
12819 cur = wild->nsSet;
12820 while (cur != NULL) {
12821 if (xmlStrEqual(cur->value, ns))
12822 return(1);
12823 cur = cur->next;
12824 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012825 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012826 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012827 return(1);
12828
Daniel Veillard3646d642004-06-02 19:19:14 +000012829 return(0);
12830}
12831
12832/**
12833 * xmlSchemaBuildAttributeValidation:
12834 * @ctxt: the schema parser context
12835 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012836 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012837 *
12838 * Builds the wildcard and the attribute uses on the given complex type.
12839 * Returns -1 if an internal error occurs, 0 otherwise.
12840 */
12841static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012842xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
12843 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000012844{
12845 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012846 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
12847 prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012848 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012849 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012850 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012851 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012852
Daniel Veillard01fa6152004-06-29 17:04:39 +000012853 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012854 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012855 * Complex Type Definition with complex content Schema Component.
12856 *
12857 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012858 * TODO: Add checks for absent referenced attribute declarations and
12859 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012860 */
12861 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012862 PERROR_INT("xmlSchemaBuildAttributeValidation",
12863 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000012864 return (-1);
12865 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012866 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012867 PERROR_INT("xmlSchemaBuildAttributeValidation",
12868 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012869 return (-1);
12870 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012871 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012872 /*
12873 * Inherit the attribute uses of the base type.
12874 */
12875 /*
12876 * NOTE: It is allowed to "extend" the anyType complex type.
12877 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012878 if (! IS_ANYTYPE(baseType)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012879 if (baseType != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012880 for (cur = baseType->attributeUses; cur != NULL;
12881 cur = cur->next) {
12882 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012883 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12884 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012885 xmlSchemaPErrMemory(pctxt,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012886 "building attribute uses of complexType", NULL);
12887 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012888 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012889 tmp->attr = cur->attr;
12890 tmp->next = NULL;
12891 if (type->attributeUses == NULL) {
12892 type->attributeUses = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012893 } else
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012894 lastBaseUse->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012895 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012896 }
12897 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012898 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012899 attrs = type->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012900 /*
12901 * Handle attribute wildcards.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012902 */
12903 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
12904 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012905 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012906 * NOTE: During the parse time, the wildcard is created on the complexType
12907 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012908 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012909 if (err == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012910 PERROR_INT("xmlSchemaBuildAttributeValidation",
12911 "failed to build an intersected attribute wildcard");
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012912 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012913 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012914
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012915 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12916 ((IS_ANYTYPE(baseType)) ||
12917 ((baseType != NULL) &&
12918 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12919 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012920 if (type->attributeWildcard != NULL) {
12921 /*
12922 * Union the complete wildcard with the base wildcard.
12923 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012924 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012925 baseType->attributeWildcard) == -1)
12926 return (-1);
12927 } else {
12928 /*
12929 * Just inherit the wildcard.
12930 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012931 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012932 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012933 * wildcard is shared.
12934 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012935 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012936 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012937 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012938
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012939 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12940 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012941 /*
12942 * Derivation Valid (Restriction, Complex)
12943 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012944 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012945 if (baseType->attributeWildcard == NULL) {
12946 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012947 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012948 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012949 "The type has an attribute wildcard, "
12950 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012951 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012952 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012953 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012954 } else if (xmlSchemaCheckCOSNSSubset(
12955 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012956 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012957 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012958 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012959 NULL, type, NULL,
12960 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012961 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012962 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12963 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012964 return (1);
12965 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012966 /* 4.3 Unless the {base type definition} is the ·ur-type
12967 * definition·, the complex type definition's {attribute
12968 * wildcard}'s {process contents} must be identical to or
12969 * stronger than the {base type definition}'s {attribute
12970 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012971 * than lax is stronger than skip.
12972 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012973 if ((! IS_ANYTYPE(baseType)) &&
12974 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012975 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012976 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012977 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012978 NULL, type, NULL,
12979 "The 'process contents' of the attribute wildcard is "
12980 "weaker than the one in the base type %s",
12981 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012982 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012983 return (1);
12984 }
12985 }
12986 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12987 /*
12988 * Derivation Valid (Extension)
12989 * At this point the type and the base have both, either
12990 * no wildcard or a wildcard.
12991 */
12992 if ((baseType->attributeWildcard != NULL) &&
12993 (baseType->attributeWildcard != type->attributeWildcard)) {
12994 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012995 if (xmlSchemaCheckCOSNSSubset(
12996 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012997 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012998 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012999 NULL, type, NULL,
13000 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013001 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013002 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
13003 FREE_AND_NULL(str)
13004 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013005 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013006 }
13007 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013008
Daniel Veillard3646d642004-06-02 19:19:14 +000013009 /*
13010 * Gather attribute uses defined by this type.
13011 */
13012 if (attrs != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013013 if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
Daniel Veillard3646d642004-06-02 19:19:14 +000013014 &uses, &lastUse) == -1) {
13015 return (-1);
13016 }
13017 }
13018 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013019 * "Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000013020 * not have identical {name}s and {target namespace}s."
13021 *
13022 * For "extension" this is done further down.
13023 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013024 if ((uses != NULL) && ((type->flags &
13025 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013026 cur = uses;
13027 while (cur != NULL) {
13028 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013029 while (tmp != NULL) {
13030 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000013031 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013032 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000013033 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
13034
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013035 xmlSchemaPAttrUseErr(pctxt,
13036 XML_SCHEMAP_CT_PROPS_CORRECT_4,
13037 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013038 "Duplicate attribute use %s specified",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013039 xmlSchemaFormatQName(&str,
13040 xmlSchemaGetAttrTargetNsURI(tmp->attr),
13041 xmlSchemaGetAttrName(tmp->attr)));
13042 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000013043 break;
13044 }
13045 tmp = tmp->next;
13046 }
13047 cur = cur->next;
13048 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013049 }
13050 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013051 /*
13052 * Derive by restriction.
13053 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013054 if (IS_ANYTYPE(baseType)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013055 type->attributeUses = uses;
13056 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013057 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013058 const xmlChar *bEffValue;
13059 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000013060
13061 cur = uses;
13062 while (cur != NULL) {
13063 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013064 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000013065 base = type->attributeUses;
13066 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013067 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000013068 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013069 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000013070 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013071
13072 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000013073
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013074 if ((cur->attr->occurs ==
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000013075 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
13076 (base->attr->occurs ==
13077 XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
13078 /*
13079 * NOOP.
13080 */
13081 } else if ((cur->attr->occurs ==
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013082 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
13083 (base->attr->occurs ==
13084 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013085 /*
13086 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000013087 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013088 xmlSchemaPAttrUseErr(pctxt,
13089 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
13090 type, cur->attr,
13091 "The 'optional' use is inconsistent with a "
13092 "matching 'required' use of the base type",
13093 NULL);
13094 } else if ((cur->attr->occurs ==
13095 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
13096 (base->attr->occurs ==
13097 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
13098 /*
13099 * derivation-ok-restriction 3
13100 */
13101 xmlSchemaPCustomErr(pctxt,
13102 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
13103 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013104 "A matching attribute use for the 'required' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013105 "attribute use '%s' of the base type is "
13106 "missing",
13107 xmlSchemaFormatQName(&str,
13108 xmlSchemaGetAttrTargetNsURI(base->attr),
13109 xmlSchemaGetAttrName(base->attr)));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013110 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013111 } else if (xmlSchemaCheckCOSSTDerivedOK(
13112 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
13113
13114 /*
13115 * SPEC (2.1.2) "R's {attribute declaration}'s
13116 * {type definition} must be validly derived from
13117 * B's {type definition} given the empty set as
13118 * defined in Type Derivation OK (Simple) (§3.14.6)."
13119 */
13120 xmlSchemaPAttrUseErr(pctxt,
13121 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
13122 type, cur->attr,
13123 "The attribute declaration's type "
13124 "definition is not validly derived from "
13125 "the corresponding definition in the "
13126 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000013127 } else {
13128 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013129 * 2.1.3 [Definition:] Let the effective value
13130 * constraint of an attribute use be its {value
13131 * constraint}, if present, otherwise its {attribute
13132 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013133 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013134 xmlSchemaGetEffectiveValueConstraint(base->attr,
Daniel Veillard24505b02005-07-28 23:49:35 +000013135 &effFixed, &bEffValue, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013136 /*
13137 * 2.1.3 ... one of the following must be true
13138 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013139 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013140 * ·absent· or default.
13141 */
13142 if ((bEffValue != NULL) &&
13143 (effFixed == 1)) {
13144 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013145
13146 xmlSchemaGetEffectiveValueConstraint(base->attr,
Daniel Veillard24505b02005-07-28 23:49:35 +000013147 &effFixed, &rEffValue, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013148 /*
13149 * 2.1.3.2 R's ·effective value constraint· is
13150 * fixed with the same string as B's.
13151 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013152 */
13153 if ((effFixed == 0) ||
13154 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013155 xmlSchemaPAttrUseErr(pctxt,
13156 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
13157 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013158 "The effective value constraint of the "
13159 "attribute use is inconsistent with "
13160 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013161 NULL);
13162 } else {
13163 /*
13164 * Override the attribute use.
13165 */
13166 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013167 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013168 } else
13169 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000013170 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013171
Daniel Veillard3646d642004-06-02 19:19:14 +000013172 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013173 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013174 base = base->next;
13175 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013176
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013177 if ((!found) && (cur->attr->occurs !=
13178 XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
13179 /*
13180 * derivation-ok-restriction 2.2
13181 */
13182 if ((baseType->attributeWildcard == NULL) ||
13183 (xmlSchemaCheckCVCWildcardNamespace(
13184 baseType->attributeWildcard,
13185 cur->attr->targetNamespace) != 1)) {
13186 xmlSchemaPAttrUseErr(pctxt,
13187 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
13188 type, cur->attr,
13189 "Neither a matching attribute use, "
13190 "nor a matching wildcard in the base type does exist",
13191 NULL);
13192 } else {
13193 /*
13194 * Add the attribute use.
13195 *
13196 * Note that this may lead to funny derivation error reports, if
13197 * multiple equal attribute uses exist; but this is not
13198 * allowed anyway, and it will be reported beforehand.
13199 */
13200 tmp = cur;
13201 if (prev != NULL)
13202 prev->next = cur->next;
13203 else
13204 uses = cur->next;
13205 cur = cur->next;
13206 tmp->next = NULL;
13207 if (type->attributeUses == NULL) {
13208 type->attributeUses = tmp;
13209 } else
13210 lastBaseUse->next = tmp;
13211 lastBaseUse = tmp;
13212
13213 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000013214 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013215 }
13216 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000013217 cur = cur->next;
13218 }
13219 if (uses != NULL)
13220 xmlSchemaFreeAttributeUseList(uses);
13221 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013222 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013223 /*
13224 * The spec allows only appending, and not other kinds of extensions.
13225 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013226 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000013227 */
13228 if (uses != NULL) {
13229 if (type->attributeUses == NULL) {
13230 type->attributeUses = uses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013231 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000013232 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000013233 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013234 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013235 PERROR_INT("xmlSchemaBuildAttributeValidation",
13236 "no derivation method");
13237 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013238 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013239 /*
13240 * 3.4.6 -> Complex Type Definition Properties Correct
13241 */
13242 if (type->attributeUses != NULL) {
13243 cur = type->attributeUses;
13244 prev = NULL;
13245 while (cur != NULL) {
13246 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013247 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000013248 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000013249 *
Daniel Veillard3646d642004-06-02 19:19:14 +000013250 * Note that this was already done for "restriction" and types derived from
13251 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000013252 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013253 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
13254 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013255 while (tmp != NULL) {
13256 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000013257 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013258 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000013259 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013260
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013261 xmlSchemaPAttrUseErr(pctxt,
13262 XML_SCHEMAP_CT_PROPS_CORRECT_4,
13263 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013264 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013265 break;
13266 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013267 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000013268 }
13269 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013270 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013271 * 5. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000013272 * not have {type definition}s which are or are derived from ID.
13273 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013274 if ((cur->attr->subtypes != NULL) &&
13275 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
13276 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013277 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013278 xmlSchemaPAttrUseErr(pctxt,
13279 XML_SCHEMAP_CT_PROPS_CORRECT_5,
13280 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013281 "There must not exist more than one attribute use, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013282 "declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000013283 NULL);
13284 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013285 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013286 id = cur;
13287 }
13288 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013289 * Remove "prohibited" attribute uses. The reason this is done at this late
Daniel Veillard3646d642004-06-02 19:19:14 +000013290 * stage is to be able to catch dublicate attribute uses. So we had to keep
13291 * prohibited uses in the list as well.
13292 */
13293 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
13294 tmp = cur;
13295 if (prev == NULL)
13296 type->attributeUses = cur->next;
13297 else
13298 prev->next = cur->next;
13299 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000013300 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000013301 } else {
13302 prev = cur;
13303 cur = cur->next;
13304 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013305 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013306 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013307 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013308 * TODO: This check should be removed if we are 100% sure of
13309 * the base type attribute uses already being built.
13310 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013311 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013312 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013313 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013314 PERROR_INT("xmlSchemaBuildAttributeValidation",
13315 "attribute uses not builded on base type");
13316 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013317 return (0);
13318}
13319
13320/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013321 * xmlSchemaTypeFinalContains:
13322 * @schema: the schema
13323 * @type: the type definition
13324 * @final: the final
13325 *
13326 * Evaluates if a type definition contains the given "final".
13327 * This does take "finalDefault" into account as well.
13328 *
13329 * Returns 1 if the type does containt the given "final",
13330 * 0 otherwise.
13331 */
13332static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013333xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013334{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013335 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013336 return (0);
13337 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013338 return (1);
13339 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013340 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013341}
13342
13343/**
13344 * xmlSchemaGetUnionSimpleTypeMemberTypes:
13345 * @type: the Union Simple Type
13346 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013347 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013348 * returns NULL otherwise.
13349 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013350static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000013351xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
13352{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013353 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013354 if (type->memberTypes != NULL)
13355 return (type->memberTypes);
13356 else
13357 type = type->baseType;
13358 }
13359 return (NULL);
13360}
13361
13362/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013363 * xmlSchemaGetParticleTotalRangeMin:
13364 * @particle: the particle
13365 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013366 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013367 * (all and sequence) + (choice)
13368 *
13369 * Returns the minimun Effective Total Range.
13370 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013371static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013372xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013373{
13374 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013375 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013376 return (0);
13377 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013378 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013379 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013380 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013381
13382 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013383 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013384 while (part != NULL) {
13385 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13386 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013387 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013388 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013389 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013390 if (cur == 0)
13391 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013392 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013393 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013394 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013395 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013396 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013397 } else {
13398 /* <all> and <sequence> */
13399 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013400 xmlSchemaParticlePtr part =
13401 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013402
13403 if (part == NULL)
13404 return (0);
13405 do {
13406 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13407 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013408 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013409 else
13410 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013411 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013412 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013413 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013414 }
13415}
13416
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013417/**
13418 * xmlSchemaGetParticleTotalRangeMax:
13419 * @particle: the particle
13420 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013421 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013422 * (all and sequence) + (choice)
13423 *
13424 * Returns the maximum Effective Total Range.
13425 */
13426static int
13427xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13428{
13429 if ((particle->children == NULL) ||
13430 (particle->children->children == NULL))
13431 return (0);
13432 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13433 int max = -1, cur;
13434 xmlSchemaParticlePtr part =
13435 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013436
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013437 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13438 if (part->children == NULL)
13439 continue;
13440 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13441 (part->children->type == XML_SCHEMA_TYPE_ANY))
13442 cur = part->maxOccurs;
13443 else
13444 cur = xmlSchemaGetParticleTotalRangeMax(part);
13445 if (cur == UNBOUNDED)
13446 return (UNBOUNDED);
13447 if ((max < cur) || (max == -1))
13448 max = cur;
13449 }
13450 /* TODO: Handle overflows? */
13451 return (particle->maxOccurs * max);
13452 } else {
13453 /* <all> and <sequence> */
13454 int sum = 0, cur;
13455 xmlSchemaParticlePtr part =
13456 (xmlSchemaParticlePtr) particle->children->children;
13457
13458 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13459 if (part->children == NULL)
13460 continue;
13461 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13462 (part->children->type == XML_SCHEMA_TYPE_ANY))
13463 cur = part->maxOccurs;
13464 else
13465 cur = xmlSchemaGetParticleTotalRangeMax(part);
13466 if (cur == UNBOUNDED)
13467 return (UNBOUNDED);
13468 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13469 return (UNBOUNDED);
13470 sum += cur;
13471 }
13472 /* TODO: Handle overflows? */
13473 return (particle->maxOccurs * sum);
13474 }
13475}
13476
13477/**
13478 * xmlSchemaIsParticleEmptiable:
13479 * @particle: the particle
13480 *
13481 * Schema Component Constraint: Particle Emptiable
13482 * Checks whether the given particle is emptiable.
13483 *
13484 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013485 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013486static int
13487xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13488{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013489 /*
13490 * SPEC (1) "Its {min occurs} is 0."
13491 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013492 if ((particle == NULL) || (particle->minOccurs == 0) ||
13493 (particle->children == NULL))
13494 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013495 /*
13496 * SPEC (2) "Its {term} is a group and the minimum part of the
13497 * effective total range of that group, [...] is 0."
13498 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013499 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013500 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013501 return (1);
13502 }
13503 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013504}
13505
13506/**
13507 * xmlSchemaCheckCOSSTDerivedOK:
13508 * @type: the derived simple type definition
13509 * @baseType: the base type definition
13510 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013511 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013512 * Type Derivation OK (Simple) (cos-st-derived-OK)
13513 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013514 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013515 * derived from @baseType.
13516 *
13517 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013518 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013519static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013520xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13521 xmlSchemaTypePtr baseType,
13522 int subset)
13523{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013524 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013525 * 1 They are the same type definition.
13526 * TODO: The identy check might have to be more complex than this.
13527 */
13528 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013529 return (0);
13530 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013531 * 2.1 restriction is not in the subset, or in the {final}
13532 * of its own {base type definition};
13533 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013534 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013535 (xmlSchemaTypeFinalContains(type->baseType,
13536 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13537 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013538 }
13539 /* 2.2 */
13540 if (type->baseType == baseType) {
13541 /*
13542 * 2.2.1 D's ·base type definition· is B.
13543 */
13544 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013545 }
13546 /*
13547 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13548 * and is validly derived from B given the subset, as defined by this
13549 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013550 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013551 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013552 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013553 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013554 return (0);
13555 }
13556 /*
13557 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000013558 * definition·.
13559 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013560 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013561 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013562 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013563 }
13564 /*
13565 * 2.2.4 B's {variety} is union and D is validly derived from a type
13566 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000013567 * defined by this constraint.
13568 *
13569 * NOTE: This seems not to involve built-in types, since there is no
13570 * built-in Union Simple Type.
13571 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013572 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013573 xmlSchemaTypeLinkPtr cur;
13574
13575 cur = baseType->memberTypes;
13576 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013577 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013578 return (0);
13579 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013580 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013581 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013582
Daniel Veillard01fa6152004-06-29 17:04:39 +000013583 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13584}
13585
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013586/**
13587 * xmlSchemaCheckTypeDefCircularInternal:
13588 * @pctxt: the schema parser context
13589 * @ctxtType: the type definition
13590 * @ancestor: an ancestor of @ctxtType
13591 *
13592 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013593 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013594 *
13595 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13596 * circular, 0 otherwise.
13597 */
13598static int
13599xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13600 xmlSchemaTypePtr ctxtType,
13601 xmlSchemaTypePtr ancestor)
13602{
13603 int ret;
13604
13605 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13606 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013607
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013608 if (ctxtType == ancestor) {
13609 xmlSchemaPCustomErr(pctxt,
13610 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13611 NULL, ctxtType, GET_NODE(ctxtType),
13612 "The definition is circular", NULL);
13613 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13614 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013615 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13616 /*
13617 * Avoid inifinite recursion on circular types not yet checked.
13618 */
13619 return (0);
13620 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013621 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13622 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13623 ancestor->baseType);
13624 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13625 return (ret);
13626}
13627
13628/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013629 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013630 * @item: the complex/simple type definition
13631 * @ctxt: the parser context
13632 * @name: the name
13633 *
13634 * Checks for circular type definitions.
13635 */
13636static void
13637xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013638 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013639 const xmlChar * name ATTRIBUTE_UNUSED)
13640{
13641 if ((item == NULL) ||
13642 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13643 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13644 return;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000013645 if (item->redef != NULL) {
13646 xmlSchemaTypePtr cur = item;
13647 do {
13648 xmlSchemaCheckTypeDefCircularInternal(ctxt, cur, cur->baseType);
13649 cur = cur->redef;
13650 } while (cur != NULL);
13651 } else
13652 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013653
13654}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013655
13656/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013657 * xmlSchemaResolveTypeDefs:
13658 * @item: the complex/simple type definition
13659 * @ctxt: the parser context
13660 * @name: the name
13661 *
13662 * Checks for circular type definitions.
13663 */
13664static void
13665xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013666 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013667 const xmlChar * name ATTRIBUTE_UNUSED)
13668{
13669 if (typeDef == NULL)
13670 return;
13671
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013672 /*
13673 * Resolve the base type.
13674 */
13675 if (typeDef->baseType == NULL) {
13676 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13677 typeDef->base, typeDef->baseNs);
13678 if (typeDef->baseType == NULL) {
13679 xmlSchemaPResCompAttrErr(ctxt,
13680 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013681 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013682 "base", typeDef->base, typeDef->baseNs,
13683 XML_SCHEMA_TYPE_SIMPLE, NULL);
13684 return;
13685 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013686 }
13687 if (IS_SIMPLE_TYPE(typeDef)) {
13688 if (VARIETY_UNION(typeDef)) {
13689 /*
13690 * Resolve the memberTypes.
13691 */
13692 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13693 return;
13694 } else if (VARIETY_LIST(typeDef)) {
13695 /*
13696 * Resolve the itemType.
13697 */
13698 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13699 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13700 typeDef->ref, typeDef->refNs);
13701 if ((typeDef->subtypes == NULL) ||
13702 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13703 typeDef->subtypes = NULL;
13704 xmlSchemaPResCompAttrErr(ctxt,
13705 XML_SCHEMAP_SRC_RESOLVE,
13706 typeDef, typeDef->node,
13707 "itemType", typeDef->ref, typeDef->refNs,
13708 XML_SCHEMA_TYPE_SIMPLE, NULL);
13709 }
13710 }
13711 return;
13712 }
13713 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013714}
13715
13716
13717
13718/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013719 * xmlSchemaCheckSTPropsCorrect:
13720 * @ctxt: the schema parser context
13721 * @type: the simple type definition
13722 *
13723 * Checks st-props-correct.
13724 *
13725 * Returns 0 if the properties are correct,
13726 * if not, a positive error code and -1 on internal
13727 * errors.
13728 */
13729static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013730xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013731 xmlSchemaTypePtr type)
13732{
13733 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13734 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013735 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013736
Daniel Veillardc0826a72004-08-10 14:17:33 +000013737 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013738 /*
13739 * Schema Component Constraint: Simple Type Definition Properties Correct
13740 *
13741 * NOTE: This is somehow redundant, since we actually built a simple type
13742 * to have all the needed information; this acts as an self test.
13743 */
13744 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13745 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013746 /* Base type: If the datatype has been ·derived· by ·restriction·
13747 * then the Simple Type Definition component from which it is ·derived·,
13748 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013749 */
13750 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013751 /*
13752 * TODO: Think about: "modulo the impact of Missing
13753 * Sub-components (§5.3)."
13754 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013755 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013756 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013757 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013758 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013759 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013760
Daniel Veillard01fa6152004-06-29 17:04:39 +000013761 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013762 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013763 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013764 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013765 NULL, type, NULL,
13766 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013767 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013768 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013769 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13770 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013771 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
13772 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13773 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013774 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013775 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013776 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013777 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013778 "the simple ur-type definition as base type, not '%s'",
13779 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013780 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013781 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13782 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013783 /*
13784 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013785 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013786 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
13787 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013788 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013789 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013790 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013791 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013792 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13793 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013794 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013795
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013796 /*
13797 * 3 The {final} of the {base type definition} must not contain restriction.
13798 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013799 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013800 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13801 xmlSchemaPCustomErr(ctxt,
13802 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013803 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013804 "The 'final' of its base type '%s' must not contain "
13805 "'restriction'",
13806 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013807 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013808 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013809 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013810
13811 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013812 * 2 All simple type definitions must be derived ultimately from the ·simple
13813 * ur-type definition (so· circular definitions are disallowed). That is, it
13814 * must be possible to reach a built-in primitive datatype or the ·simple
13815 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013816 *
13817 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013818 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013819 return (0);
13820}
13821
13822/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013823 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013824 * @ctxt: the schema parser context
13825 * @type: the simple type definition
13826 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013827 * Schema Component Constraint:
13828 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13829
13830 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013831 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013832 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013833 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013834 * a positive error code otherwise.
13835 */
13836static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013837xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013838 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013839{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013840 xmlChar *str = NULL;
13841
Daniel Veillard01fa6152004-06-29 17:04:39 +000013842 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013843 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13844 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013845 return (-1);
13846 }
13847
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013848 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013849 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013850 /*
13851 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000013852 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013853 */
13854 if (! VARIETY_ATOMIC(type->baseType)) {
13855 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013856 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013857 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013858 "The base type '%s' is not an atomic simple type",
13859 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013860 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013861 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13862 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013863 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000013864 * restriction.
13865 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013866 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013867 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013868 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013869 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013870 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013871 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013872 "The final of its base type '%s' must not contain 'restriction'",
13873 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013874 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013875 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13876 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013877
13878 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013879 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013880 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013881 * Primitive datatypes.
13882 */
13883 if (type->facets != NULL) {
13884 xmlSchemaFacetPtr facet;
13885 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013886
Daniel Veillard01fa6152004-06-29 17:04:39 +000013887 primitive = xmlSchemaGetPrimitiveType(type);
13888 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013889 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13890 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013891 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013892 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013893 facet = type->facets;
13894 do {
13895 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013896 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013897 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013898 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013899 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013900 }
13901 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013902 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013903 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013904 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013905 }
13906 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013907 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13908 * of the {base type definition} (call this BF),then the DF's {value}
13909 * must be a valid restriction of BF's {value} as defined in
13910 * [XML Schemas: Datatypes]."
13911 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013912 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013913 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013914 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013915 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013916 xmlSchemaTypePtr itemType = NULL;
13917
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013918 itemType = type->subtypes;
13919 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013920 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13921 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013922 return (-1);
13923 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013924 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013925 xmlSchemaTypeFixup(itemType, pctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013926 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013927 * 2.1 The {item type definition} must have a {variety} of atomic or
13928 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013929 * must be atomic).
13930 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013931 if ((! VARIETY_ATOMIC(itemType)) &&
13932 (! VARIETY_UNION(itemType))) {
13933 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013934 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013935 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013936 "The item type '%s' does not have a variety of atomic or union",
13937 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013938 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013939 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013940 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013941 xmlSchemaTypeLinkPtr member;
13942
13943 member = itemType->memberTypes;
13944 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013945 if (! VARIETY_ATOMIC(member->type)) {
13946 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013947 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013948 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013949 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013950 "member type '%s' of this item type is not atomic",
13951 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013952 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013953 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13954 }
13955 member = member->next;
13956 }
13957 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013958
13959 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013960 xmlSchemaFacetPtr facet;
13961 /*
13962 * This is the case if we have: <simpleType><list ..
13963 */
13964 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013965 * 2.3.1
13966 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000013967 * contain list.
13968 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013969 if (xmlSchemaTypeFinalContains(itemType,
13970 XML_SCHEMAS_TYPE_FINAL_LIST)) {
13971 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013972 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013973 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013974 "The final of its item type '%s' must not contain 'list'",
13975 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013976 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013977 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13978 }
13979 /*
13980 * 2.3.1.2 The {facets} must only contain the whiteSpace
13981 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013982 * OPTIMIZE TODO: the S4S already disallows any facet
13983 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013984 */
13985 if (type->facets != NULL) {
13986 facet = type->facets;
13987 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013988 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013989 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013990 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013991 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013992 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13993 }
13994 facet = facet->next;
13995 } while (facet != NULL);
13996 }
13997 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013998 * MAYBE TODO: (Hmm, not really) Datatypes states:
13999 * A ·list· datatype can be ·derived· from an ·atomic· datatype
14000 * whose ·lexical space· allows space (such as string or anyURI)or
14001 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000014002 * ·lexical space· allows space.
14003 */
14004 } else {
14005 /*
14006 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014007 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014008 */
14009 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014010 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000014011 * 2.3.2.1 The {base type definition} must have a {variety} of list.
14012 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014013 if (! VARIETY_LIST(type->baseType)) {
14014 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014015 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014016 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014017 "The base type '%s' must be a list type",
14018 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014019 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014020 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
14021 }
14022 /*
14023 * 2.3.2.2 The {final} of the {base type definition} must not
14024 * contain restriction.
14025 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014026 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014027 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014028 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014029 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014030 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014031 "The 'final' of the base type '%s' must not contain 'restriction'",
14032 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014033 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014034 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
14035 }
14036 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014037 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000014038 * from the {base type definition}'s {item type definition} given
14039 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
14040 */
14041 {
14042 xmlSchemaTypePtr baseItemType;
14043
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014044 baseItemType = type->baseType->subtypes;
14045 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014046 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
14047 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014048 return (-1);
14049 }
14050 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014051 (xmlSchemaCheckCOSSTDerivedOK(itemType,
14052 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014053 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014054 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014055 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014056 NULL, type, NULL,
14057 "The item type '%s' is not validly derived from "
14058 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014059 xmlSchemaGetComponentQName(&str, itemType),
14060 xmlSchemaGetComponentQName(&strBIT, baseItemType),
14061 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014062
14063 FREE_AND_NULL(str)
14064 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014065 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014066 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
14067 }
14068 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014069
Daniel Veillard01fa6152004-06-29 17:04:39 +000014070 if (type->facets != NULL) {
14071 xmlSchemaFacetPtr facet;
14072 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014073 /*
14074 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000014075 * and enumeration facet components are allowed among the {facets}.
14076 */
14077 facet = type->facets;
14078 do {
14079 switch (facet->type) {
14080 case XML_SCHEMA_FACET_LENGTH:
14081 case XML_SCHEMA_FACET_MINLENGTH:
14082 case XML_SCHEMA_FACET_MAXLENGTH:
14083 case XML_SCHEMA_FACET_WHITESPACE:
14084 /*
14085 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014086 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014087 */
14088 case XML_SCHEMA_FACET_PATTERN:
14089 case XML_SCHEMA_FACET_ENUMERATION:
14090 break;
14091 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014092 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014093 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014094 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014095 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014096 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000014097 * invalid facets.
14098 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014099 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014100 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014101 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014102 facet = facet->next;
14103 } while (facet != NULL);
14104 if (ok == 0)
14105 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
14106 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014107 * SPEC (2.3.2.5) (same as 1.3.2)
14108 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014109 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014110 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000014111 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014112 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014113 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014114 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014115 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014116 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000014117 * atomic or list.
14118 */
14119 xmlSchemaTypeLinkPtr member;
14120
14121 member = type->memberTypes;
14122 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014123 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014124 xmlSchemaTypeFixup(member->type, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014125
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014126 if ((! VARIETY_ATOMIC(member->type)) &&
14127 (! VARIETY_LIST(member->type))) {
14128 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014129 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014130 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014131 "The member type '%s' is neither an atomic, nor a list type",
14132 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014133 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014134 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
14135 }
14136 member = member->next;
14137 }
14138 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014139 * 3.3.1 If the {base type definition} is the ·simple ur-type
14140 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000014141 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014142 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014143 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014144 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000014145 * {final} which does not contain union.
14146 */
14147 member = type->memberTypes;
14148 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014149 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014150 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014151 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014152 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014153 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014154 "The 'final' of member type '%s' contains 'union'",
14155 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014156 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014157 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
14158 }
14159 member = member->next;
14160 }
14161 /*
14162 * 3.3.1.2 The {facets} must be empty.
14163 */
14164 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014165 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014166 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014167 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014168 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014169 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
14170 }
14171 } else {
14172 /*
14173 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014174 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014175 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014176 if (! VARIETY_UNION(type->baseType)) {
14177 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014178 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014179 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014180 "The base type '%s' is not a union type",
14181 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014182 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014183 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
14184 }
14185 /*
14186 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
14187 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014188 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014189 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014190 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014191 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014192 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014193 "The 'final' of its base type '%s' must not contain 'restriction'",
14194 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014195 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014196 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
14197 }
14198 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014199 * 3.3.2.3 The {member type definitions}, in order, must be validly
14200 * derived from the corresponding type definitions in the {base
14201 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014202 * as defined in Type Derivation OK (Simple) (§3.14.6).
14203 */
14204 {
14205 xmlSchemaTypeLinkPtr baseMember;
14206
14207 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014208 * OPTIMIZE: if the type is restricting, it has no local defined
14209 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014210 * thus a check for equality can be skipped.
14211 */
14212 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014213 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014214 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000014215 * types of it's base type. This check seems not necessary with
14216 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014217 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014218 */
14219 if (type->memberTypes != NULL) {
14220 member = type->memberTypes;
14221 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014222 if ((member == NULL) && (baseMember != NULL)) {
14223 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
14224 "different number of member types in base");
14225 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014226 while (member != NULL) {
14227 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014228 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
14229 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014230 }
14231 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014232 (xmlSchemaCheckCOSSTDerivedOK(
14233 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014234 xmlChar *strBMT = NULL, *strBT = NULL;
14235
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014236 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014237 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
14238 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014239 "The member type %s is not validly "
14240 "derived from its corresponding member "
14241 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014242 xmlSchemaGetComponentQName(&str, member->type),
14243 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
14244 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014245 FREE_AND_NULL(str)
14246 FREE_AND_NULL(strBMT)
14247 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014248 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014249 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014250 member = member->next;
14251 baseMember = baseMember->next;
14252 }
14253 }
14254 }
14255 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014256 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000014257 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014258 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014259 if (type->facets != NULL) {
14260 xmlSchemaFacetPtr facet;
14261 int ok = 1;
14262
14263 facet = type->facets;
14264 do {
14265 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
14266 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014267 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014268 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014269 NULL, type, facet);
14270 ok = 0;
14271 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014272 facet = facet->next;
14273 } while (facet != NULL);
14274 if (ok == 0)
14275 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014276
Daniel Veillard01fa6152004-06-29 17:04:39 +000014277 }
14278 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014279 * SPEC (3.3.2.5) (same as 1.3.2)
14280 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014281 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014282 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000014283 */
14284 }
14285 }
14286
14287 return (0);
14288}
14289
14290/**
14291 * xmlSchemaCheckSRCSimpleType:
14292 * @ctxt: the schema parser context
14293 * @type: the simple type definition
14294 *
14295 * Checks crc-simple-type constraints.
14296 *
14297 * Returns 0 if the constraints are satisfied,
14298 * if not a positive error code and -1 on internal
14299 * errors.
14300 */
14301static int
14302xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
14303 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014304{
14305 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014306 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014307 * must satisfy the conditions set out in Constraints on Simple Type
14308 * Definition Schema Components (§3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000014309 */
14310 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
14311 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
14312 /*
14313 * TODO: Removed this, since it got annoying to get an
14314 * extra error report, if anything failed until now.
14315 * Enable this if needed.
14316 */
14317 /*
14318 xmlSchemaPErr(ctxt, type->node,
14319 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014320 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000014321 "on simple type definitions.\n",
14322 type->name, NULL);
14323 */
14324 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
14325 }
14326
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014327 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014328 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014329 * src-simple-type.2 If the <restriction> alternative is chosen,
14330 * either it must have a base [attribute] or a <simpleType> among its
Daniel Veillard01fa6152004-06-29 17:04:39 +000014331 * [children], but not both.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014332 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014333 /*
14334 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014335 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014336 */
14337 } else if (VARIETY_LIST(type)) {
14338 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
14339 * an itemType [attribute] or a <simpleType> among its [children],
Daniel Veillard01fa6152004-06-29 17:04:39 +000014340 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014341 *
14342 * REMOVED: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014343 */
14344 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014345 xmlSchemaTypeLinkPtr member;
14346 xmlSchemaTypePtr ancestor, anySimpleType;
14347
14348 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14349
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014350 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
14351 * the <union> alternative is chosen, there must not be any entries
14352 * in the memberTypes [attribute] at any depth which resolve to the
Daniel Veillard01fa6152004-06-29 17:04:39 +000014353 * component corresponding to the <simpleType>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014354 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014355 member = type->memberTypes;
14356 while (member != NULL) {
14357 ancestor = member->type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014358 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014359 if (ancestor == type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014360 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014361 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014362 NULL, type, NULL,
14363 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014364 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014365 }
14366 if (IS_NOT_TYPEFIXED(ancestor))
14367 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014368 if (VARIETY_LIST(ancestor)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014369 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014370 * TODO, FIXME: Although a list simple type must not have a union ST
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014371 * type as item type, which in turn has a list ST as member
14372 * type, we will assume this here as well, since this check
Daniel Veillard01fa6152004-06-29 17:04:39 +000014373 * was not yet performed.
14374 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014375 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014376
Daniel Veillard01fa6152004-06-29 17:04:39 +000014377 ancestor = ancestor->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014378 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014379 member = member->next;
14380 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014381 }
14382
14383 return (0);
14384}
14385
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014386static int
14387xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
14388{
14389 if (ctxt->vctxt == NULL) {
14390 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
14391 if (ctxt->vctxt == NULL) {
14392 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014393 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014394 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014395 "failed to create a temp. validation context.\n",
14396 NULL, NULL);
14397 return (-1);
14398 }
14399 /* TODO: Pass user data. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014400 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014401 }
14402 return (0);
14403}
14404
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014405static int
14406xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
14407 xmlNodePtr node,
14408 xmlSchemaTypePtr type,
14409 const xmlChar *value,
14410 xmlSchemaValPtr *retVal,
14411 int fireErrors,
14412 int normalize,
14413 int isNormalized);
14414
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014415/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014416 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014417 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014418 * @type: the simple type definition
14419 * @value: the default value
14420 * @node: an optional node (the holder of the value)
14421 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014422 * Schema Component Constraint: Element Default Valid (Immediate)
14423 * (cos-valid-default)
14424 * This will be used by the parser only. For the validator there's
14425 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014426 *
14427 * Returns 0 if the constraints are satisfied,
14428 * if not, a positive error code and -1 on internal
14429 * errors.
14430 */
14431static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014432xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14433 xmlNodePtr node,
14434 xmlSchemaTypePtr type,
14435 const xmlChar *value,
14436 xmlSchemaValPtr *val)
14437{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014438 int ret = 0;
14439
14440 /*
14441 * cos-valid-default:
14442 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014443 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014444 * definition the appropriate case among the following must be true:
14445 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014446 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014447 /*
14448 * Complex type.
14449 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014450 * SPEC (2.1) "its {content type} must be a simple type definition
14451 * or mixed."
14452 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014453 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014454 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014455 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014456 if ((! HAS_SIMPLE_CONTENT(type)) &&
14457 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14458 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014459 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014460 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014461 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014462 "For a string to be a valid default, the type definition "
14463 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014464 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014465 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14466 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014467 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014468 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014469 * 1 If the type definition is a simple type definition, then the string
14470 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014471 * Valid (§3.14.4).
14472 *
14473 * AND
14474 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014475 * 2.2.1 If the {content type} is a simple type definition, then the
14476 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014477 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014478 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014479 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014480 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14481 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014482 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014483 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14484 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014485 else
14486 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014487
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014488 if (ret < 0) {
14489 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14490 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014491 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014492
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014493 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014494}
14495
14496/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014497 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014498 * @ctxt: the schema parser context
14499 * @type: the complex type definition
14500 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014501 *.(4.6) Constraints on Complex Type Definition Schema Components
14502 * Schema Component Constraint:
14503 * Complex Type Definition Properties Correct (ct-props-correct)
14504 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014505 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014506 * Returns 0 if the constraints are satisfied, a positive
14507 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014508 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014509static int
14510xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14511 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014512{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014513 /*
14514 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14515 *
14516 * SPEC (1) "The values of the properties of a complex type definition must
14517 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014518 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014519 * Sub-components (§5.3)."
14520 */
14521 if ((type->baseType != NULL) &&
14522 (IS_SIMPLE_TYPE(type->baseType)) &&
14523 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14524 /*
14525 * SPEC (2) "If the {base type definition} is a simple type definition,
14526 * the {derivation method} must be extension."
14527 */
14528 xmlSchemaPCustomErr(pctxt,
14529 XML_SCHEMAP_SRC_CT_1,
14530 NULL, type, NULL,
14531 "If the base type is a simple type, the derivation method must be "
14532 "'extension'", NULL);
14533 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014534 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014535 /*
14536 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14537 * definition·. That is, it must be possible to reach the ·ur-type
14538 * definition by repeatedly following the {base type definition}."
14539 *
14540 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14541 *
14542 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014543 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014544 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14545 * must not have {type definition}s which are or are derived from ID."
14546 *
14547 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14548 */
14549 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014550}
14551
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014552static int
14553xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14554 xmlSchemaTypePtr typeB)
14555{
14556 /*
14557 * TODO: This should implement component-identity
14558 * in the future.
14559 */
14560 if ((typeA == NULL) || (typeB == NULL))
14561 return (0);
14562 return (typeA == typeB);
14563}
14564
14565/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014566 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014567 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014568 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014569 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014570 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014571 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014572 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014573 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14574 *
14575 * STATUS: completed
14576 *
14577 * Returns 0 if the constraints are satisfied, or 1
14578 * if not.
14579 */
14580static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014581xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014582 xmlSchemaTypePtr baseType,
14583 int set)
14584{
14585 int equal = xmlSchemaAreEqualTypes(type, baseType);
14586 /* TODO: Error codes. */
14587 /*
14588 * SPEC "For a complex type definition (call it D, for derived)
14589 * to be validly derived from a type definition (call this
14590 * B, for base) given a subset of {extension, restriction}
14591 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014592 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014593 if (! equal) {
14594 /*
14595 * SPEC (1) "If B and D are not the same type definition, then the
14596 * {derivation method} of D must not be in the subset."
14597 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014598 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014599 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014600 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014601 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014602 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014603 } else {
14604 /*
14605 * SPEC (2.1) "B and D must be the same type definition."
14606 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014607 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014608 }
14609 /*
14610 * SPEC (2.2) "B must be D's {base type definition}."
14611 */
14612 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014613 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014614 /*
14615 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14616 * definition·."
14617 */
14618 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014619 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014620
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014621 if (IS_COMPLEX_TYPE(type->baseType)) {
14622 /*
14623 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14624 * must be validly derived from B given the subset as defined by this
14625 * constraint."
14626 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014627 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014628 baseType, set));
14629 } else {
14630 /*
14631 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14632 * must be validly derived from B given the subset as defined in Type
14633 * Derivation OK (Simple) (§3.14.6).
14634 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014635 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
14636 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014637}
14638
14639/**
14640 * xmlSchemaCheckCOSDerivedOK:
14641 * @type: the derived simple type definition
14642 * @baseType: the base type definition
14643 *
14644 * Calls:
14645 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014646 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014647 * Checks wheter @type can be validly derived from @baseType.
14648 *
14649 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014650 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014651static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014652xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014653 xmlSchemaTypePtr baseType,
14654 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014655{
14656 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014657 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014658 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014659 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014660}
14661
William M. Brack2f2a6632004-08-20 23:09:47 +000014662/**
14663 * xmlSchemaCheckCOSCTExtends:
14664 * @ctxt: the schema parser context
14665 * @type: the complex type definition
14666 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014667 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014668 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014669 * Derivation Valid (Extension) (cos-ct-extends)
14670 *
14671 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014672 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014673 * (1.5)
14674 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014675 *
14676 * Returns 0 if the constraints are satisfied, a positive
14677 * error code if not and -1 if an internal error occured.
14678 */
14679static int
14680xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14681 xmlSchemaTypePtr type)
14682{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014683 xmlSchemaTypePtr base = type->baseType;
14684 /*
14685 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14686 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014687 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014688 /*
14689 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014690 * then all of the following must be true:"
14691 */
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +000014692 if (IS_COMPLEX_TYPE(base)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014693 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014694 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014695 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014696 */
14697 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14698 xmlSchemaPCustomErr(ctxt,
14699 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14700 NULL, type, NULL,
14701 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014702 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014703 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14704 }
14705 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014706 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014707 * uses}
14708 * of the complex type definition itself, that is, for every attribute
14709 * use in the {attribute uses} of the {base type definition}, there
14710 * must be an attribute use in the {attribute uses} of the complex
14711 * type definition itself whose {attribute declaration} has the same
14712 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014713 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014714 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014715 * NOTE (1.2): This will be already satisfied by the way the attribute
14716 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14717 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014718 */
14719
14720 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014721 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14722 * definition must also have one, and the base type definition's
14723 * {attribute wildcard}'s {namespace constraint} must be a subset
14724 * of the complex type definition's {attribute wildcard}'s {namespace
14725 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014726 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014727 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014728 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014729 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014730 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014731 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014732 if ((type->contentTypeDef != NULL) &&
14733 (type->contentTypeDef == base->contentTypeDef)) {
14734 /*
14735 * SPEC (1.4.1) "The {content type} of the {base type definition}
14736 * and the {content type} of the complex type definition itself
14737 * must be the same simple type definition"
14738 * PASS
14739 */
14740 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14741 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14742 /*
14743 * SPEC (1.4.2) "The {content type} of both the {base type
14744 * definition} and the complex type definition itself must
14745 * be empty."
14746 * PASS
14747 */
14748 } else {
14749 /*
14750 * SPEC (1.4.3) "All of the following must be true:"
14751 */
14752 if (type->subtypes == NULL) {
14753 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014754 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014755 * definition itself must specify a particle.
14756 */
14757 xmlSchemaPCustomErr(ctxt,
14758 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14759 NULL, type, NULL,
14760 "The content type must specify a particle", NULL);
14761 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14762 }
14763 /*
14764 * SPEC (1.4.3.2) "One of the following must be true:"
14765 */
14766 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14767 /*
14768 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14769 * definition} must be empty.
14770 * PASS
14771 */
14772 } else {
14773 /*
14774 * SPEC (1.4.3.2.2) "All of the following must be true:"
14775 */
14776 if ((type->contentType != base->contentType) ||
14777 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14778 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14779 /*
14780 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14781 * or both must be element-only."
14782 */
14783 xmlSchemaPCustomErr(ctxt,
14784 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14785 NULL, type, NULL,
14786 "The content type of both, the type and its base "
14787 "type, must either 'mixed' or 'element-only'", NULL);
14788 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014789 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014790 /*
14791 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14792 * complex type definition must be a ·valid extension·
14793 * of the {base type definition}'s particle, as defined
14794 * in Particle Valid (Extension) (§3.9.6)."
14795 *
14796 * NOTE that we won't check "Particle Valid (Extension)",
14797 * since it is ensured by the derivation process in
14798 * xmlSchemaTypeFixup(). We need to implement this when heading
14799 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014800 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014801 }
14802 /*
14803 * TODO (1.5)
14804 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014805 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014806 } else {
14807 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014808 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014809 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014810 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014811 if (type->contentTypeDef != base) {
14812 /*
14813 * SPEC (2.1) "The {content type} must be the same simple type
14814 * definition."
14815 */
14816 xmlSchemaPCustomErr(ctxt,
14817 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14818 NULL, type, NULL,
14819 "The content type must be the simple base type", NULL);
14820 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14821 }
14822 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14823 /*
14824 * SPEC (2.2) "The {final} of the {base type definition} must not
14825 * contain extension"
14826 * NOTE that this is the same as (1.1).
14827 */
14828 xmlSchemaPCustomErr(ctxt,
14829 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14830 NULL, type, NULL,
14831 "The 'final' of the base type definition "
14832 "contains 'extension'", NULL);
14833 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014834 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014835 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014836 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014837}
14838
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014839/**
14840 * xmlSchemaCheckDerivationOKRestriction:
14841 * @ctxt: the schema parser context
14842 * @type: the complex type definition
14843 *
14844 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014845 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014846 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14847 *
14848 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014849 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014850 * (5.4.2), (5.2.2.1)
14851 *
14852 * Returns 0 if the constraints are satisfied, a positive
14853 * error code if not and -1 if an internal error occured.
14854 */
14855static int
14856xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14857 xmlSchemaTypePtr type)
14858{
14859 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014860
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014861 /*
14862 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14863 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014864 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014865 base = type->baseType;
14866 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14867 /*
14868 * SPEC (1) "The {base type definition} must be a complex type
14869 * definition whose {final} does not contain restriction."
14870 */
14871 xmlSchemaPCustomErr(ctxt,
14872 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14873 NULL, type, NULL,
14874 "The 'final' of the base type definition "
14875 "contains 'restriction'", NULL);
14876 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14877 }
14878 /*
14879 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14880 *
14881 * SPEC (5) "One of the following must be true:"
14882 */
14883 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14884 /*
14885 * SPEC (5.1) "The {base type definition} must be the
14886 * ·ur-type definition·."
14887 * PASS
14888 */
14889 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14890 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14891 /*
14892 * SPEC (5.2.1) "The {content type} of the complex type definition
14893 * must be a simple type definition"
14894 *
14895 * SPEC (5.2.2) "One of the following must be true:"
14896 */
14897 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14898 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14899 /*
14900 * SPEC (5.2.2.1) "The {content type} of the {base type
14901 * definition} must be a simple type definition from which
14902 * the {content type} is validly derived given the empty
14903 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14904 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014905 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014906 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14907 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014908 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014909 /*
14910 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14911 * and have a particle which is ·emptiable· as defined in
14912 * Particle Emptiable (§3.9.6)."
14913 * PASS
14914 */
14915 } else {
14916 xmlSchemaPCustomErr(ctxt,
14917 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14918 NULL, type, NULL,
14919 "The content type of the base type must be either "
14920 "a simple type or 'mixed' and an emptiable particle", NULL);
14921 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14922 }
14923 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14924 /*
14925 * SPEC (5.3.1) "The {content type} of the complex type itself must
14926 * be empty"
14927 */
14928 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14929 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014930 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014931 * definition} must also be empty."
14932 * PASS
14933 */
14934 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14935 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14936 xmlSchemaIsParticleEmptiable(
14937 (xmlSchemaParticlePtr) base->subtypes)) {
14938 /*
14939 * SPEC (5.3.2.2) "The {content type} of the {base type
14940 * definition} must be elementOnly or mixed and have a particle
14941 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14942 * PASS
14943 */
14944 } else {
14945 xmlSchemaPCustomErr(ctxt,
14946 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14947 NULL, type, NULL,
14948 "The content type of the base type must be either "
14949 "empty or 'mixed' (or 'elements-only') and an emptiable "
14950 "particle", NULL);
14951 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14952 }
14953 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014954 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014955 /*
14956 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14957 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014958 */
14959 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
14960 /*
14961 * SPEC (5.4.1.2) "The {content type} of the complex type
14962 * definition itself and of the {base type definition} must be
14963 * mixed"
14964 */
14965 xmlSchemaPCustomErr(ctxt,
14966 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14967 NULL, type, NULL,
14968 "If the content type is 'mixed', then the content type of the "
14969 "base type must also be 'mixed'", NULL);
14970 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14971 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014972 /*
14973 * SPEC (5.4.2) "The particle of the complex type definition itself
14974 * must be a ·valid restriction· of the particle of the {content
14975 * type} of the {base type definition} as defined in Particle Valid
14976 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014977 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014978 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014979 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014980 } else {
14981 xmlSchemaPCustomErr(ctxt,
14982 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14983 NULL, type, NULL,
14984 "The type is not a valid restriction of its base type", NULL);
14985 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14986 }
14987 return (0);
14988}
14989
14990/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014991 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014992 * @ctxt: the schema parser context
14993 * @type: the complex type definition
14994 *
14995 * (3.4.6) Constraints on Complex Type Definition Schema Components
14996 *
14997 * Returns 0 if the constraints are satisfied, a positive
14998 * error code if not and -1 if an internal error occured.
14999 */
15000static int
15001xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
15002 xmlSchemaTypePtr type)
15003{
15004 int ret;
15005 /*
15006 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015007 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015008 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
15009 if (ret != 0)
15010 return (ret);
15011 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
15012 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
15013 else
15014 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
15015 return (ret);
15016}
15017
15018/**
15019 * xmlSchemaCheckSRCCT:
15020 * @ctxt: the schema parser context
15021 * @type: the complex type definition
15022 *
15023 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015024 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015025 * Complex Type Definition Representation OK (src-ct)
15026 *
15027 * Returns 0 if the constraints are satisfied, a positive
15028 * error code if not and -1 if an internal error occured.
15029 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015030static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015031xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015032 xmlSchemaTypePtr type)
15033{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015034 xmlSchemaTypePtr base;
15035 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015036
15037 /*
15038 * TODO: Adjust the error codes here, as I used
15039 * XML_SCHEMAP_SRC_CT_1 only yet.
15040 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015041 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015042 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015043 /*
15044 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015045 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015046 * must be a complex type definition;
15047 */
15048 if (! IS_COMPLEX_TYPE(base)) {
15049 xmlChar *str = NULL;
15050 xmlSchemaPCustomErr(ctxt,
15051 XML_SCHEMAP_SRC_CT_1,
15052 NULL, type, type->node,
15053 "If using <complexContent>, the base type is expected to be "
15054 "a complex type. The base type '%s' is a simple type",
15055 xmlSchemaFormatQName(&str, base->targetNamespace,
15056 base->name));
15057 FREE_AND_NULL(str)
15058 return (XML_SCHEMAP_SRC_CT_1);
15059 }
15060 } else {
15061 /*
15062 * SPEC
15063 * 2 If the <simpleContent> alternative is chosen, all of the
15064 * following must be true:
15065 * 2.1 The type definition ·resolved· to by the ·actual value· of the
15066 * base [attribute] must be one of the following:
15067 */
15068 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015069 if ((type->flags &
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015070 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
15071 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015072 /*
15073 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015074 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015075 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015076 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015077 xmlSchemaPCustomErr(ctxt,
15078 XML_SCHEMAP_SRC_CT_1,
15079 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015080 "If using <simpleContent> and <restriction>, the base "
15081 "type must be a complex type. The base type '%s' is "
15082 "a simple type",
15083 xmlSchemaFormatQName(&str, base->targetNamespace,
15084 base->name));
15085 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015086 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015087 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015088 } else {
15089 /* Base type is a complex type. */
15090 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
15091 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
15092 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015093 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015094 * simple type definition;
15095 * PASS
15096 */
15097 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015098 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015099 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015100 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015101 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015102 type->name);
15103 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015104 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015105 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
15106 (type->flags &
15107 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015108
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015109 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015110 * 2.1.2 only if the <restriction> alternative is also
15111 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015112 * is mixed and a particle emptiable.
15113 */
15114 if (! xmlSchemaIsParticleEmptiable(
15115 (xmlSchemaParticlePtr) base->subtypes)) {
15116 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015117 } else
15118 /*
15119 * Attention: at this point the <simpleType> child is in
15120 * ->contentTypeDef (put there during parsing).
15121 */
15122 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015123 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015124 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015125 * 2.2 If clause 2.1.2 above is satisfied, then there
15126 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015127 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015128 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015129 /* TODO: Change error code to ..._SRC_CT_2_2. */
15130 xmlSchemaPCustomErr(ctxt,
15131 XML_SCHEMAP_SRC_CT_1,
15132 NULL, type, NULL,
15133 "A <simpleType> is expected among the children "
15134 "of <restriction>, if <simpleContent> is used and "
15135 "the base type '%s' is a complex type",
15136 xmlSchemaFormatQName(&str, base->targetNamespace,
15137 base->name));
15138 FREE_AND_NULL(str)
15139 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015140 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015141 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015142 ret = XML_SCHEMAP_SRC_CT_1;
15143 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015144 }
15145 if (ret > 0) {
15146 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015147 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015148 xmlSchemaPCustomErr(ctxt,
15149 XML_SCHEMAP_SRC_CT_1,
15150 NULL, type, NULL,
15151 "If <simpleContent> and <restriction> is used, the "
15152 "base type must be a simple type or a complex type with "
15153 "mixed content and particle emptiable. The base type "
15154 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015155 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015156 base->name));
15157 } else {
15158 xmlSchemaPCustomErr(ctxt,
15159 XML_SCHEMAP_SRC_CT_1,
15160 NULL, type, NULL,
15161 "If <simpleContent> and <extension> is used, the "
15162 "base type must be a simple type. The base type '%s' "
15163 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015164 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015165 base->name));
15166 }
15167 FREE_AND_NULL(str)
15168 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015169 }
15170 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015171 * SPEC (3) "The corresponding complex type definition component must
15172 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015173 * Definition Schema Components (§3.4.6);"
15174 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015175 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015176 /*
15177 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015178 * above for {attribute wildcard} is satisfied, the intensional
15179 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015180 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015181 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015182 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015183 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015184}
William M. Brack2f2a6632004-08-20 23:09:47 +000015185
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015186#ifdef ENABLE_PARTICLE_RESTRICTION
15187/**
15188 * xmlSchemaCheckParticleRangeOK:
15189 * @ctxt: the schema parser context
15190 * @type: the complex type definition
15191 *
15192 * (3.9.6) Constraints on Particle Schema Components
15193 * Schema Component Constraint:
15194 * Occurrence Range OK (range-ok)
15195 *
15196 * STATUS: complete
15197 *
15198 * Returns 0 if the constraints are satisfied, a positive
15199 * error code if not and -1 if an internal error occured.
15200 */
15201static int
15202xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
15203 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015204{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015205 if (rmin < bmin)
15206 return (1);
15207 if ((bmax != UNBOUNDED) &&
15208 (rmax > bmax))
15209 return (1);
15210 return (0);
15211}
15212
15213/**
15214 * xmlSchemaCheckRCaseNameAndTypeOK:
15215 * @ctxt: the schema parser context
15216 * @r: the restricting element declaration particle
15217 * @b: the base element declaration particle
15218 *
15219 * (3.9.6) Constraints on Particle Schema Components
15220 * Schema Component Constraint:
15221 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
15222 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015223 *
15224 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015225 * MISSING (3.2.3)
15226 * CLARIFY: (3.2.2)
15227 *
15228 * Returns 0 if the constraints are satisfied, a positive
15229 * error code if not and -1 if an internal error occured.
15230 */
15231static int
15232xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
15233 xmlSchemaParticlePtr r,
15234 xmlSchemaParticlePtr b)
15235{
15236 xmlSchemaElementPtr elemR, elemB;
15237
15238 /* TODO: Error codes (rcase-NameAndTypeOK). */
15239 elemR = (xmlSchemaElementPtr) r->children;
15240 elemB = (xmlSchemaElementPtr) b->children;
15241 /*
15242 * SPEC (1) "The declarations' {name}s and {target namespace}s are
15243 * the same."
15244 */
15245 if ((elemR != elemB) &&
15246 ((! xmlStrEqual(elemR->name, elemB->name)) ||
15247 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
15248 return (1);
15249 /*
15250 * SPEC (2) "R's occurrence range is a valid restriction of B's
15251 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15252 */
15253 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15254 b->minOccurs, b->maxOccurs) != 0)
15255 return (1);
15256 /*
15257 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
15258 * {scope} are global."
15259 */
15260 if (elemR == elemB)
15261 return (0);
15262 /*
15263 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
15264 */
15265 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
15266 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
15267 return (1);
15268 /*
15269 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
15270 * or is not fixed, or R's declaration's {value constraint} is fixed
15271 * with the same value."
15272 */
15273 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
15274 ((elemR->value == NULL) ||
15275 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
15276 /* TODO: Equality of the initial value or normalized or canonical? */
15277 (! xmlStrEqual(elemR->value, elemB->value))))
15278 return (1);
15279 /*
15280 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
15281 * definitions} is a subset of B's declaration's {identity-constraint
15282 * definitions}, if any."
15283 */
15284 if (elemB->idcs != NULL) {
15285 /* TODO */
15286 }
15287 /*
15288 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
15289 * superset of B's declaration's {disallowed substitutions}."
15290 */
15291 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
15292 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
15293 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
15294 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
15295 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
15296 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
15297 return (1);
15298 /*
15299 * SPEC (3.2.5) "R's {type definition} is validly derived given
15300 * {extension, list, union} from B's {type definition}"
15301 *
15302 * BADSPEC TODO: What's the point of adding "list" and "union" to the
15303 * set, if the corresponding constraints handle "restriction" and
15304 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015305 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015306 */
15307 {
15308 int set = 0;
15309
15310 set |= SUBSET_EXTENSION;
15311 set |= SUBSET_LIST;
15312 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015313 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015314 elemB->subtypes, set) != 0)
15315 return (1);
15316 }
15317 return (0);
15318}
15319
15320/**
15321 * xmlSchemaCheckRCaseNSCompat:
15322 * @ctxt: the schema parser context
15323 * @r: the restricting element declaration particle
15324 * @b: the base wildcard particle
15325 *
15326 * (3.9.6) Constraints on Particle Schema Components
15327 * Schema Component Constraint:
15328 * Particle Derivation OK (Elt:Any -- NSCompat)
15329 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015330 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015331 * STATUS: complete
15332 *
15333 * Returns 0 if the constraints are satisfied, a positive
15334 * error code if not and -1 if an internal error occured.
15335 */
15336static int
15337xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
15338 xmlSchemaParticlePtr r,
15339 xmlSchemaParticlePtr b)
15340{
15341 /* TODO:Error codes (rcase-NSCompat). */
15342 /*
15343 * SPEC "For an element declaration particle to be a ·valid restriction·
15344 * of a wildcard particle all of the following must be true:"
15345 *
15346 * SPEC (1) "The element declaration's {target namespace} is ·valid·
15347 * with respect to the wildcard's {namespace constraint} as defined by
15348 * Wildcard allows Namespace Name (§3.10.4)."
15349 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015350 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015351 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
15352 return (1);
15353 /*
15354 * SPEC (2) "R's occurrence range is a valid restriction of B's
15355 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15356 */
15357 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15358 b->minOccurs, b->maxOccurs) != 0)
15359 return (1);
15360
15361 return (0);
15362}
15363
15364/**
15365 * xmlSchemaCheckRCaseRecurseAsIfGroup:
15366 * @ctxt: the schema parser context
15367 * @r: the restricting element declaration particle
15368 * @b: the base model group particle
15369 *
15370 * (3.9.6) Constraints on Particle Schema Components
15371 * Schema Component Constraint:
15372 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
15373 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015374 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015375 * STATUS: TODO
15376 *
15377 * Returns 0 if the constraints are satisfied, a positive
15378 * error code if not and -1 if an internal error occured.
15379 */
15380static int
15381xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
15382 xmlSchemaParticlePtr r,
15383 xmlSchemaParticlePtr b)
15384{
15385 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
15386 TODO
15387 return (0);
15388}
15389
15390/**
15391 * xmlSchemaCheckRCaseNSSubset:
15392 * @ctxt: the schema parser context
15393 * @r: the restricting wildcard particle
15394 * @b: the base wildcard particle
15395 *
15396 * (3.9.6) Constraints on Particle Schema Components
15397 * Schema Component Constraint:
15398 * Particle Derivation OK (Any:Any -- NSSubset)
15399 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015400 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015401 * STATUS: complete
15402 *
15403 * Returns 0 if the constraints are satisfied, a positive
15404 * error code if not and -1 if an internal error occured.
15405 */
15406static int
15407xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15408 xmlSchemaParticlePtr r,
15409 xmlSchemaParticlePtr b,
15410 int isAnyTypeBase)
15411{
15412 /* TODO: Error codes (rcase-NSSubset). */
15413 /*
15414 * SPEC (1) "R's occurrence range is a valid restriction of B's
15415 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15416 */
15417 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15418 b->minOccurs, b->maxOccurs))
15419 return (1);
15420 /*
15421 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15422 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15423 */
15424 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15425 (xmlSchemaWildcardPtr) b->children))
15426 return (1);
15427 /*
15428 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15429 * definition·, R's {process contents} must be identical to or stronger
15430 * than B's {process contents}, where strict is stronger than lax is
15431 * stronger than skip."
15432 */
15433 if (! isAnyTypeBase) {
15434 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15435 ((xmlSchemaWildcardPtr) b->children)->processContents)
15436 return (1);
15437 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015438
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015439 return (0);
15440}
15441
15442/**
15443 * xmlSchemaCheckCOSParticleRestrict:
15444 * @ctxt: the schema parser context
15445 * @type: the complex type definition
15446 *
15447 * (3.9.6) Constraints on Particle Schema Components
15448 * Schema Component Constraint:
15449 * Particle Valid (Restriction) (cos-particle-restrict)
15450 *
15451 * STATUS: TODO
15452 *
15453 * Returns 0 if the constraints are satisfied, a positive
15454 * error code if not and -1 if an internal error occured.
15455 */
15456static int
15457xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15458 xmlSchemaParticlePtr r,
15459 xmlSchemaParticlePtr b)
15460{
15461 int ret = 0;
15462
15463 /*part = GET_PARTICLE(type);
15464 basePart = GET_PARTICLE(base);
15465 */
15466
15467 TODO
15468
15469 /*
15470 * SPEC (1) "They are the same particle."
15471 */
15472 if (r == b)
15473 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015474
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015475
15476 return (0);
15477}
15478
15479/**
15480 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15481 * @ctxt: the schema parser context
15482 * @r: the model group particle
15483 * @b: the base wildcard particle
15484 *
15485 * (3.9.6) Constraints on Particle Schema Components
15486 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015487 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015488 * NSRecurseCheckCardinality)
15489 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015490 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015491 * STATUS: TODO: subst-groups
15492 *
15493 * Returns 0 if the constraints are satisfied, a positive
15494 * error code if not and -1 if an internal error occured.
15495 */
15496static int
15497xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15498 xmlSchemaParticlePtr r,
15499 xmlSchemaParticlePtr b)
15500{
15501 xmlSchemaParticlePtr part;
15502 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15503 if ((r->children == NULL) || (r->children->children == NULL))
15504 return (-1);
15505 /*
15506 * SPEC "For a group particle to be a ·valid restriction· of a
15507 * wildcard particle..."
15508 *
15509 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015510 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015511 * Particle Valid (Restriction) (§3.9.6)."
15512 */
15513 part = (xmlSchemaParticlePtr) r->children->children;
15514 do {
15515 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15516 return (1);
15517 part = (xmlSchemaParticlePtr) part->next;
15518 } while (part != NULL);
15519 /*
15520 * SPEC (2) "The effective total range of the group [...] is a
15521 * valid restriction of B's occurrence range as defined by
15522 * Occurrence Range OK (§3.9.6)."
15523 */
15524 if (xmlSchemaCheckParticleRangeOK(
15525 xmlSchemaGetParticleTotalRangeMin(r),
15526 xmlSchemaGetParticleTotalRangeMax(r),
15527 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015528 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015529 return (0);
15530}
15531
15532/**
15533 * xmlSchemaCheckRCaseRecurse:
15534 * @ctxt: the schema parser context
15535 * @r: the <all> or <sequence> model group particle
15536 * @b: the base <all> or <sequence> model group particle
15537 *
15538 * (3.9.6) Constraints on Particle Schema Components
15539 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015540 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015541 Recurse)
15542 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015543 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015544 * STATUS: ?
15545 * TODO: subst-groups
15546 *
15547 * Returns 0 if the constraints are satisfied, a positive
15548 * error code if not and -1 if an internal error occured.
15549 */
15550static int
15551xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15552 xmlSchemaParticlePtr r,
15553 xmlSchemaParticlePtr b)
15554{
15555 /* xmlSchemaParticlePtr part; */
15556 /* TODO: Error codes (rcase-Recurse). */
15557 if ((r->children == NULL) || (b->children == NULL) ||
15558 (r->children->type != b->children->type))
15559 return (-1);
15560 /*
15561 * SPEC "For an all or sequence group particle to be a ·valid
15562 * restriction· of another group particle with the same {compositor}..."
15563 *
15564 * SPEC (1) "R's occurrence range is a valid restriction of B's
15565 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15566 */
15567 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15568 b->minOccurs, b->maxOccurs))
15569 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015570
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015571
15572 return (0);
15573}
15574
15575#endif
15576
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015577#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15578 xmlSchemaPCustomErrExt(pctxt, \
15579 XML_SCHEMAP_INVALID_FACET_VALUE, \
15580 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15581 "It is an error for both '%s' and '%s' to be specified on the "\
15582 "same type definition", \
15583 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15584 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15585
15586#define FACET_RESTR_ERR(fac1, msg) \
15587 xmlSchemaPCustomErr(pctxt, \
15588 XML_SCHEMAP_INVALID_FACET_VALUE, \
15589 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015590 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015591
15592#define FACET_RESTR_FIXED_ERR(fac) \
15593 xmlSchemaPCustomErr(pctxt, \
15594 XML_SCHEMAP_INVALID_FACET_VALUE, \
15595 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15596 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015597 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015598
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015599static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015600xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15601 xmlSchemaFacetPtr facet1,
15602 xmlSchemaFacetPtr facet2,
15603 int lessGreater,
15604 int orEqual,
15605 int ofBase)
15606{
15607 xmlChar *msg = NULL;
15608
15609 msg = xmlStrdup(BAD_CAST "'");
15610 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15611 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15612 if (lessGreater == 0)
15613 msg = xmlStrcat(msg, BAD_CAST " equal to");
15614 if (lessGreater == 1)
15615 msg = xmlStrcat(msg, BAD_CAST " greater than");
15616 else
15617 msg = xmlStrcat(msg, BAD_CAST " less than");
15618
15619 if (orEqual)
15620 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15621 msg = xmlStrcat(msg, BAD_CAST " '");
15622 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15623 if (ofBase)
15624 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15625 else
15626 msg = xmlStrcat(msg, BAD_CAST "'");
15627
15628 xmlSchemaPCustomErr(pctxt,
15629 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015630 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015631 (const char *) msg, NULL);
15632
15633 if (msg != NULL)
15634 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015635}
15636
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015637static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015638xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15639 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015640{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015641 xmlSchemaTypePtr base = type->baseType;
15642 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015643 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015644 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15645 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15646 fmininc = NULL, fmaxinc = NULL,
15647 fminexc = NULL, fmaxexc = NULL,
15648 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15649 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15650 bfmininc = NULL, bfmaxinc = NULL,
15651 bfminexc = NULL, bfmaxexc = NULL;
15652 int res, err = 0, fixedErr;
15653 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015654 * 3 The {facets} of R are the union of S and the {facets}
15655 * of B, eliminating duplicates. To eliminate duplicates,
15656 * when a facet of the same kind occurs in both S and the
15657 * {facets} of B, the one in the {facets} of B is not
15658 * included, with the exception of enumeration and pattern
15659 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015660 * are allowed.
15661 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015662
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015663 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15664 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015665
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015666 last = type->facetSet;
15667 if (last != NULL)
15668 while (last->next != NULL)
15669 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015670
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015671 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15672 facet = cur->facet;
15673 switch (facet->type) {
15674 case XML_SCHEMA_FACET_LENGTH:
15675 flength = facet; break;
15676 case XML_SCHEMA_FACET_MINLENGTH:
15677 fminlen = facet; break;
15678 case XML_SCHEMA_FACET_MININCLUSIVE:
15679 fmininc = facet; break;
15680 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15681 fminexc = facet; break;
15682 case XML_SCHEMA_FACET_MAXLENGTH:
15683 fmaxlen = facet; break;
15684 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15685 fmaxinc = facet; break;
15686 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15687 fmaxexc = facet; break;
15688 case XML_SCHEMA_FACET_TOTALDIGITS:
15689 ftotdig = facet; break;
15690 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15691 ffracdig = facet; break;
15692 default:
15693 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015694 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015695 }
15696 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15697 facet = cur->facet;
15698 switch (facet->type) {
15699 case XML_SCHEMA_FACET_LENGTH:
15700 bflength = facet; break;
15701 case XML_SCHEMA_FACET_MINLENGTH:
15702 bfminlen = facet; break;
15703 case XML_SCHEMA_FACET_MININCLUSIVE:
15704 bfmininc = facet; break;
15705 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15706 bfminexc = facet; break;
15707 case XML_SCHEMA_FACET_MAXLENGTH:
15708 bfmaxlen = facet; break;
15709 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15710 bfmaxinc = facet; break;
15711 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15712 bfmaxexc = facet; break;
15713 case XML_SCHEMA_FACET_TOTALDIGITS:
15714 bftotdig = facet; break;
15715 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15716 bffracdig = facet; break;
15717 default:
15718 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015719 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015720 }
15721 err = 0;
15722 /*
15723 * length and minLength or maxLength (2.2) + (3.2)
15724 */
15725 if (flength && (fminlen || fmaxlen)) {
15726 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15727 "either of 'minLength' or 'maxLength' to be specified on "
15728 "the same type definition")
15729 }
15730 /*
15731 * Mutual exclusions in the same derivation step.
15732 */
15733 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015734 /*
15735 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015736 */
15737 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15738 }
15739 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015740 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015741 * SCC "minInclusive and minExclusive"
15742 */
15743 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015744 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015745
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015746 if (flength && bflength) {
15747 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015748 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015749 * The values have to be equal.
15750 */
15751 res = xmlSchemaCompareValues(flength->val, bflength->val);
15752 if (res == -2)
15753 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015754 if (res != 0)
15755 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15756 if ((res != 0) && (bflength->fixed)) {
15757 FACET_RESTR_FIXED_ERR(flength)
15758 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015759
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015760 }
15761 if (fminlen && bfminlen) {
15762 /*
15763 * SCC "minLength valid restriction"
15764 * minLength >= BASE minLength
15765 */
15766 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15767 if (res == -2)
15768 goto internal_error;
15769 if (res == -1)
15770 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15771 if ((res != 0) && (bfminlen->fixed)) {
15772 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015773 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015774 }
15775 if (fmaxlen && bfmaxlen) {
15776 /*
15777 * SCC "maxLength valid restriction"
15778 * maxLength <= BASE minLength
15779 */
15780 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15781 if (res == -2)
15782 goto internal_error;
15783 if (res == 1)
15784 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15785 if ((res != 0) && (bfmaxlen->fixed)) {
15786 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015787 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015788 }
15789 /*
15790 * SCC "length and minLength or maxLength"
15791 */
15792 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015793 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015794 if (flength) {
15795 if (! fminlen)
15796 flength = bflength;
15797 if (fminlen) {
15798 /* (1.1) length >= minLength */
15799 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15800 if (res == -2)
15801 goto internal_error;
15802 if (res == -1)
15803 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15804 }
15805 if (! fmaxlen)
15806 fmaxlen = bfmaxlen;
15807 if (fmaxlen) {
15808 /* (2.1) length <= maxLength */
15809 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15810 if (res == -2)
15811 goto internal_error;
15812 if (res == 1)
15813 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15814 }
15815 }
15816 if (fmaxinc) {
15817 /*
15818 * "maxInclusive"
15819 */
15820 if (fmininc) {
15821 /* SCC "maxInclusive >= minInclusive" */
15822 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15823 if (res == -2)
15824 goto internal_error;
15825 if (res == -1) {
15826 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15827 }
15828 }
15829 /*
15830 * SCC "maxInclusive valid restriction"
15831 */
15832 if (bfmaxinc) {
15833 /* maxInclusive <= BASE maxInclusive */
15834 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15835 if (res == -2)
15836 goto internal_error;
15837 if (res == 1)
15838 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15839 if ((res != 0) && (bfmaxinc->fixed)) {
15840 FACET_RESTR_FIXED_ERR(fmaxinc)
15841 }
15842 }
15843 if (bfmaxexc) {
15844 /* maxInclusive < BASE maxExclusive */
15845 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15846 if (res == -2)
15847 goto internal_error;
15848 if (res != -1) {
15849 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15850 }
15851 }
15852 if (bfmininc) {
15853 /* maxInclusive >= BASE minInclusive */
15854 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15855 if (res == -2)
15856 goto internal_error;
15857 if (res == -1) {
15858 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15859 }
15860 }
15861 if (bfminexc) {
15862 /* maxInclusive > BASE minExclusive */
15863 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15864 if (res == -2)
15865 goto internal_error;
15866 if (res != 1) {
15867 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15868 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015869 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015870 }
15871 if (fmaxexc) {
15872 /*
15873 * "maxExclusive >= minExclusive"
15874 */
15875 if (fminexc) {
15876 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15877 if (res == -2)
15878 goto internal_error;
15879 if (res == -1) {
15880 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15881 }
15882 }
15883 /*
15884 * "maxExclusive valid restriction"
15885 */
15886 if (bfmaxexc) {
15887 /* maxExclusive <= BASE maxExclusive */
15888 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15889 if (res == -2)
15890 goto internal_error;
15891 if (res == 1) {
15892 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15893 }
15894 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015895 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015896 }
15897 }
15898 if (bfmaxinc) {
15899 /* maxExclusive <= BASE maxInclusive */
15900 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15901 if (res == -2)
15902 goto internal_error;
15903 if (res == 1) {
15904 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15905 }
15906 }
15907 if (bfmininc) {
15908 /* maxExclusive > BASE minInclusive */
15909 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15910 if (res == -2)
15911 goto internal_error;
15912 if (res != 1) {
15913 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15914 }
15915 }
15916 if (bfminexc) {
15917 /* maxExclusive > BASE minExclusive */
15918 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15919 if (res == -2)
15920 goto internal_error;
15921 if (res != 1) {
15922 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15923 }
15924 }
15925 }
15926 if (fminexc) {
15927 /*
15928 * "minExclusive < maxInclusive"
15929 */
15930 if (fmaxinc) {
15931 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15932 if (res == -2)
15933 goto internal_error;
15934 if (res != -1) {
15935 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15936 }
15937 }
15938 /*
15939 * "minExclusive valid restriction"
15940 */
15941 if (bfminexc) {
15942 /* minExclusive >= BASE minExclusive */
15943 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15944 if (res == -2)
15945 goto internal_error;
15946 if (res == -1) {
15947 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15948 }
15949 if ((res != 0) && (bfminexc->fixed)) {
15950 FACET_RESTR_FIXED_ERR(fminexc)
15951 }
15952 }
15953 if (bfmaxinc) {
15954 /* minExclusive <= BASE maxInclusive */
15955 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15956 if (res == -2)
15957 goto internal_error;
15958 if (res == 1) {
15959 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15960 }
15961 }
15962 if (bfmininc) {
15963 /* minExclusive >= BASE minInclusive */
15964 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15965 if (res == -2)
15966 goto internal_error;
15967 if (res == -1) {
15968 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15969 }
15970 }
15971 if (bfmaxexc) {
15972 /* minExclusive < BASE maxExclusive */
15973 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15974 if (res == -2)
15975 goto internal_error;
15976 if (res != -1) {
15977 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15978 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015979 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015980 }
15981 if (fmininc) {
15982 /*
15983 * "minInclusive < maxExclusive"
15984 */
15985 if (fmaxexc) {
15986 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15987 if (res == -2)
15988 goto internal_error;
15989 if (res != -1) {
15990 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15991 }
15992 }
15993 /*
15994 * "minExclusive valid restriction"
15995 */
15996 if (bfmininc) {
15997 /* minInclusive >= BASE minInclusive */
15998 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15999 if (res == -2)
16000 goto internal_error;
16001 if (res == -1) {
16002 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
16003 }
16004 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016005 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016006 }
16007 }
16008 if (bfmaxinc) {
16009 /* minInclusive <= BASE maxInclusive */
16010 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
16011 if (res == -2)
16012 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000016013 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016014 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
16015 }
16016 }
16017 if (bfminexc) {
16018 /* minInclusive > BASE minExclusive */
16019 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
16020 if (res == -2)
16021 goto internal_error;
16022 if (res != 1)
16023 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
16024 }
16025 if (bfmaxexc) {
16026 /* minInclusive < BASE maxExclusive */
16027 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
16028 if (res == -2)
16029 goto internal_error;
16030 if (res != -1)
16031 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
16032 }
16033 }
16034 if (ftotdig && bftotdig) {
16035 /*
16036 * SCC " totalDigits valid restriction"
16037 * totalDigits <= BASE totalDigits
16038 */
16039 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
16040 if (res == -2)
16041 goto internal_error;
16042 if (res == 1)
16043 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
16044 -1, 1, 1);
16045 if ((res != 0) && (bftotdig->fixed)) {
16046 FACET_RESTR_FIXED_ERR(ftotdig)
16047 }
16048 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016049 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016050 /*
16051 * SCC "fractionDigits valid restriction"
16052 * fractionDigits <= BASE fractionDigits
16053 */
16054 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
16055 if (res == -2)
16056 goto internal_error;
16057 if (res == 1)
16058 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
16059 -1, 1, 1);
16060 if ((res != 0) && (bffracdig->fixed)) {
16061 FACET_RESTR_FIXED_ERR(ffracdig)
16062 }
16063 }
16064 /*
16065 * SCC "fractionDigits less than or equal to totalDigits"
16066 */
16067 if (! ftotdig)
16068 ftotdig = bftotdig;
16069 if (! ffracdig)
16070 ffracdig = bffracdig;
16071 if (ftotdig && ffracdig) {
16072 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
16073 if (res == -2)
16074 goto internal_error;
16075 if (res == 1)
16076 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
16077 -1, 1, 0);
16078 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016079 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016080 * *Enumerations* won' be added here, since only the first set
16081 * of enumerations in the ancestor-or-self axis is used
16082 * for validation, plus we need to use the base type of those
16083 * enumerations for whitespace.
16084 *
16085 * *Patterns*: won't be add here, since they are ORed at
16086 * type level and ANDed at ancestor level. This will
16087 * happed during validation by walking the base axis
16088 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016089 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016090 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
16091 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016092 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016093 * Special handling of enumerations and patterns.
16094 * TODO: hmm, they should not appear in the set, so remove this.
16095 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016096 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016097 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016098 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016099 /*
16100 * Search for a duplicate facet in the current type.
16101 */
16102 link = type->facetSet;
16103 err = 0;
16104 fixedErr = 0;
16105 while (link != NULL) {
16106 facet = link->facet;
16107 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016108 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016109 case XML_SCHEMA_FACET_WHITESPACE:
16110 /*
16111 * The whitespace must be stronger.
16112 */
16113 if (facet->whitespace < bfacet->whitespace) {
16114 FACET_RESTR_ERR(flength,
16115 "The 'whitespace' value has to be equal to "
16116 "or stronger than the 'whitespace' value of "
16117 "the base type")
16118 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016119 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016120 (facet->whitespace != bfacet->whitespace)) {
16121 FACET_RESTR_FIXED_ERR(facet)
16122 }
16123 break;
16124 default:
16125 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016126 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016127 /* Duplicate found. */
16128 break;
16129 }
16130 link = link->next;
16131 }
16132 /*
16133 * If no duplicate was found: add the base types's facet
16134 * to the set.
16135 */
16136 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016137 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016138 xmlMalloc(sizeof(xmlSchemaFacetLink));
16139 if (link == NULL) {
16140 xmlSchemaPErrMemory(pctxt,
16141 "deriving facets, creating a facet link", NULL);
16142 return (-1);
16143 }
16144 link->facet = cur->facet;
16145 link->next = NULL;
16146 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016147 type->facetSet = link;
16148 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016149 last->next = link;
16150 last = link;
16151 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016152
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016153 }
16154
16155 return (0);
16156internal_error:
16157 xmlSchemaPCustomErr(pctxt,
16158 XML_SCHEMAP_INVALID_FACET_VALUE,
16159 NULL, type, NULL,
16160 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
16161 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016162}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016163
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016164static int
16165xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
16166 xmlSchemaTypePtr type)
16167{
16168 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
16169 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016170 * The actual value is then formed by replacing any union type
16171 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016172 * {member type definitions}, in order.
16173 */
16174 link = type->memberTypes;
16175 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016176
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016177 if (IS_NOT_TYPEFIXED(link->type))
16178 xmlSchemaTypeFixup(link->type, pctxt, NULL);
16179
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016180 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016181 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016182 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016183 link->type = subLink->type;
16184 if (subLink->next != NULL) {
16185 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016186 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016187 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016188 while (subLink != NULL) {
16189 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016190 xmlMalloc(sizeof(xmlSchemaTypeLink));
16191 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016192 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016193 NULL);
16194 return (-1);
16195 }
16196 newLink->type = subLink->type;
16197 prevLink->next = newLink;
16198 prevLink = newLink;
16199 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016200
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016201 subLink = subLink->next;
16202 }
16203 }
16204 }
16205 }
16206 link = link->next;
16207 }
16208 return (0);
16209}
16210
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016211static void
16212xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
16213{
16214 int has = 0, needVal = 0, normVal = 0;
16215
16216 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
16217 if (has) {
16218 needVal = (type->baseType->flags &
16219 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
16220 normVal = (type->baseType->flags &
16221 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
16222 }
16223 if (type->facets != NULL) {
16224 xmlSchemaFacetPtr fac;
16225
16226 for (fac = type->facets; fac != NULL; fac = fac->next) {
16227 switch (fac->type) {
16228 case XML_SCHEMA_FACET_WHITESPACE:
16229 break;
16230 case XML_SCHEMA_FACET_PATTERN:
16231 normVal = 1;
16232 has = 1;
16233 break;
16234 case XML_SCHEMA_FACET_ENUMERATION:
16235 needVal = 1;
16236 normVal = 1;
16237 has = 1;
16238 break;
16239 default:
16240 has = 1;
16241 break;
16242 }
16243 }
16244 }
16245 if (normVal)
16246 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
16247 if (needVal)
16248 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
16249 if (has)
16250 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
16251
16252 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
16253 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
16254 /*
16255 * OPTIMIZE VAL TODO: Some facets need a computed value.
16256 */
16257 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
16258 (prim->builtInType != XML_SCHEMAS_STRING)) {
16259 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
16260 }
16261 }
16262}
16263
16264static int
16265xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
16266{
16267
16268
16269 /*
16270 * Evaluate the whitespace-facet value.
16271 */
16272 if (VARIETY_LIST(type)) {
16273 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
16274 return (0);
16275 } else if (VARIETY_UNION(type))
16276 return (0);
16277
16278 if (type->facetSet != NULL) {
16279 xmlSchemaFacetLinkPtr lin;
16280
16281 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
16282 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
16283 switch (lin->facet->whitespace) {
16284 case XML_SCHEMAS_FACET_PRESERVE:
16285 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
16286 break;
16287 case XML_SCHEMAS_FACET_REPLACE:
16288 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
16289 break;
16290 case XML_SCHEMAS_FACET_COLLAPSE:
16291 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
16292 break;
16293 default:
16294 return (-1);
16295 }
16296 return (0);
16297 }
16298 }
16299 }
16300 /*
16301 * For all ·atomic· datatypes other than string (and types ·derived·
16302 * by ·restriction· from it) the value of whiteSpace is fixed to
16303 * collapse
16304 */
16305 {
16306 xmlSchemaTypePtr anc;
16307
16308 for (anc = type->baseType; anc != NULL &&
16309 anc->builtInType != XML_SCHEMAS_ANYTYPE;
16310 anc = anc->baseType) {
16311
16312 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
16313 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
16314 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
16315
16316 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
16317 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
16318 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
16319
16320 } else
16321 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
16322 break;
16323 }
16324 }
16325 return (0);
16326 }
16327 return (0);
16328}
16329
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016330/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016331 * xmlSchemaTypeFixup:
16332 * @typeDecl: the schema type definition
16333 * @ctxt: the schema parser context
16334 *
16335 * Fixes the content model of the type.
16336 */
16337static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016338xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016339 xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000016340{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016341 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000016342 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016343 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
16344 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000016345 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016346 if (! IS_NOT_TYPEFIXED(type))
16347 return;
16348 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000016349 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016350 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016351
16352 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016353 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016354 XML_SCHEMAP_INTERNAL,
16355 NULL, type, NULL,
16356 "Internal error: xmlSchemaTypeFixup, "
16357 "baseType is missing on '%s'", type->name);
16358 return;
16359 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016360
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016361 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016362 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016363
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016364 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016365 * Type-fix the base type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016366 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016367 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016368 xmlSchemaTypeFixup(baseType, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016369 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
16370 /*
16371 * Skip fixup if the base type is invalid.
16372 * TODO: Generate a warning!
16373 */
16374 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016375 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016376 /*
16377 * This basically checks if the base type can be derived.
16378 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016379 if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016380 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
16381 return;
16382 }
16383 /*
16384 * Fixup the content type.
16385 */
16386 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
16387 /*
16388 * Corresponds to <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016389 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016390 if ((IS_COMPLEX_TYPE(baseType)) &&
16391 (baseType->contentTypeDef != NULL) &&
16392 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016393 xmlSchemaTypePtr contentBase, content;
16394 char buf[30];
16395 const xmlChar *tmpname;
16396 /*
16397 * SPEC (1) If <restriction> + base type is <complexType>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016398 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016399 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016400 if (type->contentTypeDef != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016401 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016402 * SPEC (1.1) "the simple type definition corresponding to the
16403 * <simpleType> among the [children] of <restriction> if there
16404 * is one;"
16405 * Note that this "<simpleType> among the [children]" was put
16406 * into ->contentTypeDef during parsing.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016407 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016408 contentBase = type->contentTypeDef;
16409 type->contentTypeDef = NULL;
16410 } else {
16411 /*
16412 * (1.2) "...otherwise (<restriction> has no <simpleType>
16413 * among its [children]), the simple type definition which
16414 * is the {content type} of the ... base type."
16415 */
16416 contentBase = baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016417 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016418 /*
16419 * SPEC
16420 * "... a simple type definition which restricts the simple
16421 * type definition identified in clause 1.1 or clause 1.2
16422 * with a set of facet components"
16423 *
16424 * Create the anonymous simple type, which will be the content
16425 * type of the complex type.
16426 */
16427 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
16428 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
16429 content = xmlSchemaAddType(pctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000016430 pctxt->schema, tmpname, tmpname, type->node, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016431 if (content == NULL)
16432 return;
16433 /*
16434 * We will use the same node as for the <complexType>
16435 * to have it somehow anchored in the schema doc.
16436 */
16437 content->node = type->node;
16438 content->type = XML_SCHEMA_TYPE_SIMPLE;
16439 content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16440 content->baseType = contentBase;
16441 /*
16442 * Move the facets, previously anchored on the complexType.
16443 */
16444 content->facets = type->facets;
16445 type->facets = NULL;
16446 content->facetSet = type->facetSet;
16447 type->facetSet = NULL;
16448
16449 type->contentTypeDef = content;
16450 if (IS_NOT_TYPEFIXED(contentBase))
16451 xmlSchemaTypeFixup(contentBase, pctxt, NULL);
16452 xmlSchemaTypeFixup(content, pctxt, NULL);
16453
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016454 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16455 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16456 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16457 /*
16458 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16459 * an emptiable particle, then a simple type definition which
16460 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016461 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016462 if ((type->contentTypeDef == NULL) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016463 (type->contentTypeDef->baseType == NULL)) {
16464 /*
16465 * TODO: Check if this ever happens.
16466 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016467 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016468 XML_SCHEMAP_INTERNAL,
16469 NULL, type, NULL,
16470 "Internal error: xmlSchemaTypeFixup, "
16471 "complex type '%s': the <simpleContent><restriction> "
16472 "is missing a <simpleType> child, but was not catched "
16473 "by xmlSchemaCheckSRCCT()", type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016474 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016475 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16476 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16477 /*
16478 * SPEC (3) If <extension> + base is <complexType> with
16479 * <simpleType> content, "...then the {content type} of that
16480 * complex type definition"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016481 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016482 if (baseType->contentTypeDef == NULL) {
16483 /*
16484 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16485 * should have catched this already.
16486 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016487 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016488 XML_SCHEMAP_INTERNAL,
16489 NULL, type, NULL,
16490 "Internal error: xmlSchemaTypeFixup, "
16491 "complex type '%s': the <extension>ed base type is "
16492 "a complex type with no simple content type",
16493 type->name);
16494 }
16495 type->contentTypeDef = baseType->contentTypeDef;
16496 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16497 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16498 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016499 * SPEC (4) <extension> + base is <simpleType>
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016500 * "... then that simple type definition"
16501 */
16502 type->contentTypeDef = baseType;
16503 } else {
16504 /*
16505 * TODO: Check if this ever happens.
16506 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016507 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016508 XML_SCHEMAP_INTERNAL,
16509 NULL, type, NULL,
16510 "Internal error: xmlSchemaTypeFixup, "
16511 "complex type '%s' with <simpleContent>: unhandled "
16512 "derivation case", type->name);
16513 }
16514 } else {
16515 int dummySequence = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016516 xmlSchemaParticlePtr particle =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016517 (xmlSchemaParticlePtr) type->subtypes;
16518 /*
16519 * Corresponds to <complexType><complexContent>...
16520 *
16521 * NOTE that the effective mixed was already set during parsing of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016522 * <complexType> and <complexContent>; its flag value is
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016523 * XML_SCHEMAS_TYPE_MIXED.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016524 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016525 * Compute the "effective content":
16526 * (2.1.1) + (2.1.2) + (2.1.3)
16527 */
16528 if ((particle == NULL) ||
16529 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16530 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16531 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16532 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16533 (particle->minOccurs == 0))) &&
16534 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016535 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016536 /*
16537 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16538 * a particle whose properties are as follows:..."
16539 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016540 * Empty sequence model group with
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016541 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16542 * NOTE that we sill assign it the <complexType> node to
16543 * somehow anchor it in the doc.
16544 */
16545 if ((particle == NULL) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016546 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016547 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016548 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016549 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016550 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016551 type->node, 1, 1);
16552 if (particle == NULL)
16553 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016554 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016555 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016556 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016557 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016558 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016559 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16560 if (particle->children == NULL)
16561 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016562
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016563 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016564 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016565 dummySequence = 1;
16566 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16567 } else {
16568 /*
16569 * SPEC (2.1.5) "otherwise empty"
16570 */
16571 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016572 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016573 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016574 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016575 * SPEC (2.2) "otherwise the particle corresponding to the
16576 * <all>, <choice>, <group> or <sequence> among the
16577 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016578 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016579 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16580 }
16581 /*
16582 * Compute the "content type".
16583 */
16584 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016585 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016586 * SPEC (3.1) "If <restriction>..."
16587 * (3.1.1) + (3.1.2) */
16588 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16589 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16590 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16591 }
16592 } else {
16593 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016594 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016595 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016596 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16597 /*
16598 * SPEC (3.2.1)
16599 */
16600 type->contentType = baseType->contentType;
16601 type->subtypes = baseType->subtypes;
16602 /*
16603 * NOTE that the effective mixed is ignored here.
16604 */
16605 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16606 /*
16607 * SPEC (3.2.2)
16608 */
16609 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16610 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16611 } else {
16612 /*
16613 * SPEC (3.2.3)
16614 */
16615 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16616 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16617 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016618 * "A model group whose {compositor} is sequence and whose
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016619 * {particles} are..."
16620 */
16621 if (! dummySequence) {
16622 xmlSchemaTreeItemPtr effectiveContent =
16623 (xmlSchemaTreeItemPtr) type->subtypes;
16624 /*
16625 * Create the particle.
16626 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016627 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016628 type->node, 1, 1);
16629 if (particle == NULL)
16630 return;
16631 /*
16632 * Create the "sequence" model group.
16633 */
16634 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016635 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016636 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16637 if (particle->children == NULL)
16638 return;
16639 type->subtypes = (xmlSchemaTypePtr) particle;
16640 /*
16641 * SPEC "the particle of the {content type} of
16642 * the ... base ..."
16643 * Create a duplicate of the base type's particle
16644 * and assign its "term" to it.
16645 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016646 particle->children->children =
16647 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
16648 pctxt->schema, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016649 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016650 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016651 if (particle->children->children == NULL)
16652 return;
16653 particle = (xmlSchemaParticlePtr)
16654 particle->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016655 particle->children =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016656 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16657 /*
16658 * SPEC "followed by the ·effective content·."
16659 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016660 particle->next = effectiveContent;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016661 } else {
16662 /*
16663 * This is the case when there is already an empty
16664 * <sequence> with minOccurs==maxOccurs==1.
16665 * Just add the base types's content type.
16666 * NOTE that, although we miss to add an intermediate
16667 * <sequence>, this should produce no difference to
16668 * neither the regex compilation of the content model,
16669 * nor to the complex type contraints.
16670 */
16671 particle->children->children =
16672 (xmlSchemaTreeItemPtr) baseType->subtypes;
16673 }
16674 }
16675 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016676 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016677 /*
16678 * Apply the complex type component constraints; this will not
16679 * check attributes, since this is done in
16680 * xmlSchemaBuildAttributeValidation().
16681 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016682 if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
16683 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016684 /*
16685 * Inherit & check constraints for attributes.
16686 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016687 xmlSchemaBuildAttributeValidation(pctxt, type);
16688 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016689 /*
16690 * Simple Type Definition Schema Component
16691 */
16692 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016693 if (VARIETY_LIST(type)) {
16694 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016695 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016696 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016697 if (type->subtypes == NULL) {
16698 /*
16699 * This one is really needed, so get out.
16700 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016701 PERROR_INT("xmlSchemaTypeFixup",
16702 "list type has no item-type assigned");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016703 return;
16704 }
16705 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016706 xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
16707 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016708 /*
16709 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016710 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016711 if (type->memberTypes == NULL) {
16712 /*
16713 * This one is really needed, so get out.
16714 */
16715 return;
16716 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016717 if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016718 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016719 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016720 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016721 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016722 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016723 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016724 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016725 xmlSchemaTypeFixup(baseType, pctxt, NULL);
16726 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016727 * Variety
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016728 * If the <restriction> alternative is chosen, then the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016729 * {variety} of the {base type definition}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016730 */
16731 if (VARIETY_ATOMIC(baseType))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016732 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016733 else if (VARIETY_LIST(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016734 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16735 /*
16736 * Inherit the itemType.
16737 */
16738 type->subtypes = baseType->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016739 } else if (VARIETY_UNION(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016740 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16741 /*
16742 * NOTE that we won't assign the memberTypes of the base,
16743 * since this will make trouble when freeing them; we will
16744 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016745 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016746 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016747 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016748 /*
16749 * Check constraints.
16750 *
16751 * TODO: Split this somehow, we need to know first if we can derive
16752 * from the base type at all!
16753 */
16754 if (type->baseType != NULL) {
16755 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016756 * Schema Component Constraint: Simple Type Restriction
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016757 * (Facets)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016758 * NOTE: Satisfaction of 1 and 2 arise from the fixup
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016759 * applied beforehand.
16760 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016761 xmlSchemaCheckSRCSimpleType(pctxt, type);
16762 xmlSchemaCheckFacetValues(type, pctxt);
16763 if ((type->facetSet != NULL) ||
16764 (type->baseType->facetSet != NULL))
16765 xmlSchemaDeriveAndValidateFacets(pctxt, type);
16766 /*
16767 * Whitespace value.
16768 */
16769 xmlSchemaTypeFixupWhitespace(type);
16770 xmlSchemaTypeFixupOptimFacets(type);
16771 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016772 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016773
Daniel Veillard8651f532002-04-17 09:06:27 +000016774#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016775 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016776 xmlGenericError(xmlGenericErrorContext,
16777 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016778 type->node->doc->URL,
16779 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016780 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016781 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016782 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016783 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16784 switch (type->contentType) {
16785 case XML_SCHEMA_CONTENT_SIMPLE:
16786 xmlGenericError(xmlGenericErrorContext, "simple\n");
16787 break;
16788 case XML_SCHEMA_CONTENT_ELEMENTS:
16789 xmlGenericError(xmlGenericErrorContext, "elements\n");
16790 break;
16791 case XML_SCHEMA_CONTENT_UNKNOWN:
16792 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16793 break;
16794 case XML_SCHEMA_CONTENT_EMPTY:
16795 xmlGenericError(xmlGenericErrorContext, "empty\n");
16796 break;
16797 case XML_SCHEMA_CONTENT_MIXED:
16798 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016799 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016800 xmlGenericError(xmlGenericErrorContext,
16801 "mixed as emptiable particle\n");
16802 else
16803 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16804 break;
16805 /* Removed, since not used. */
16806 /*
16807 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16808 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16809 break;
16810 */
16811 case XML_SCHEMA_CONTENT_BASIC:
16812 xmlGenericError(xmlGenericErrorContext, "basic\n");
16813 break;
16814 default:
16815 xmlGenericError(xmlGenericErrorContext,
16816 "not registered !!!\n");
16817 break;
16818 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016819 }
16820#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016821}
16822
16823/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016824 * xmlSchemaCheckFacet:
16825 * @facet: the facet
16826 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000016827 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016828 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016829 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016830 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016831 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016832 * Returns 0 if valid, a positive error code if not valid and
16833 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016834 */
16835int
16836xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016837 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016838 xmlSchemaParserCtxtPtr pctxt,
16839 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016840{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016841 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016842
Daniel Veillardce682bc2004-11-05 17:22:25 +000016843 if ((facet == NULL) || (typeDecl == NULL))
16844 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016845 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016846 * TODO: will the parser context be given if used from
16847 * the relaxNG module?
16848 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016849 if (pctxt == NULL)
16850 ctxtGiven = 0;
16851 else
16852 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016853
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016854 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016855 case XML_SCHEMA_FACET_MININCLUSIVE:
16856 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16857 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016858 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16859 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016860 /*
16861 * Okay we need to validate the value
16862 * at that point.
16863 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016864 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016865
16866 /* 4.3.5.5 Constraints on enumeration Schema Components
16867 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016868 * It is an ·error· if any member of {value} is not in the
16869 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016870 *
16871 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016872 * The value ·must· be in the
16873 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016874 */
16875 /*
16876 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016877 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016878 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016879 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016880 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016881 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016882 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016883 */
16884 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16885 base = typeDecl->baseType;
16886 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016887 PERROR_INT("xmlSchemaCheckFacet",
16888 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016889 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016890 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016891 } else
16892 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016893
16894 if (! ctxtGiven) {
16895 /*
16896 * A context is needed if called from RelaxNG.
16897 */
16898 pctxt = xmlSchemaNewParserCtxt("*");
16899 if (pctxt == NULL)
16900 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016901 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016902 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016903 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016904 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016905 * facet->node is just the node holding the facet
16906 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016907 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016908 */
16909 ret = xmlSchemaVCheckCVCSimpleType(
16910 (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
16911 facet->value, &(facet->val), 1, 1, 0);
16912 if (ret != 0) {
16913 if (ret < 0) {
16914 /* No error message for RelaxNG. */
16915 if (ctxtGiven) {
16916 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16917 XML_SCHEMAP_INTERNAL, facet->node, NULL,
16918 "Internal error: xmlSchemaCheckFacet, "
16919 "failed to validate the value '%s' of the "
16920 "facet '%s' against the base type",
16921 facet->value, xmlSchemaFacetTypeToString(facet->type));
16922 }
16923 goto internal_error;
16924 }
16925 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16926 /* No error message for RelaxNG. */
16927 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016928 xmlChar *str = NULL;
16929
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016930 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16931 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016932 "The value '%s' of the facet does not validate "
16933 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016934 facet->value,
16935 xmlSchemaFormatQName(&str,
16936 base->targetNamespace, base->name));
16937 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016938 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016939 goto exit;
16940 } else if (facet->val == NULL) {
16941 if (ctxtGiven) {
16942 PERROR_INT("xmlSchemaCheckFacet",
16943 "value was not computed");
16944 }
16945 TODO
16946 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016947 break;
16948 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016949 case XML_SCHEMA_FACET_PATTERN:
16950 facet->regexp = xmlRegexpCompile(facet->value);
16951 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016952 ret = XML_SCHEMAP_REGEXP_INVALID;
16953 /* No error message for RelaxNG. */
16954 if (ctxtGiven) {
16955 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16956 ret, facet->node, typeDecl,
16957 "The value '%s' of the facet 'pattern' is not a "
16958 "valid regular expression",
16959 facet->value, NULL);
16960 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016961 }
16962 break;
16963 case XML_SCHEMA_FACET_TOTALDIGITS:
16964 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16965 case XML_SCHEMA_FACET_LENGTH:
16966 case XML_SCHEMA_FACET_MAXLENGTH:
16967 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016968 ret = xmlSchemaValidatePredefinedType(
16969 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
16970 facet->value, &(facet->val));
16971 if (ret != 0) {
16972 if (ret < 0) {
16973 /* No error message for RelaxNG. */
16974 if (ctxtGiven) {
16975 PERROR_INT("xmlSchemaCheckFacet",
16976 "validating facet value");
16977 }
16978 goto internal_error;
16979 }
16980 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16981 /* No error message for RelaxNG. */
16982 if (ctxtGiven) {
16983 /* error code */
16984 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16985 ret, facet->node, typeDecl,
16986 "The value '%s' of the facet '%s' is not a valid "
16987 "'nonNegativeInteger'",
16988 facet->value,
16989 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016990 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016991 }
16992 break;
16993 }
16994 case XML_SCHEMA_FACET_WHITESPACE:{
16995 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16996 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16997 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16998 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16999 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
17000 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
17001 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017002 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
17003 /* No error message for RelaxNG. */
17004 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017005 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017006 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17007 ret, facet->node, typeDecl,
17008 "The value '%s' of the facet 'whitespace' is not "
17009 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017010 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017011 }
17012 }
17013 default:
17014 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000017015 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017016exit:
17017 if ((! ctxtGiven) && (pctxt != NULL))
17018 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017019 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017020internal_error:
17021 if ((! ctxtGiven) && (pctxt != NULL))
17022 xmlSchemaFreeParserCtxt(pctxt);
17023 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000017024}
17025
17026/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017027 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000017028 * @typeDecl: the schema type definition
17029 * @ctxt: the schema parser context
17030 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017031 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000017032 */
17033static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017034xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
17035 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000017036{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017037 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000017038 /*
17039 * NOTE: It is intended to use the facets list, instead
17040 * of facetSet.
17041 */
17042 if (typeDecl->facets != NULL) {
17043 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017044
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017045 /*
17046 * Temporarily assign the "schema" to the validation context
17047 * of the parser context. This is needed for NOTATION validation.
17048 */
17049 if (ctxt->vctxt == NULL) {
17050 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
17051 return;
17052 }
17053 ctxt->vctxt->schema = ctxt->schema;
17054
Daniel Veillard01fa6152004-06-29 17:04:39 +000017055 while (facet != NULL) {
17056 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
17057 facet = facet->next;
17058 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017059
17060 ctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017061 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017062}
17063
17064/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017065 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017066 * @ctxtMGroup: the searched model group
17067 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017068 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017069 *
17070 * This one is intended to be used by
17071 * xmlSchemaCheckGroupDefCircular only.
17072 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017073 * Returns the particle with the circular model group definition reference,
17074 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017075 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017076static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017077xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017078 xmlSchemaTreeItemPtr particle)
17079{
17080 xmlSchemaTreeItemPtr circ = NULL;
17081 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017082 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017083
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017084 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017085 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017086 if (term == NULL)
17087 continue;
17088 switch (term->type) {
17089 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017090 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017091 if (gdef == groupDef)
17092 return (particle);
17093 /*
17094 * Mark this model group definition to avoid infinite
17095 * recursion on circular references not yet examined.
17096 */
17097 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
17098 continue;
17099 if (gdef->children != NULL) {
17100 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
17101 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
17102 gdef->children->children);
17103 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
17104 if (circ != NULL)
17105 return (circ);
17106 }
17107 break;
17108 case XML_SCHEMA_TYPE_SEQUENCE:
17109 case XML_SCHEMA_TYPE_CHOICE:
17110 case XML_SCHEMA_TYPE_ALL:
17111 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
17112 if (circ != NULL)
17113 return (circ);
17114 break;
17115 default:
17116 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017117 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017118 }
17119 return (NULL);
17120}
17121
17122/**
17123 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017124 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017125 * @ctxt: the parser context
17126 * @name: the name
17127 *
17128 * Checks for circular references to model group definitions.
17129 */
17130static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017131xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017132 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017133 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017134{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017135 /*
17136 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017137 * 2 Circular groups are disallowed. That is, within the {particles}
17138 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017139 * is the group itself.
17140 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017141 if ((item == NULL) ||
17142 (item->type != XML_SCHEMA_TYPE_GROUP) ||
17143 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017144 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017145 {
17146 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017147
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017148 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017149 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017150 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017151 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017152 * TODO: The error report is not adequate: this constraint
17153 * is defined for model groups but not definitions, but since
17154 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017155 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017156 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017157 */
17158 xmlSchemaPCustomErr(ctxt,
17159 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017160 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017161 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017162 "defined", xmlSchemaFormatQName(&str,
17163 item->targetNamespace, item->name));
17164 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017165 /*
17166 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017167 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017168 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017169 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017170 }
17171 }
17172}
17173
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017174/**
17175 * xmlSchemaGroupDefTermFixup:
17176 * @item: the particle with a model group definition as term
17177 * @ctxt: the parser context
17178 * @name: the name
17179 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017180 * Checks cos-all-limited.
17181 *
17182 * Assigns the model group of model group definitions to the "term"
17183 * of the referencing particle.
17184 * In xmlSchemaMiscRefFixup the model group definitions was assigned
17185 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017186 */
17187static void
17188xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017189 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017190 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017191{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017192 if ((item == NULL) ||
17193 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
17194 (item->children == NULL) ||
17195 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
17196 (item->children->children == NULL))
17197 return;
17198 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017199 /*
17200 * TODO: Not nice, but we will anchor cos-all-limited here.
17201 */
17202 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
17203 (item->maxOccurs != 1)) {
17204 /*
17205 * SPEC (1.2) "the {term} property of a particle with
17206 * {max occurs}=1which is part of a pair which constitutes the
17207 * {content type} of a complex type definition."
17208 */
17209 xmlSchemaPCustomErr(ctxt,
17210 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
17211 NULL, (xmlSchemaTypePtr) item, item->node,
17212 "The particle's 'maxOccurs' must be 1, since an xs:all model "
17213 "group is its term", NULL);
17214 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017215}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017216
17217/**
17218 * xmlSchemaGetCircAttrGrRef:
17219 * @ctxtGr: the searched attribute group
17220 * @attr: the current attribute list to be processed
17221 *
17222 * This one is intended to be used by
17223 * xmlSchemaCheckSRCAttributeGroupCircular only.
17224 *
17225 * Returns the circular attribute grou reference, otherwise NULL.
17226 */
17227static xmlSchemaAttributeGroupPtr
17228xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
17229 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017230{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017231 xmlSchemaAttributeGroupPtr circ = NULL, gr;
17232 int marked;
17233 /*
17234 * We will search for an attribute group reference which
17235 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017236 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017237 while (attr != NULL) {
17238 marked = 0;
17239 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
17240 gr = (xmlSchemaAttributeGroupPtr) attr;
17241 if (gr->refItem != NULL) {
17242 if (gr->refItem == ctxtGr)
17243 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017244 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017245 XML_SCHEMAS_ATTRGROUP_MARKED) {
17246 attr = attr->next;
17247 continue;
17248 } else {
17249 /*
17250 * Mark as visited to avoid infinite recursion on
17251 * circular references not yet examined.
17252 */
17253 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
17254 marked = 1;
17255 }
17256 }
17257 if (gr->attributes != NULL)
17258 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
17259 /*
17260 * Unmark the visited group's attributes.
17261 */
17262 if (marked)
17263 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
17264 if (circ != NULL)
17265 return (circ);
17266 }
17267 attr = attr->next;
17268 }
17269 return (NULL);
17270}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017271
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017272/**
17273 * xmlSchemaCheckSRCAttributeGroupCircular:
17274 * attrGr: the attribute group definition
17275 * @ctxt: the parser context
17276 * @name: the name
17277 *
17278 * Checks for circular references of attribute groups.
17279 */
17280static void
17281xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017282 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017283 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017284{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017285 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017286 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017287 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017288 * 3 Circular group reference is disallowed outside <redefine>.
17289 * That is, unless this element information item's parent is
17290 * <redefine>, then among the [children], if any, there must
17291 * not be an <attributeGroup> with ref [attribute] which resolves
17292 * to the component corresponding to this <attributeGroup>. Indirect
17293 * circularity is also ruled out. That is, when QName resolution
17294 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
17295 * any <attributeGroup>s with a ref [attribute] among the [children],
17296 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017297 * which resolves to the component corresponding to this <attributeGroup>.
17298 */
17299 /*
17300 * Only global components can be referenced.
17301 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017302 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017303 (attrGr->attributes == NULL))
17304 return;
17305 else {
17306 xmlSchemaAttributeGroupPtr circ;
17307
17308 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
17309 if (circ != NULL) {
17310 /*
17311 * TODO: Report the referenced attr group as QName.
17312 */
17313 xmlSchemaPCustomErr(ctxt,
17314 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
17315 NULL, NULL, circ->node,
17316 "Circular reference to the attribute group '%s' "
17317 "defined", attrGr->name);
17318 /*
17319 * NOTE: We will cut the reference to avoid further
17320 * confusion of the processor.
17321 * BADSPEC: The spec should define how to process in this case.
17322 */
17323 circ->attributes = NULL;
17324 circ->refItem = NULL;
17325 }
17326 }
17327}
17328
17329/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000017330 * xmlSchemaAttrGrpFixup:
17331 * @attrgrpDecl: the schema attribute definition
17332 * @ctxt: the schema parser context
17333 * @name: the attribute name
17334 *
17335 * Fixes finish doing the computations on the attributes definitions
17336 */
17337static void
Daniel Veillard3646d642004-06-02 19:19:14 +000017338xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017339 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000017340{
17341 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000017342 name = attrgrp->name;
17343 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017344 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000017345 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017346 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000017347
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017348 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017349 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017350 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017351 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017352 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017353 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
17354 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017355 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017356 return;
17357 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017358 attrgrp->refItem = ref;
17359 /*
17360 * Check for self reference!
17361 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017362 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000017363 attrgrp->attributes = ref->attributes;
17364 attrgrp->attributeWildcard = ref->attributeWildcard;
17365 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000017366}
17367
17368/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017369 * xmlSchemaAttrCheckValConstr:
17370 * @item: an schema attribute declaration/use
17371 * @ctxt: a schema parser context
17372 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017373 *
17374 *
17375 * Schema Component Constraint: Attribute Declaration Properties Correct
17376 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017377 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000017378 *
17379 * Fixes finish doing the computations on the attributes definitions
17380 */
17381static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017382xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017383 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017384 const xmlChar * name ATTRIBUTE_UNUSED)
17385{
17386
17387 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017388 * 2 if there is a {value constraint}, the canonical lexical
17389 * representation of its value must be ·valid· with respect
17390 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017391 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017392 if (item->defValue != NULL) {
17393 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017394
17395 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017396 PERROR_INT("xmlSchemaCheckAttrValConstr",
17397 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017398 return;
17399 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017400 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
17401 item->node, item->subtypes, item->defValue, &(item->defVal),
17402 1, 1, 0);
17403 if (ret != 0) {
17404 if (ret < 0) {
17405 PERROR_INT("xmlSchemaAttrCheckValConstr",
17406 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017407 return;
17408 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017409 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
17410 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17411 ret, item->node, (xmlSchemaTypePtr) item,
17412 "The value of the value constraint is not valid", NULL, NULL);
17413 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017414 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017415 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017416}
17417
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017418static xmlSchemaElementPtr
17419xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17420 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017421{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017422 xmlSchemaElementPtr ret;
17423
17424 if (SUBST_GROUP_AFF(ancestor) == NULL)
17425 return (NULL);
17426 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17427 return (ancestor);
17428
17429 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17430 return (NULL);
17431 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17432 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17433 SUBST_GROUP_AFF(ancestor));
17434 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17435
17436 return (ret);
17437}
17438
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017439/**
17440 * xmlSchemaCheckElemPropsCorrect:
17441 * @ctxt: a schema parser context
17442 * @decl: the element declaration
17443 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017444 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017445 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017446 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017447 *
17448 * STATUS:
17449 * missing: (6)
17450 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017451static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017452xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17453 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017454{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017455 int ret = 0;
17456 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017457 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017458 * SPEC (1) "The values of the properties of an element declaration
17459 * must be as described in the property tableau in The Element
17460 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17461 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017462 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017463 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017464 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017465
17466 xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017467 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017468 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017469 * affiliation}, then {scope} must be global."
17470 */
17471 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17472 xmlSchemaPCustomErr(pctxt,
17473 XML_SCHEMAP_E_PROPS_CORRECT_3,
17474 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17475 "Only global element declarations can have a "
17476 "substitution group affiliation", NULL);
17477 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017478 }
17479 /*
17480 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17481 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017482 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017483 * property."
17484 */
17485 if (head == elemDecl)
17486 circ = head;
17487 else if (SUBST_GROUP_AFF(head) != NULL)
17488 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17489 else
17490 circ = NULL;
17491 if (circ != NULL) {
17492 xmlChar *strA = NULL, *strB = NULL;
17493
17494 xmlSchemaPCustomErrExt(pctxt,
17495 XML_SCHEMAP_E_PROPS_CORRECT_6,
17496 NULL, (xmlSchemaTypePtr) circ, circ->node,
17497 "The element declaration '%s' defines a circular "
17498 "substitution group to element declaration '%s'",
17499 xmlSchemaGetComponentQName(&strA, circ),
17500 xmlSchemaGetComponentQName(&strB, head),
17501 NULL);
17502 FREE_AND_NULL(strA)
17503 FREE_AND_NULL(strB)
17504 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17505 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017506 /*
17507 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017508 * the {type definition}
17509 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017510 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017511 * of the {substitution group exclusions} of the {substitution group
17512 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17513 * (if the {type definition} is complex) or as defined in
17514 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017515 * simple)."
17516 *
17517 * NOTE: {substitution group exclusions} means the values of the
17518 * attribute "final".
17519 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017520
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017521 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017522 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017523
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017524 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
17525 set |= SUBSET_EXTENSION;
17526 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
17527 set |= SUBSET_RESTRICTION;
17528
17529 if (xmlSchemaCheckCOSDerivedOK(typeDef,
17530 ELEM_TYPE(head), set) != 0) {
17531 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
17532
17533 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017534 xmlSchemaPCustomErrExt(pctxt,
17535 XML_SCHEMAP_E_PROPS_CORRECT_4,
17536 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017537 "The type definition '%s' was "
17538 "either rejected by the substitution group "
17539 "affiliation '%s', or not validly derived from its type "
17540 "definition '%s'",
17541 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017542 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017543 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017544 FREE_AND_NULL(strA)
17545 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017546 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017547 }
17548 }
17549 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017550 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017551 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017552 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017553 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017554 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017555 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017556 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017557 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017558 ((IS_SIMPLE_TYPE(typeDef) &&
17559 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017560 (IS_COMPLEX_TYPE(typeDef) &&
17561 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017562 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
17563 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017564
17565 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17566 xmlSchemaPCustomErr(pctxt,
17567 XML_SCHEMAP_E_PROPS_CORRECT_5,
17568 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17569 "The type definition (or type definition's content type) is or "
17570 "is derived from ID; value constraints are not allowed in "
17571 "conjunction with such a type definition", NULL);
17572 } else if (elemDecl->value != NULL) {
17573 int vcret;
17574 xmlNodePtr node = NULL;
17575
17576 /*
17577 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17578 * representation of its value must be ·valid· with respect to the
17579 * {type definition} as defined in Element Default Valid (Immediate)
17580 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017581 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017582 if (typeDef == NULL) {
17583 xmlSchemaPErr(pctxt, elemDecl->node,
17584 XML_SCHEMAP_INTERNAL,
17585 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17586 "type is missing... skipping validation of "
17587 "the value constraint", NULL, NULL);
17588 return (-1);
17589 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017590 if (elemDecl->node != NULL) {
17591 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17592 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17593 BAD_CAST "fixed");
17594 else
17595 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17596 BAD_CAST "default");
17597 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017598 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
17599 typeDef, elemDecl->value, &(elemDecl->defVal));
17600 if (vcret != 0) {
17601 if (vcret < 0) {
17602 PERROR_INT("xmlSchemaElemCheckValConstr",
17603 "failed to validate the value constraint of an "
17604 "element declaration");
17605 return (-1);
17606 }
17607 return (vcret);
17608 }
17609 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017610
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017611 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017612}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017613
17614/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017615 * xmlSchemaCheckElemSubstGroup:
17616 * @ctxt: a schema parser context
17617 * @decl: the element declaration
17618 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017619 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017620 * Schema Component Constraint:
17621 * Substitution Group (cos-equiv-class)
17622 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017623 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017624 * a list will be built for each subst. group head, holding all direct
17625 * referents to this head.
17626 * NOTE that this function needs:
17627 * 1. circular subst. groups to be checked beforehand
17628 * 2. the declaration's type to be derived from the head's type
17629 *
17630 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017631 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017632 */
17633static void
17634xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17635 xmlSchemaElementPtr elemDecl)
17636{
17637 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17638 /* SPEC (1) "Its {abstract} is false." */
17639 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17640 return;
17641 {
17642 xmlSchemaElementPtr head;
17643 xmlSchemaTypePtr headType, type;
17644 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017645 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017646 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17647 * {disallowed substitutions} as the blocking constraint, as defined in
17648 * Substitution Group OK (Transitive) (§3.3.6)."
17649 */
17650 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17651 head = SUBST_GROUP_AFF(head)) {
17652 set = 0;
17653 methSet = 0;
17654 /*
17655 * The blocking constraints.
17656 */
17657 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17658 continue;
17659 headType = head->subtypes;
17660 type = elemDecl->subtypes;
17661 if (headType == type)
17662 goto add_member;
17663 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17664 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17665 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17666 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17667 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017668 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017669 * "The set of all {derivation method}s involved in the
17670 * derivation of D's {type definition} from C's {type definition}
17671 * does not intersect with the union of the blocking constraint,
17672 * C's {prohibited substitutions} (if C is complex, otherwise the
17673 * empty set) and the {prohibited substitutions} (respectively the
17674 * empty set) of any intermediate {type definition}s in the
17675 * derivation of D's {type definition} from C's {type definition}."
17676 */
17677 /*
17678 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17679 * subst.head axis, the methSet does not need to be computed for
17680 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017681 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017682 /*
17683 * The set of all {derivation method}s involved in the derivation
17684 */
17685 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017686 if ((type->flags &
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017687 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17688 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17689 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017690
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017691 if ((type->flags &
17692 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17693 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17694 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17695
17696 type = type->baseType;
17697 }
17698 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017699 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017700 * the head's type.
17701 */
17702 type = elemDecl->subtypes->baseType;
17703 while (type != NULL) {
17704 if (IS_COMPLEX_TYPE(type)) {
17705 if ((type->flags &
17706 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17707 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17708 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17709 if ((type->flags &
17710 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17711 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17712 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17713 } else
17714 break;
17715 if (type == headType)
17716 break;
17717 type = type->baseType;
17718 }
17719 if ((set != 0) &&
17720 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17721 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17722 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17723 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17724 continue;
17725 }
17726add_member:
17727 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17728 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17729 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17730 }
17731 }
17732}
17733
17734/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017735 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017736 * @item: an schema element declaration/particle
17737 * @ctxt: a schema parser context
17738 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017739 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017740 * Validates the value constraints of an element declaration.
17741 *
17742 * Fixes finish doing the computations on the element declarations.
17743 */
17744static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017745xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017746 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017747 const xmlChar * name ATTRIBUTE_UNUSED)
17748{
17749 if (elemDecl == NULL)
17750 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017751 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
17752 return;
17753 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017754 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17755 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017756}
17757
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017758/**
17759 * xmlSchemaMiscRefFixup:
17760 * @item: an schema component
17761 * @ctxt: a schema parser context
17762 * @name: the internal name of the component
17763 *
17764 * Resolves references of misc. schema components.
17765 */
17766static void
17767xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017768 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017769 const xmlChar * name ATTRIBUTE_UNUSED)
17770{
17771 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017772 if ((item->children != NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017773 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17774 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17775 xmlSchemaTreeItemPtr refItem;
17776 /*
17777 * Resolve the reference.
17778 */
17779 item->children = NULL;
17780 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17781 ref->itemType, ref->name, ref->targetNamespace);
17782 if (refItem == NULL) {
17783 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017784 NULL, GET_NODE(item), "ref", ref->name,
17785 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017786 } else {
17787 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17788 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017789 * NOTE that we will assign the model group definition
17790 * itself to the "term" of the particle. This will ease
17791 * the check for circular model group definitions. After
17792 * that the "term" will be assigned the model group of the
17793 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017794 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017795 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017796 } else
17797 item->children = refItem;
17798 }
17799 }
17800 }
17801}
17802
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017803static int
17804xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
17805 xmlSchemaValPtr y)
17806{
17807 xmlSchemaTypePtr tx, ty, ptx, pty;
17808 int ret;
17809
17810 while (x != NULL) {
17811 /* Same types. */
17812 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
17813 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
17814 ptx = xmlSchemaGetPrimitiveType(tx);
17815 pty = xmlSchemaGetPrimitiveType(ty);
17816 /*
17817 * (1) if a datatype T' is ·derived· by ·restriction· from an
17818 * atomic datatype T then the ·value space· of T' is a subset of
17819 * the ·value space· of T. */
17820 /*
17821 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
17822 * from a common atomic ancestor T then the ·value space·s of T'
17823 * and T'' may overlap.
17824 */
17825 if (ptx != pty)
17826 return(0);
17827 /*
17828 * We assume computed values to be normalized, so do a fast
17829 * string comparison for string based types.
17830 */
17831 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
17832 IS_ANY_SIMPLE_TYPE(ptx)) {
17833 if (! xmlStrEqual(
17834 xmlSchemaValueGetAsString(x),
17835 xmlSchemaValueGetAsString(y)))
17836 return (0);
17837 } else {
17838 ret = xmlSchemaCompareValuesWhtsp(
17839 x, XML_SCHEMA_WHITESPACE_PRESERVE,
17840 y, XML_SCHEMA_WHITESPACE_PRESERVE);
17841 if (ret == -2)
17842 return(-1);
17843 if (ret != 0)
17844 return(0);
17845 }
17846 /*
17847 * Lists.
17848 */
17849 x = xmlSchemaValueGetNext(x);
17850 if (x != NULL) {
17851 y = xmlSchemaValueGetNext(y);
17852 if (y == NULL)
17853 return (0);
17854 } else if (xmlSchemaValueGetNext(y) != NULL)
17855 return (0);
17856 else
17857 return (1);
17858 }
17859 return (0);
17860}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017861
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017862/**
17863 * xmlSchemaAttrFixup:
17864 * @item: an schema attribute declaration/use.
17865 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017866 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017867 *
17868 * Fixes finish doing the computations on attribute declarations/uses.
17869 */
17870static void
17871xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017872 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017873 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017874{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017875 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017876 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017877 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017878 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017879 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017880 * The simple type definition corresponding to the <simpleType> element
17881 * information item in the [children], if present, otherwise the simple
17882 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000017883 * [attribute], if present, otherwise the ·simple ur-type definition·.
17884 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017885 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017886 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017887 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17888 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017889 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017890 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017891 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017892
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017893 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17894 item->typeNs);
17895 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017896 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017897 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017898 (xmlSchemaTypePtr) item, item->node,
17899 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017900 XML_SCHEMA_TYPE_SIMPLE, NULL);
17901 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017902 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017903
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017904 } else if (item->ref != NULL) {
17905 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017906
Daniel Veillardc0826a72004-08-10 14:17:33 +000017907 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017908 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017909 * attribute declaration.
17910 */
17911 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017912 * TODO: Evaluate, what errors could occur if the declaration is not
17913 * found. It might be possible that the "typefixup" might crash if
17914 * no ref declaration was found.
17915 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017916 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017917 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017918 xmlSchemaPResCompAttrErr(ctxt,
17919 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017920 (xmlSchemaTypePtr) item, item->node,
17921 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017922 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017923 return;
17924 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017925 item->refDecl = decl;
17926 xmlSchemaAttrFixup(decl, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017927 item->subtypes = decl->subtypes;
17928 /*
17929 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017930 * au-props-correct.2: If the {attribute declaration} has a fixed
17931 * {value constraint}, then if the attribute use itself has a
17932 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017933 * that of the {attribute declaration}'s {value constraint}.
17934 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017935 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017936 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017937 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017938 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017939 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17940 NULL, NULL, item->node,
17941 "The attribute declaration has a 'fixed' value constraint "
17942 ", thus it must be 'fixed' in attribute use as well",
17943 NULL);
17944 } else {
17945 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
17946 xmlSchemaPCustomErr(ctxt,
17947 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17948 NULL, NULL, item->node,
17949 "The 'fixed' value constraint of the attribute use "
17950 "must match the attribute declaration's value "
17951 "constraint '%s'",
17952 decl->defValue);
17953 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017954 }
17955 /*
17956 * FUTURE: One should change the values of the attr. use
17957 * if ever validation should be attempted even if the
17958 * schema itself was not fully valid.
17959 */
17960 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017961 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017962 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17963 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017964}
17965
17966/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017967 * xmlSchemaResolveIDCKeyRef:
17968 * @idc: the identity-constraint definition
17969 * @ctxt: the schema parser context
17970 * @name: the attribute name
17971 *
17972 * Resolve keyRef references to key/unique IDCs.
17973 */
17974static void
17975xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017976 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017977 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017978{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017979 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17980 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017981 if (idc->ref->name != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017982 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017983 pctxt->schema->idcDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017984 idc->ref->name,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017985 idc->ref->targetNamespace);
17986 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017987 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017988 * TODO: It is actually not an error to fail to resolve.
17989 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017990 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017991 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017992 (xmlSchemaTypePtr) idc, idc->node,
17993 "refer", idc->ref->name,
17994 idc->ref->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017995 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17996 return;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017997 } else {
17998 if (idc->nbFields !=
17999 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
18000 xmlChar *str = NULL;
18001 xmlSchemaIDCPtr refer;
18002
18003 refer = (xmlSchemaIDCPtr) idc->ref->item;
18004 /*
18005 * SPEC c-props-correct(2)
18006 * "If the {identity-constraint category} is keyref,
18007 * the cardinality of the {fields} must equal that of
18008 * the {fields} of the {referenced key}.
18009 */
18010 xmlSchemaPCustomErr(pctxt,
18011 XML_SCHEMAP_C_PROPS_CORRECT,
18012 NULL, (xmlSchemaTypePtr) idc, idc->node,
18013 "The cardinality of the keyref differs from the "
18014 "cardinality of the referenced key '%s'",
18015 xmlSchemaFormatQName(&str, refer->targetNamespace,
18016 refer->name)
18017 );
18018 FREE_AND_NULL(str)
18019 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018020 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018021 }
18022}
18023
18024/**
Daniel Veillard4255d502002-04-16 15:50:10 +000018025 * xmlSchemaParse:
18026 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000018027 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000018028 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000018029 * XML Shema struture which can be used to validate instances.
18030 * *WARNING* this interface is highly subject to change
18031 *
18032 * Returns the internal XML Schema structure built from the resource or
18033 * NULL in case of error
18034 */
18035xmlSchemaPtr
18036xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
18037{
18038 xmlSchemaPtr ret = NULL;
18039 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000018040 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000018041 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000018042
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018043 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018044 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018045 * the API; i.e. not automatically by the validated instance document.
18046 */
18047
Daniel Veillard4255d502002-04-16 15:50:10 +000018048 xmlSchemaInitTypes();
18049
Daniel Veillard6045c902002-10-09 21:13:59 +000018050 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000018051 return (NULL);
18052
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000018053 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000018054 ctxt->counter = 0;
18055 ctxt->container = NULL;
18056
18057 /*
18058 * First step is to parse the input document into an DOM/Infoset
18059 */
Daniel Veillard6045c902002-10-09 21:13:59 +000018060 if (ctxt->URL != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018061 doc = xmlReadFile((const char *) ctxt->URL, NULL,
Daniel Veillardbd2904b2003-11-25 15:38:59 +000018062 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018063 if (doc == NULL) {
18064 xmlSchemaPErr(ctxt, NULL,
18065 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018066 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018067 ctxt->URL, NULL);
18068 return (NULL);
18069 }
Daniel Veillard6045c902002-10-09 21:13:59 +000018070 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000018071 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
18072 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018073 if (doc == NULL) {
18074 xmlSchemaPErr(ctxt, NULL,
18075 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018076 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018077 NULL, NULL);
18078 return (NULL);
18079 }
18080 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000018081 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000018082 } else if (ctxt->doc != NULL) {
18083 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000018084 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000018085 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018086 xmlSchemaPErr(ctxt, NULL,
18087 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018088 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018089 NULL, NULL);
18090 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000018091 }
18092
18093 /*
18094 * Then extract the root and Schema parse it
18095 */
18096 root = xmlDocGetRootElement(doc);
18097 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018098 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
18099 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018100 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000018101 if (!preserve) {
18102 xmlFreeDoc(doc);
18103 }
Daniel Veillard4255d502002-04-16 15:50:10 +000018104 return (NULL);
18105 }
18106
18107 /*
18108 * Remove all the blank text nodes
18109 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000018110 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000018111
18112 /*
18113 * Then do the parsing for good
18114 */
18115 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000018116 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000018117 if (!preserve) {
18118 xmlFreeDoc(doc);
18119 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018120 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000018121 }
Daniel Veillard4255d502002-04-16 15:50:10 +000018122 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000018123 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000018124 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018125 ctxt->ctxtType = NULL;
18126 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018127
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018128 /*
18129 * Resolve base types of simple/complex types.
18130 */
18131 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018132
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018133 if (ctxt->nberrors != 0)
18134 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018135
18136 if (ret->volatiles != NULL) {
18137 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
18138 int i;
18139 xmlSchemaTreeItemPtr item;
18140
18141 for (i = 0; i < list->nbItems; i++) {
18142 item = (xmlSchemaTreeItemPtr) list->items[i];
18143 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
18144 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018145 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018146 }
Daniel Veillard4255d502002-04-16 15:50:10 +000018147 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000018148 * Then fixup all attributes declarations
18149 */
18150 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000018151 /*
18152 * Then fixup all attributes group declarations
18153 */
18154 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
18155 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000018156 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018157 * Resolve identity-constraint keyRefs.
18158 */
18159 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018160 /*
18161 * Check type defnitions for circular references.
18162 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018163 xmlHashScan(ret->typeDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018164 xmlSchemaCheckTypeDefCircular, ctxt);
18165 /*
18166 * Check model groups defnitions for circular references.
18167 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018168 xmlHashScan(ret->groupDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018169 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018170 /*
18171 * Set the "term" of particles pointing to model group definitions
18172 * to the contained model group.
18173 */
18174 if (ret->volatiles != NULL) {
18175 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
18176 int i;
18177 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018178
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018179 for (i = 0; i < list->nbItems; i++) {
18180 item = (xmlSchemaParticlePtr) list->items[i];
18181 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
18182 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
18183 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018184 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018185 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018186 * Check attribute groups for circular references.
18187 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018188 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
18189 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018190 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000018191 * Then fix references of element declaration; apply constraints.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018192 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018193 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018194 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000018195 /*
18196 * We will stop here if the schema was not valid to avoid internal errors
18197 * on missing sub-components. This is not conforming to the spec, since it
18198 * allows missing components, but it might make further processing crash.
18199 * So see it as a very strict handling, which might be made more lax in the
18200 * future.
18201 */
18202 if (ctxt->nberrors != 0)
18203 goto exit;
18204 /*
18205 * Then fixup all types properties
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018206 */
18207 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018208 /*
18209 * Validate the value constraint of attribute declarations/uses.
18210 */
18211 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018212 /*
18213 * Validate the value constraint of element declarations.
18214 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018215 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018216
18217 if (ctxt->nberrors != 0)
18218 goto exit;
18219
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018220 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018221 * TODO: cos-element-consistent, cos-all-limited
18222 *
18223 * Then build the content model for all complex types
18224 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018225 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018226 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018227
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000018228exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000018229 if (ctxt->nberrors != 0) {
18230 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018231 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000018232 }
Daniel Veillard4255d502002-04-16 15:50:10 +000018233 return (ret);
18234}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018235
Daniel Veillard4255d502002-04-16 15:50:10 +000018236/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000018237 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000018238 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000018239 * @err: the error callback
18240 * @warn: the warning callback
18241 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000018242 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000018243 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000018244 */
18245void
18246xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018247 xmlSchemaValidityErrorFunc err,
18248 xmlSchemaValidityWarningFunc warn, void *ctx)
18249{
Daniel Veillard4255d502002-04-16 15:50:10 +000018250 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018251 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000018252 ctxt->error = err;
18253 ctxt->warning = warn;
18254 ctxt->userData = ctx;
18255}
18256
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018257/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000018258 * xmlSchemaGetParserErrors:
18259 * @ctxt: a XMl-Schema parser context
18260 * @err: the error callback result
18261 * @warn: the warning callback result
18262 * @ctx: contextual data for the callbacks result
18263 *
18264 * Get the callback information used to handle errors for a parser context
18265 *
18266 * Returns -1 in case of failure, 0 otherwise
18267 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018268int
Daniel Veillard259f0df2004-08-18 09:13:18 +000018269xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
18270 xmlSchemaValidityErrorFunc * err,
18271 xmlSchemaValidityWarningFunc * warn, void **ctx)
18272{
18273 if (ctxt == NULL)
18274 return(-1);
18275 if (err != NULL)
18276 *err = ctxt->error;
18277 if (warn != NULL)
18278 *warn = ctxt->warning;
18279 if (ctx != NULL)
18280 *ctx = ctxt->userData;
18281 return(0);
18282}
18283
18284/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018285 * xmlSchemaFacetTypeToString:
18286 * @type: the facet type
18287 *
18288 * Convert the xmlSchemaTypeType to a char string.
18289 *
18290 * Returns the char string representation of the facet type if the
18291 * type is a facet and an "Internal Error" string otherwise.
18292 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018293static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018294xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
18295{
18296 switch (type) {
18297 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018298 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018299 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018300 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018301 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018302 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018303 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018304 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018305 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018306 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018307 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018308 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018309 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018310 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018311 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018312 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018313 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018314 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018315 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018316 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018317 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018318 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018319 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018320 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018321 default:
18322 break;
18323 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018324 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018325}
18326
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018327static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000018328xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
18329{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018330 /*
18331 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000018332 * from xsd:string.
18333 */
18334 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018335 /*
18336 * Note that we assume a whitespace of preserve for anySimpleType.
18337 */
18338 if ((type->builtInType == XML_SCHEMAS_STRING) ||
18339 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
18340 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000018341 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018342 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018343 else {
18344 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018345 * For all ·atomic· datatypes other than string (and types ·derived·
18346 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000018347 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018348 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018349 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018350 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018351 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018352 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018353 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018354 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018355 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018356 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
18357 } else if (VARIETY_UNION(type)) {
18358 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
18359 } else if (VARIETY_ATOMIC(type)) {
18360 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
18361 return (XML_SCHEMA_WHITESPACE_PRESERVE);
18362 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
18363 return (XML_SCHEMA_WHITESPACE_REPLACE);
18364 else
18365 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018366 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018367 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018368}
18369
Daniel Veillard4255d502002-04-16 15:50:10 +000018370/************************************************************************
18371 * *
18372 * Simple type validation *
18373 * *
18374 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000018375
Daniel Veillard4255d502002-04-16 15:50:10 +000018376
18377/************************************************************************
18378 * *
18379 * DOM Validation code *
18380 * *
18381 ************************************************************************/
18382
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018383static void
18384xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
18385{
18386 int i, nbItems;
18387 xmlSchemaTypePtr item, *items;
18388
18389
18390 /*
18391 * During the Assemble of the schema ctxt->curItems has
18392 * been filled with the relevant new items. Fix those up.
18393 */
18394 nbItems = ctxt->assemble->nbItems;
18395 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018396
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018397 for (i = 0; i < nbItems; i++) {
18398 item = items[i];
18399 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018400 case XML_SCHEMA_TYPE_COMPLEX:
18401 case XML_SCHEMA_TYPE_SIMPLE:
18402 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
18403 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018404 case XML_SCHEMA_TYPE_ATTRIBUTE:
18405 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
18406 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018407 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018408 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018409 ctxt, NULL);
18410 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018411 case XML_SCHEMA_TYPE_PARTICLE:
18412 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018413 break;
18414 case XML_SCHEMA_TYPE_IDC_KEY:
18415 case XML_SCHEMA_TYPE_IDC_UNIQUE:
18416 case XML_SCHEMA_TYPE_IDC_KEYREF:
18417 xmlSchemaResolveIDCKeyRef((xmlSchemaIDCPtr) item, ctxt, NULL);
18418 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018419 default:
18420 break;
18421 }
18422 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018423 if (ctxt->nberrors != 0)
18424 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018425 /*
18426 * Circularity checks.
18427 */
18428 for (i = 0; i < nbItems; i++) {
18429 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018430 switch (item->type) {
18431 case XML_SCHEMA_TYPE_COMPLEX:
18432 case XML_SCHEMA_TYPE_SIMPLE:
18433 xmlSchemaCheckTypeDefCircular(
18434 (xmlSchemaTypePtr) item, ctxt, NULL);
18435 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018436 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018437 xmlSchemaCheckGroupDefCircular(
18438 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018439 break;
18440 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18441 xmlSchemaCheckAttributeGroupCircular(
18442 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18443 break;
18444 default:
18445 break;
18446 }
18447 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018448 if (ctxt->nberrors != 0)
18449 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018450 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018451 * Set the "term" of particles pointing to model group definitions
18452 * to the contained model group.
18453 */
18454 for (i = 0; i < nbItems; i++) {
18455 item = items[i];
18456 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18457 (((xmlSchemaParticlePtr) item)->children != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018458 (((xmlSchemaParticlePtr) item)->children->type ==
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018459 XML_SCHEMA_TYPE_GROUP)) {
18460 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18461 ctxt, NULL);
18462 }
18463 }
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018464 if (ctxt->nberrors != 0)
18465 return;
18466 for (i = 0; i < nbItems; i++) {
18467 item = items[i];
18468 switch (item->type) {
18469 case XML_SCHEMA_TYPE_ELEMENT:
18470 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
18471 NULL, NULL, NULL);
18472 break;
18473 default:
18474 break;
18475 }
18476 }
18477 if (ctxt->nberrors != 0)
18478 return;
18479
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018480 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018481 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018482 */
18483 for (i = 0; i < nbItems; i++) {
18484 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018485 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018486 case XML_SCHEMA_TYPE_SIMPLE:
18487 case XML_SCHEMA_TYPE_COMPLEX:
18488 xmlSchemaTypeFixup(item, ctxt, NULL);
18489 break;
18490 default:
18491 break;
18492 }
18493 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018494 if (ctxt->nberrors != 0)
18495 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018496 /*
18497 * Validate value contraint values.
18498 */
18499 for (i = 0; i < nbItems; i++) {
18500 item = items[i];
18501 switch (item->type) {
18502 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018503 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18504 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018505 break;
18506 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018507 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018508 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018509 break;
18510 default:
18511 break;
18512 }
18513 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018514 if (ctxt->nberrors != 0)
18515 return;
18516 /*
18517 * Build the content model for complex types.
18518 */
18519 for (i = 0; i < nbItems; i++) {
18520 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018521 switch (item->type) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018522 case XML_SCHEMA_TYPE_COMPLEX:
18523 xmlSchemaBuildContentModel(item, ctxt, NULL);
18524 break;
18525 default:
18526 break;
18527 }
18528 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018529}
18530
18531/**
18532 * xmlSchemaAssembleByLocation:
18533 * @pctxt: a schema parser context
18534 * @vctxt: a schema validation context
18535 * @schema: the existing schema
18536 * @node: the node that fired the assembling
18537 * @nsName: the namespace name of the new schema
18538 * @location: the location of the schema
18539 *
18540 * Expands an existing schema by an additional schema.
18541 *
18542 * Returns 0 if the new schema is correct, a positive error code
18543 * number otherwise and -1 in case of an internal or API error.
18544 */
18545static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018546xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018547 xmlSchemaPtr schema,
18548 xmlNodePtr node,
18549 const xmlChar *nsName,
18550 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018551{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018552 const xmlChar *targetNs, *oldtns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018553 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018554 int oldflags, ret = 0, oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018555 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018556 xmlSchemaParserCtxtPtr pctxt;
18557
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018558 /*
18559 * This should be used:
18560 * 1. on <import>(s)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018561 * 2. if requested by the validated instance
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018562 * 3. if requested via the API
18563 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018564 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018565 return (-1);
18566 /*
18567 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018568 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018569 if ((vctxt->pctxt == NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018570 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
18571 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018572 pctxt = vctxt->pctxt;
18573 /*
18574 * Set the counter to produce unique names for anonymous items.
18575 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018576 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018577 /*
18578 * Acquire the schema document.
18579 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018580 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
18581 node, nsName, location, &doc, &targetNs, 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018582 if (ret != 0) {
18583 if (doc != NULL)
18584 xmlFreeDoc(doc);
18585 } else if (doc != NULL) {
18586 docElem = xmlDocGetRootElement(doc);
18587 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018588 * Create new assemble info.
18589 */
18590 if (pctxt->assemble == NULL) {
18591 pctxt->assemble = xmlSchemaNewAssemble();
18592 if (pctxt->assemble == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018593 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018594 "Memory error: xmlSchemaAssembleByLocation, "
18595 "allocating assemble info", NULL);
18596 xmlFreeDoc(doc);
18597 return (-1);
18598 }
18599 }
18600 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018601 * Save and reset the context & schema.
18602 */
18603 oldflags = schema->flags;
18604 oldtns = schema->targetNamespace;
18605 olddoc = schema->doc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018606 oldIsS4S = vctxt->pctxt->isS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018607
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018608 xmlSchemaClearSchemaDefaults(schema);
18609 schema->targetNamespace = targetNs;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018610 if ((targetNs != NULL) &&
18611 xmlStrEqual(targetNs, xmlSchemaNs)) {
18612 /*
18613 * We are parsing the schema for schema!
18614 */
18615 vctxt->pctxt->isS4S = 1;
18616 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018617 /* schema->nbCurItems = 0; */
18618 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018619 pctxt->ctxtType = NULL;
18620 pctxt->parentItem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018621
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018622 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18623 if (pctxt->nberrors != 0) {
18624 vctxt->nberrors += pctxt->nberrors;
18625 goto finally;
18626 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018627 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018628 if (pctxt->nberrors != 0) {
18629 vctxt->nberrors += pctxt->nberrors;
18630 goto finally;
18631 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018632 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018633 if (pctxt->nberrors != 0)
18634 vctxt->nberrors += pctxt->nberrors;
18635finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018636 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018637 * Set the counter of items.
18638 */
18639 schema->counter = pctxt->counter;
18640 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018641 * Free the list of assembled components.
18642 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018643 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018644 /*
18645 * Restore the context & schema.
18646 */
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018647 vctxt->pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018648 schema->flags = oldflags;
18649 schema->targetNamespace = oldtns;
18650 schema->doc = olddoc;
18651 ret = pctxt->err;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018652 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018653 return (ret);
18654}
18655
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018656static xmlSchemaAttrInfoPtr
18657xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
18658 int metaType)
18659{
18660 if (vctxt->nbAttrInfos == 0)
18661 return (NULL);
18662 {
18663 int i;
18664 xmlSchemaAttrInfoPtr iattr;
18665
18666 for (i = 0; i < vctxt->nbAttrInfos; i++) {
18667 iattr = vctxt->attrInfos[i];
18668 if (iattr->metaType == metaType)
18669 return (iattr);
18670 }
18671
18672 }
18673 return (NULL);
18674}
18675
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018676/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018677 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018678 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018679 *
18680 * Expands an existing schema by an additional schema using
18681 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18682 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18683 * must be set to 1.
18684 *
18685 * Returns 0 if the new schema is correct, a positive error code
18686 * number otherwise and -1 in case of an internal or API error.
18687 */
18688static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018689xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018690{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018691 const xmlChar *cur, *end;
18692 const xmlChar *nsname = NULL, *location;
18693 int count = 0;
18694 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018695 xmlSchemaAttrInfoPtr iattr;
18696
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018697 /*
18698 * Parse the value; we will assume an even number of values
18699 * to be given (this is how Xerces and XSV work).
18700 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018701 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
18702 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
18703 if (iattr == NULL)
18704 xmlSchemaGetMetaAttrInfo(vctxt,
18705 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
18706 if (iattr == NULL)
18707 return (0);
18708 cur = iattr->value;
18709 do {
18710 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018711 /*
18712 * Get the namespace name.
18713 */
18714 while (IS_BLANK_CH(*cur))
18715 cur++;
18716 end = cur;
18717 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18718 end++;
18719 if (end == cur)
18720 break;
18721 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018722 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018723 cur = end;
18724 }
18725 /*
18726 * Get the URI.
18727 */
18728 while (IS_BLANK_CH(*cur))
18729 cur++;
18730 end = cur;
18731 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18732 end++;
18733 if (end == cur)
18734 break;
18735 count++;
18736 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018737 cur = end;
18738 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
18739 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018740 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018741 VERROR_INT("xmlSchemaAssembleByXSI",
18742 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018743 return (-1);
18744 }
18745 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018746 return (ret);
18747}
18748
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018749static const xmlChar *
18750xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
18751 const xmlChar *prefix)
18752{
18753 if (vctxt->sax != NULL) {
18754 int i, j;
18755 xmlSchemaNodeInfoPtr inode;
18756
18757 for (i = vctxt->depth; i >= 0; i--) {
18758 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
18759 inode = vctxt->elemInfos[i];
18760 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
18761 if (((prefix == NULL) &&
18762 (inode->nsBindings[j] == NULL)) ||
18763 ((prefix != NULL) && xmlStrEqual(prefix,
18764 inode->nsBindings[j]))) {
18765
18766 /*
18767 * Note that the namespace bindings are already
18768 * in a string dict.
18769 */
18770 return (inode->nsBindings[j+1]);
18771 }
18772 }
18773 }
18774 }
18775 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018776#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018777 } else if (vctxt->reader != NULL) {
18778 xmlChar *nsName;
18779
18780 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
18781 if (nsName != NULL) {
18782 const xmlChar *ret;
18783
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018784 ret = xmlDictLookup(vctxt->dict, nsName, -1);
18785 xmlFree(nsName);
18786 return (ret);
18787 } else
18788 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018789#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018790 } else {
18791 xmlNsPtr ns;
18792
18793 if ((vctxt->inode->node == NULL) ||
18794 (vctxt->inode->node->doc == NULL)) {
18795 VERROR_INT("xmlSchemaLookupNamespace",
18796 "no node or node's doc avaliable");
18797 return (NULL);
18798 }
18799 ns = xmlSearchNs(vctxt->inode->node->doc,
18800 vctxt->inode->node, prefix);
18801 if (ns != NULL)
18802 return (ns->href);
18803 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018804 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018805}
18806
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018807/*
18808* This one works on the schema of the validation context.
18809*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018810static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018811xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18812 xmlSchemaPtr schema,
18813 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018814 const xmlChar *value,
18815 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018816 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018817{
18818 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018819
18820 if (vctxt && (vctxt->schema == NULL)) {
18821 VERROR_INT("xmlSchemaValidateNotation",
18822 "a schema is needed on the validation context");
18823 return (-1);
18824 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018825 ret = xmlValidateQName(value, 1);
18826 if (ret != 0)
18827 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018828 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018829 xmlChar *localName = NULL;
18830 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018831
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018832 localName = xmlSplitQName2(value, &prefix);
18833 if (prefix != NULL) {
18834 const xmlChar *nsName = NULL;
18835
18836 if (vctxt != NULL)
18837 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
18838 else if (node != NULL) {
18839 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
18840 if (ns != NULL)
18841 nsName = ns->href;
18842 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018843 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018844 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018845 return (1);
18846 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018847 if (nsName == NULL) {
18848 xmlFree(prefix);
18849 xmlFree(localName);
18850 return (1);
18851 }
18852 if (xmlHashLookup2(schema->notaDecl, localName,
18853 nsName) != NULL) {
18854 if (valNeeded && (val != NULL)) {
18855 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
18856 BAD_CAST xmlStrdup(nsName));
18857 if (*val == NULL)
18858 ret = -1;
18859 }
18860 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018861 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018862 xmlFree(prefix);
18863 xmlFree(localName);
18864 } else {
18865 if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
18866 if (valNeeded && (val != NULL)) {
18867 (*val) = xmlSchemaNewNOTATIONValue(
18868 BAD_CAST xmlStrdup(value), NULL);
18869 if (*val == NULL)
18870 ret = -1;
18871 }
18872 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018873 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018874 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018875 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018876 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018877}
18878
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000018879static int
18880xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
18881 const xmlChar* lname,
18882 const xmlChar* nsname)
18883{
18884 int i;
18885
18886 lname = xmlDictLookup(vctxt->dict, lname, -1);
18887 if (lname == NULL)
18888 return(-1);
18889 if (nsname != NULL) {
18890 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
18891 if (nsname == NULL)
18892 return(-1);
18893 }
18894 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
18895 if ((vctxt->nodeQNames->items [i] == lname) &&
18896 (vctxt->nodeQNames->items[i +1] == nsname))
18897 /* Already there */
18898 return(i);
18899 }
18900 /* Add new entry. */
18901 i = vctxt->nodeQNames->nbItems;
18902 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
18903 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
18904 return(i);
18905}
18906
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018907/************************************************************************
18908 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018909 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018910 * *
18911 ************************************************************************/
18912
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018913/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018914 * xmlSchemaAugmentIDC:
18915 * @idcDef: the IDC definition
18916 *
18917 * Creates an augmented IDC definition item.
18918 *
18919 * Returns the item, or NULL on internal errors.
18920 */
18921static void
18922xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18923 xmlSchemaValidCtxtPtr vctxt)
18924{
18925 xmlSchemaIDCAugPtr aidc;
18926
18927 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18928 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018929 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018930 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18931 NULL);
18932 return;
18933 }
18934 aidc->bubbleDepth = -1;
18935 aidc->def = idcDef;
18936 aidc->next = NULL;
18937 if (vctxt->aidcs == NULL)
18938 vctxt->aidcs = aidc;
18939 else {
18940 aidc->next = vctxt->aidcs;
18941 vctxt->aidcs = aidc;
18942 }
18943}
18944
18945/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018946 * xmlSchemaIDCNewBinding:
18947 * @idcDef: the IDC definition of this binding
18948 *
18949 * Creates a new IDC binding.
18950 *
18951 * Returns the new binding in case of succeeded, NULL on internal errors.
18952 */
18953static xmlSchemaPSVIIDCBindingPtr
18954xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18955{
18956 xmlSchemaPSVIIDCBindingPtr ret;
18957
18958 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18959 sizeof(xmlSchemaPSVIIDCBinding));
18960 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018961 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018962 "allocating a PSVI IDC binding item", NULL);
18963 return (NULL);
18964 }
18965 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18966 ret->definition = idcDef;
18967 return (ret);
18968}
18969
18970/**
18971 * xmlSchemaIDCStoreNodeTableItem:
18972 * @vctxt: the WXS validation context
18973 * @item: the IDC node table item
18974 *
18975 * The validation context is used to store an IDC node table items.
18976 * They are stored to avoid copying them if IDC node-tables are merged
18977 * with corresponding parent IDC node-tables (bubbling).
18978 *
18979 * Returns 0 if succeeded, -1 on internal errors.
18980 */
18981static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018982xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018983 xmlSchemaPSVIIDCNodePtr item)
18984{
18985 /*
18986 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018987 */
18988 if (vctxt->idcNodes == NULL) {
18989 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018990 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18991 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018992 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018993 "allocating the IDC node table item list", NULL);
18994 return (-1);
18995 }
18996 vctxt->sizeIdcNodes = 20;
18997 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18998 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018999 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
19000 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019001 sizeof(xmlSchemaPSVIIDCNodePtr));
19002 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019003 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019004 "re-allocating the IDC node table item list", NULL);
19005 return (-1);
19006 }
19007 }
19008 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019009
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019010 return (0);
19011}
19012
19013/**
19014 * xmlSchemaIDCStoreKey:
19015 * @vctxt: the WXS validation context
19016 * @item: the IDC key
19017 *
19018 * The validation context is used to store an IDC key.
19019 *
19020 * Returns 0 if succeeded, -1 on internal errors.
19021 */
19022static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019023xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019024 xmlSchemaPSVIIDCKeyPtr key)
19025{
19026 /*
19027 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019028 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019029 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019030 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019031 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
19032 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019033 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019034 "allocating the IDC key storage list", NULL);
19035 return (-1);
19036 }
19037 vctxt->sizeIdcKeys = 40;
19038 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
19039 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019040 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
19041 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019042 sizeof(xmlSchemaPSVIIDCKeyPtr));
19043 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019044 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019045 "re-allocating the IDC key storage list", NULL);
19046 return (-1);
19047 }
19048 }
19049 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019050
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019051 return (0);
19052}
19053
19054/**
19055 * xmlSchemaIDCAppendNodeTableItem:
19056 * @bind: the IDC binding
19057 * @ntItem: the node-table item
19058 *
19059 * Appends the IDC node-table item to the binding.
19060 *
19061 * Returns 0 on success and -1 on internal errors.
19062 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019063static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019064xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
19065 xmlSchemaPSVIIDCNodePtr ntItem)
19066{
19067 if (bind->nodeTable == NULL) {
19068 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019069 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019070 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
19071 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019072 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019073 "allocating an array of IDC node-table items", NULL);
19074 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019075 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019076 } else if (bind->sizeNodes <= bind->nbNodes) {
19077 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019078 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19079 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019080 sizeof(xmlSchemaPSVIIDCNodePtr));
19081 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019082 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019083 "re-allocating an array of IDC node-table items", NULL);
19084 return(-1);
19085 }
19086 }
19087 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019088 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019089}
19090
19091/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019092 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019093 * @vctxt: the WXS validation context
19094 * @matcher: the IDC matcher
19095 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019096 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019097 * of the given matcher. If none found, a new one is created
19098 * and added to the IDC table.
19099 *
19100 * Returns an IDC binding or NULL on internal errors.
19101 */
19102static xmlSchemaPSVIIDCBindingPtr
19103xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
19104 xmlSchemaIDCMatcherPtr matcher)
19105{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019106 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019107
19108 info = vctxt->elemInfos[matcher->depth];
19109
19110 if (info->idcTable == NULL) {
19111 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
19112 if (info->idcTable == NULL)
19113 return (NULL);
19114 return(info->idcTable);
19115 } else {
19116 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019117
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019118 bind = info->idcTable;
19119 do {
19120 if (bind->definition == matcher->aidc->def)
19121 return(bind);
19122 if (bind->next == NULL) {
19123 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
19124 if (bind->next == NULL)
19125 return (NULL);
19126 return(bind->next);
19127 }
19128 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019129 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019130 }
19131 return (NULL);
19132}
19133
19134/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019135 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019136 * @key: the IDC key
19137 *
19138 * Frees an IDC key together with its compiled value.
19139 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019140static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019141xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
19142{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019143 if (key->val != NULL)
19144 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019145 xmlFree(key);
19146}
19147
19148/**
19149 * xmlSchemaIDCFreeBinding:
19150 *
19151 * Frees an IDC binding. Note that the node table-items
19152 * are not freed.
19153 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019154static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019155xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
19156{
19157 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019158 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19159 int i;
19160 /*
19161 * Node-table items for keyrefs are not stored globally
19162 * to the validation context, since they are not bubbled.
19163 * We need to free them here.
19164 */
19165 for (i = 0; i < bind->nbNodes; i++) {
19166 xmlFree(bind->nodeTable[i]->keys);
19167 xmlFree(bind->nodeTable[i]);
19168 }
19169 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019170 xmlFree(bind->nodeTable);
19171 }
19172 xmlFree(bind);
19173}
19174
19175/**
19176 * xmlSchemaIDCFreeIDCTable:
19177 * @bind: the first IDC binding in the list
19178 *
19179 * Frees an IDC table, i.e. all the IDC bindings in the list.
19180 */
19181static void
19182xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
19183{
19184 xmlSchemaPSVIIDCBindingPtr prev;
19185
19186 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019187 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019188 bind = bind->next;
19189 xmlSchemaIDCFreeBinding(prev);
19190 }
19191}
19192
19193/**
19194 * xmlSchemaIDCFreeMatcherList:
19195 * @matcher: the first IDC matcher in the list
19196 *
19197 * Frees a list of IDC matchers.
19198 */
19199static void
19200xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
19201{
19202 xmlSchemaIDCMatcherPtr next;
19203
19204 while (matcher != NULL) {
19205 next = matcher->next;
19206 if (matcher->keySeqs != NULL) {
19207 int i;
19208 for (i = 0; i < matcher->sizeKeySeqs; i++)
19209 if (matcher->keySeqs[i] != NULL)
19210 xmlFree(matcher->keySeqs[i]);
19211 xmlFree(matcher->keySeqs);
19212 }
19213 xmlFree(matcher);
19214 matcher = next;
19215 }
19216}
19217
19218/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019219 * xmlSchemaIDCAddStateObject:
19220 * @vctxt: the WXS validation context
19221 * @matcher: the IDC matcher
19222 * @sel: the XPath information
19223 * @parent: the parent "selector" state object if any
19224 * @type: "selector" or "field"
19225 *
19226 * Creates/reuses and activates state objects for the given
19227 * XPath information; if the XPath expression consists of unions,
19228 * multiple state objects are created for every unioned expression.
19229 *
19230 * Returns 0 on success and -1 on internal errors.
19231 */
19232static int
19233xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
19234 xmlSchemaIDCMatcherPtr matcher,
19235 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019236 int type)
19237{
19238 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019239
19240 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019241 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019242 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019243 if (vctxt->xpathStatePool != NULL) {
19244 sto = vctxt->xpathStatePool;
19245 vctxt->xpathStatePool = sto->next;
19246 sto->next = NULL;
19247 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019248 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019249 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019250 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019251 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
19252 if (sto == NULL) {
19253 xmlSchemaVErrMemory(NULL,
19254 "allocating an IDC state object", NULL);
19255 return (-1);
19256 }
19257 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
19258 }
19259 /*
19260 * Add to global list.
19261 */
19262 if (vctxt->xpathStates != NULL)
19263 sto->next = vctxt->xpathStates;
19264 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019265
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019266 /*
19267 * Free the old xpath validation context.
19268 */
19269 if (sto->xpathCtxt != NULL)
19270 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
19271
19272 /*
19273 * Create a new XPath (pattern) validation context.
19274 */
19275 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
19276 (xmlPatternPtr) sel->xpathComp);
19277 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019278 VERROR_INT("xmlSchemaIDCAddStateObject",
19279 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019280 return (-1);
19281 }
19282 sto->type = type;
19283 sto->depth = vctxt->depth;
19284 sto->matcher = matcher;
19285 sto->sel = sel;
19286 sto->nbHistory = 0;
19287
19288#if DEBUG_IDC
19289 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
19290 sto->sel->xpath);
19291#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019292 return (0);
19293}
19294
19295/**
19296 * xmlSchemaXPathEvaluate:
19297 * @vctxt: the WXS validation context
19298 * @nodeType: the nodeType of the current node
19299 *
19300 * Evaluates all active XPath state objects.
19301 *
19302 * Returns the number of IC "field" state objects which resolved to
19303 * this node, 0 if none resolved and -1 on internal errors.
19304 */
19305static int
19306xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019307 xmlElementType nodeType)
19308{
19309 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019310 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019311
19312 if (vctxt->xpathStates == NULL)
19313 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019314
19315 if (nodeType == XML_ATTRIBUTE_NODE)
19316 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019317#if DEBUG_IDC
19318 {
19319 xmlChar *str = NULL;
19320 xmlGenericError(xmlGenericErrorContext,
19321 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019322 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19323 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019324 FREE_AND_NULL(str)
19325 }
19326#endif
19327 /*
19328 * Process all active XPath state objects.
19329 */
19330 first = vctxt->xpathStates;
19331 sto = first;
19332 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019333#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019334 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019335 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
19336 sto->matcher->aidc->def->name, sto->sel->xpath);
19337 else
19338 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
19339 sto->matcher->aidc->def->name, sto->sel->xpath);
19340#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019341 if (nodeType == XML_ELEMENT_NODE)
19342 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019343 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019344 else
19345 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019346 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019347
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019348 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019349 VERROR_INT("xmlSchemaXPathEvaluate",
19350 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019351 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019352 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019353 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019354 goto next_sto;
19355 /*
19356 * Full match.
19357 */
19358#if DEBUG_IDC
19359 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019360 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019361#endif
19362 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019363 * Register a match in the state object history.
19364 */
19365 if (sto->history == NULL) {
19366 sto->history = (int *) xmlMalloc(5 * sizeof(int));
19367 if (sto->history == NULL) {
19368 xmlSchemaVErrMemory(NULL,
19369 "allocating the state object history", NULL);
19370 return(-1);
19371 }
19372 sto->sizeHistory = 10;
19373 } else if (sto->sizeHistory <= sto->nbHistory) {
19374 sto->sizeHistory *= 2;
19375 sto->history = (int *) xmlRealloc(sto->history,
19376 sto->sizeHistory * sizeof(int));
19377 if (sto->history == NULL) {
19378 xmlSchemaVErrMemory(NULL,
19379 "re-allocating the state object history", NULL);
19380 return(-1);
19381 }
19382 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019383 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019384
19385#ifdef DEBUG_IDC
19386 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
19387 vctxt->depth);
19388#endif
19389
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019390 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
19391 xmlSchemaIDCSelectPtr sel;
19392 /*
19393 * Activate state objects for the IDC fields of
19394 * the IDC selector.
19395 */
19396#if DEBUG_IDC
19397 xmlGenericError(xmlGenericErrorContext, "IDC: "
19398 "activating field states\n");
19399#endif
19400 sel = sto->matcher->aidc->def->fields;
19401 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019402 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
19403 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
19404 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019405 sel = sel->next;
19406 }
19407 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19408 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000019409 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019410 */
19411#if DEBUG_IDC
19412 xmlGenericError(xmlGenericErrorContext,
19413 "IDC: key found\n");
19414#endif
19415 /*
19416 * Notify that the character value of this node is
19417 * needed.
19418 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019419 if (resolved == 0) {
19420 if ((vctxt->inode->flags &
19421 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
19422 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
19423 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019424 resolved++;
19425 }
19426next_sto:
19427 if (sto->next == NULL) {
19428 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019429 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019430 */
19431 head = first;
19432 sto = vctxt->xpathStates;
19433 } else
19434 sto = sto->next;
19435 }
19436 return (resolved);
19437}
19438
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019439static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019440xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019441 xmlChar **buf,
19442 xmlSchemaPSVIIDCKeyPtr *seq,
19443 int count)
19444{
19445 int i, res;
19446 const xmlChar *value = NULL;
19447
19448 *buf = xmlStrdup(BAD_CAST "[");
19449 for (i = 0; i < count; i++) {
19450 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019451 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
19452 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019453 if (res == 0)
19454 *buf = xmlStrcat(*buf, value);
19455 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019456 VERROR_INT("xmlSchemaFormatIDCKeySequence",
19457 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019458 *buf = xmlStrcat(*buf, BAD_CAST "???");
19459 }
19460 if (i < count -1)
19461 *buf = xmlStrcat(*buf, BAD_CAST "', ");
19462 else
19463 *buf = xmlStrcat(*buf, BAD_CAST "'");
19464 if (value != NULL) {
19465 xmlFree((xmlChar *) value);
19466 value = NULL;
19467 }
19468 }
19469 *buf = xmlStrcat(*buf, BAD_CAST "]");
19470
19471 return (BAD_CAST *buf);
19472}
19473
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019474/**
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000019475 * xmlSchemaXPathPop:
19476 * @vctxt: the WXS validation context
19477 *
19478 * Pops all XPath states.
19479 *
19480 * Returns 0 on success and -1 on internal errors.
19481 */
19482static int
19483xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
19484{
19485 xmlSchemaIDCStateObjPtr sto;
19486 int res;
19487
19488 if (vctxt->xpathStates == NULL)
19489 return(0);
19490 sto = vctxt->xpathStates;
19491 do {
19492 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19493 if (res == -1)
19494 return (-1);
19495 sto = sto->next;
19496 } while (sto != NULL);
19497 return(0);
19498}
19499
19500/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019501 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019502 * @vctxt: the WXS validation context
19503 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019504 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019505 *
19506 * Processes and pops the history items of the IDC state objects.
19507 * IDC key-sequences are validated/created on IDC bindings.
19508 *
19509 * Returns 0 on success and -1 on internal errors.
19510 */
19511static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019512xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019513 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019514{
19515 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019516 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019517 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019518 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019519
19520 if (vctxt->xpathStates == NULL)
19521 return (0);
19522 sto = vctxt->xpathStates;
19523
19524#if DEBUG_IDC
19525 {
19526 xmlChar *str = NULL;
19527 xmlGenericError(xmlGenericErrorContext,
19528 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019529 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19530 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019531 FREE_AND_NULL(str)
19532 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019533#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019534 /*
19535 * Evaluate the state objects.
19536 */
19537 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000019538 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19539 if (res == -1) {
19540 VERROR_INT("xmlSchemaXPathProcessHistory",
19541 "calling xmlStreamPop()");
19542 return (-1);
19543 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019544#if DEBUG_IDC
19545 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19546 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019547#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019548 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019549 goto deregister_check;
19550
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019551 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019552
19553 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019554 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019555 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019556 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019557 sto = sto->next;
19558 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019559 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019560 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19561 if (! IS_SIMPLE_TYPE(type)) {
19562 /*
19563 * Not qualified if the field resolves to a node of non
19564 * simple type.
19565 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019566 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19567 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019568 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19569 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019570 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019571
19572 sto->nbHistory--;
19573 goto deregister_check;
19574 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019575 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019576 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019577 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019578 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019579 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019580 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019581 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19582 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019583 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019584 sto->nbHistory--;
19585 goto deregister_check;
19586 } else {
19587 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19588 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019589 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019590
19591 /*
19592 * The key will be anchored on the matcher's list of
19593 * key-sequences. The position in this list is determined
19594 * by the target node's depth relative to the matcher's
19595 * depth of creation (i.e. the depth of the scope element).
19596 */
19597 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019598 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019599
19600 /*
19601 * Create/grow the array of key-sequences.
19602 */
19603 if (matcher->keySeqs == NULL) {
19604 if (pos > 9)
19605 matcher->sizeKeySeqs = pos * 2;
19606 else
19607 matcher->sizeKeySeqs = 10;
19608 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19609 xmlMalloc(matcher->sizeKeySeqs *
19610 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19611 if (matcher->keySeqs == NULL) {
19612 xmlSchemaVErrMemory(NULL,
19613 "allocating an array of key-sequences",
19614 NULL);
19615 return(-1);
19616 }
19617 memset(matcher->keySeqs, 0,
19618 matcher->sizeKeySeqs *
19619 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19620 } else if (pos >= matcher->sizeKeySeqs) {
19621 int i = matcher->sizeKeySeqs;
19622
19623 matcher->sizeKeySeqs *= 2;
19624 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19625 xmlRealloc(matcher->keySeqs,
19626 matcher->sizeKeySeqs *
19627 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019628 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019629 xmlSchemaVErrMemory(NULL,
19630 "reallocating an array of key-sequences",
19631 NULL);
19632 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019633 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019634 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019635 * The array needs to be NULLed.
19636 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019637 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019638 for (; i < matcher->sizeKeySeqs; i++)
19639 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019640 }
19641
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019642 /*
19643 * Get/create the key-sequence.
19644 */
19645 keySeq = matcher->keySeqs[pos];
19646 if (keySeq == NULL) {
19647 goto create_sequence;
19648 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019649 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019650 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019651 * cvc-identity-constraint:
19652 * 3 For each node in the ·target node set· all
19653 * of the {fields}, with that node as the context
19654 * node, evaluate to either an empty node-set or
19655 * a node-set with exactly one member, which must
19656 * have a simple type.
19657 *
19658 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019659 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019660 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19661 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019662 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019663 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019664 "with more than one member",
19665 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019666 sto->nbHistory--;
19667 goto deregister_check;
19668 } else {
19669 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019670 }
19671 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019672
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019673create_sequence:
19674 /*
19675 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019676 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019677 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19678 matcher->aidc->def->nbFields *
19679 sizeof(xmlSchemaPSVIIDCKeyPtr));
19680 if (keySeq == NULL) {
19681 xmlSchemaVErrMemory(NULL,
19682 "allocating an IDC key-sequence", NULL);
19683 return(-1);
19684 }
19685 memset(keySeq, 0, matcher->aidc->def->nbFields *
19686 sizeof(xmlSchemaPSVIIDCKeyPtr));
19687 matcher->keySeqs[pos] = keySeq;
19688create_key:
19689 /*
19690 * Created a key once per node only.
19691 */
19692 if (key == NULL) {
19693 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19694 sizeof(xmlSchemaPSVIIDCKey));
19695 if (key == NULL) {
19696 xmlSchemaVErrMemory(NULL,
19697 "allocating a IDC key", NULL);
19698 xmlFree(keySeq);
19699 matcher->keySeqs[pos] = NULL;
19700 return(-1);
19701 }
19702 /*
19703 * Consume the compiled value.
19704 */
19705 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019706 key->val = vctxt->inode->val;
19707 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019708 /*
19709 * Store the key in a global list.
19710 */
19711 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19712 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019713 return (-1);
19714 }
19715 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019716 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019717 }
19718 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019719
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019720 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19721 xmlSchemaPSVIIDCBindingPtr bind;
19722 xmlSchemaPSVIIDCNodePtr ntItem;
19723 xmlSchemaIDCMatcherPtr matcher;
19724 xmlSchemaIDCPtr idc;
19725 int pos, i, j, nbKeys;
19726 /*
19727 * Here we have the following scenario:
19728 * An IDC 'selector' state object resolved to a target node,
19729 * during the time this target node was in the
19730 * ancestor-or-self axis, the 'field' state object(s) looked
19731 * out for matching nodes to create a key-sequence for this
19732 * target node. Now we are back to this target node and need
19733 * to put the key-sequence, together with the target node
19734 * itself, into the node-table of the corresponding IDC
19735 * binding.
19736 */
19737 matcher = sto->matcher;
19738 idc = matcher->aidc->def;
19739 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019740 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019741 /*
19742 * Check if the matcher has any key-sequences at all, plus
19743 * if it has a key-sequence for the current target node.
19744 */
19745 if ((matcher->keySeqs == NULL) ||
19746 (matcher->sizeKeySeqs <= pos)) {
19747 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19748 goto selector_key_error;
19749 else
19750 goto selector_leave;
19751 }
19752
19753 keySeq = &(matcher->keySeqs[pos]);
19754 if (*keySeq == NULL) {
19755 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19756 goto selector_key_error;
19757 else
19758 goto selector_leave;
19759 }
19760
19761 for (i = 0; i < nbKeys; i++) {
19762 if ((*keySeq)[i] == NULL) {
19763 /*
19764 * Not qualified, if not all fields did resolve.
19765 */
19766 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19767 /*
19768 * All fields of a "key" IDC must resolve.
19769 */
19770 goto selector_key_error;
19771 }
19772 goto selector_leave;
19773 }
19774 }
19775 /*
19776 * All fields did resolve.
19777 */
19778
19779 /*
19780 * 4.1 If the {identity-constraint category} is unique(/key),
19781 * then no two members of the ·qualified node set· have
19782 * ·key-sequences· whose members are pairwise equal, as
19783 * defined by Equal in [XML Schemas: Datatypes].
19784 *
19785 * Get the IDC binding from the matcher and check for
19786 * duplicate key-sequences.
19787 */
19788 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19789 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19790 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019791 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019792
19793 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019794 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019795 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019796 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019797 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019798 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019799 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019800 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019801 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019802 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019803 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019804 if (res == -1) {
19805 return (-1);
19806 } else if (res == 0)
19807 break;
19808 }
19809 if (res == 1) {
19810 /*
19811 * Duplicate found.
19812 */
19813 break;
19814 }
19815 i++;
19816 } while (i < bind->nbNodes);
19817 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019818 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019819 /*
19820 * TODO: Try to report the key-sequence.
19821 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019822 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19823 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019824 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019825 "Duplicate key-sequence %s",
19826 xmlSchemaFormatIDCKeySequence(vctxt, &str,
19827 (*keySeq), nbKeys), NULL);
19828 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019829 goto selector_leave;
19830 }
19831 }
19832 /*
19833 * Add a node-table item to the IDC binding.
19834 */
19835 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19836 sizeof(xmlSchemaPSVIIDCNode));
19837 if (ntItem == NULL) {
19838 xmlSchemaVErrMemory(NULL,
19839 "allocating an IDC node-table item", NULL);
19840 xmlFree(*keySeq);
19841 *keySeq = NULL;
19842 return(-1);
19843 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000019844 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019845
19846 /*
19847 * Store the node-table item on global list.
19848 */
19849 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19850 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19851 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019852 xmlFree(*keySeq);
19853 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019854 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019855 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000019856 ntItem->nodeQNameID = -1;
19857 } else {
19858 /*
19859 * Save a cached QName for this node on the IDC node, to be
19860 * able to report it, even if the node is not saved.
19861 */
19862 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
19863 vctxt->inode->localName, vctxt->inode->nsName);
19864 if (ntItem->nodeQNameID == -1) {
19865 xmlFree(ntItem);
19866 xmlFree(*keySeq);
19867 *keySeq = NULL;
19868 return (-1);
19869 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019870 }
19871 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000019872 * Init the node-table item: Save the node, position and
19873 * consume the key-sequence.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019874 */
19875 ntItem->node = vctxt->node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000019876 ntItem->nodeLine = vctxt->inode->nodeLine;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019877 ntItem->keys = *keySeq;
19878 *keySeq = NULL;
19879 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19880 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19881 /*
19882 * Free the item, since keyref items won't be
19883 * put on a global list.
19884 */
19885 xmlFree(ntItem->keys);
19886 xmlFree(ntItem);
19887 }
19888 return (-1);
19889 }
19890
19891 goto selector_leave;
19892selector_key_error:
19893 /*
19894 * 4.2.1 (KEY) The ·target node set· and the
19895 * ·qualified node set· are equal, that is, every
19896 * member of the ·target node set· is also a member
19897 * of the ·qualified node set· and vice versa.
19898 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019899 VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
19900 "All 'key' fields must evaluate to a node");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019901selector_leave:
19902 /*
19903 * Free the key-sequence if not added to the IDC table.
19904 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019905 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019906 xmlFree(*keySeq);
19907 *keySeq = NULL;
19908 }
19909 } /* if selector */
19910
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019911 sto->nbHistory--;
19912
19913deregister_check:
19914 /*
19915 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019916 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019917 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019918#if DEBUG_IDC
19919 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19920 sto->sel->xpath);
19921#endif
19922 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019923 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019924 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019925 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019926 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019927 nextsto = sto->next;
19928 /*
19929 * Unlink from the list of active XPath state objects.
19930 */
19931 vctxt->xpathStates = sto->next;
19932 sto->next = vctxt->xpathStatePool;
19933 /*
19934 * Link it to the pool of reusable state objects.
19935 */
19936 vctxt->xpathStatePool = sto;
19937 sto = nextsto;
19938 } else
19939 sto = sto->next;
19940 } /* while (sto != NULL) */
19941 return (0);
19942}
19943
19944/**
19945 * xmlSchemaIDCRegisterMatchers:
19946 * @vctxt: the WXS validation context
19947 * @elemDecl: the element declaration
19948 *
19949 * Creates helper objects to evaluate IDC selectors/fields
19950 * successively.
19951 *
19952 * Returns 0 if OK and -1 on internal errors.
19953 */
19954static int
19955xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19956 xmlSchemaElementPtr elemDecl)
19957{
19958 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19959 xmlSchemaIDCPtr idc, refIdc;
19960 xmlSchemaIDCAugPtr aidc;
19961
19962 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19963 if (idc == NULL)
19964 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019965
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019966#if DEBUG_IDC
19967 {
19968 xmlChar *str = NULL;
19969 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019970 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019971 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19972 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019973 FREE_AND_NULL(str)
19974 }
19975#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019976 if (vctxt->inode->idcMatchers != NULL) {
19977 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19978 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019979 return (-1);
19980 }
19981 do {
19982 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19983 /*
19984 * Since IDCs bubbles are expensive we need to know the
19985 * depth at which the bubbles should stop; this will be
19986 * the depth of the top-most keyref IDC. If no keyref
19987 * references a key/unique IDC, the bubbleDepth will
19988 * be -1, indicating that no bubbles are needed.
19989 */
19990 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19991 if (refIdc != NULL) {
19992 /*
19993 * Lookup the augmented IDC.
19994 */
19995 aidc = vctxt->aidcs;
19996 while (aidc != NULL) {
19997 if (aidc->def == refIdc)
19998 break;
19999 aidc = aidc->next;
20000 }
20001 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020002 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020003 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020004 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020005 return (-1);
20006 }
20007 if ((aidc->bubbleDepth == -1) ||
20008 (vctxt->depth < aidc->bubbleDepth))
20009 aidc->bubbleDepth = vctxt->depth;
20010 }
20011 }
20012 /*
20013 * Lookup the augmented IDC item for the IDC definition.
20014 */
20015 aidc = vctxt->aidcs;
20016 while (aidc != NULL) {
20017 if (aidc->def == idc)
20018 break;
20019 aidc = aidc->next;
20020 }
20021 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020022 VERROR_INT("xmlSchemaIDCRegisterMatchers",
20023 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020024 return (-1);
20025 }
20026 /*
20027 * Create an IDC matcher for every IDC definition.
20028 */
20029 matcher = (xmlSchemaIDCMatcherPtr)
20030 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
20031 if (matcher == NULL) {
20032 xmlSchemaVErrMemory(vctxt,
20033 "allocating an IDC matcher", NULL);
20034 return (-1);
20035 }
20036 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
20037 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020038 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020039 else
20040 last->next = matcher;
20041 last = matcher;
20042
20043 matcher->type = IDC_MATCHER;
20044 matcher->depth = vctxt->depth;
20045 matcher->aidc = aidc;
20046#if DEBUG_IDC
20047 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
20048#endif
20049 /*
20050 * Init the automaton state object.
20051 */
20052 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020053 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020054 return (-1);
20055
20056 idc = idc->next;
20057 } while (idc != NULL);
20058 return (0);
20059}
20060
20061/**
20062 * xmlSchemaBubbleIDCNodeTables:
20063 * @depth: the current tree depth
20064 *
20065 * Merges IDC bindings of an element at @depth into the corresponding IDC
20066 * bindings of its parent element. If a duplicate note-table entry is found,
20067 * both, the parent node-table entry and child entry are discarded from the
20068 * node-table of the parent.
20069 *
20070 * Returns 0 if OK and -1 on internal errors.
20071 */
20072static int
20073xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
20074{
20075 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020076 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
20077 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020078 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
20079 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020080 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020081 int duplTop;
20082
20083 /*
20084 * The node table has the following sections:
20085 *
20086 * O --> old node-table entries (first)
20087 * O
20088 * + --> new node-table entries
20089 * +
20090 * % --> new duplicate node-table entries
20091 * %
20092 * # --> old duplicate node-table entries
20093 * # (last)
20094 *
20095 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020096 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020097 if (bind == NULL) {
20098 /* Fine, no table, no bubbles. */
20099 return (0);
20100 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020101
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020102 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
20103 /*
20104 * Walk all bindings; create new or add to existing bindings.
20105 * Remove duplicate key-sequences.
20106 */
20107start_binding:
20108 while (bind != NULL) {
20109 /*
20110 * Skip keyref IDCs.
20111 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020112 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20113 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020114 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020115 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020116 /*
20117 * Check if the key/unique IDC table needs to be bubbled.
20118 */
20119 aidc = vctxt->aidcs;
20120 do {
20121 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020122 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020123 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020124 bind = bind->next;
20125 goto start_binding;
20126 }
20127 break;
20128 }
20129 aidc = aidc->next;
20130 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020131
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020132 if (parTable != NULL)
20133 parBind = *parTable;
20134 while (parBind != NULL) {
20135 /*
20136 * Search a matching parent binding for the
20137 * IDC definition.
20138 */
20139 if (parBind->definition == bind->definition) {
20140
20141 /*
20142 * Compare every node-table entry of the child node,
20143 * i.e. the key-sequence within, ...
20144 */
20145 oldNum = parBind->nbNodes; /* Skip newly added items. */
20146 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020147 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020148
20149 for (i = 0; i < bind->nbNodes; i++) {
20150 node = bind->nodeTable[i];
20151 if (node == NULL)
20152 continue;
20153 /*
20154 * ...with every key-sequence of the parent node, already
20155 * evaluated to be a duplicate key-sequence.
20156 */
20157 if (parBind->nbDupls != 0) {
20158 j = bind->nbNodes + newDupls;
20159 while (j < duplTop) {
20160 parNode = parBind->nodeTable[j];
20161 for (k = 0; k < bind->definition->nbFields; k++) {
20162 key = node->keys[k];
20163 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020164 ret = xmlSchemaAreValuesEqual(key->val,
20165 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020166 if (ret == -1) {
20167 /* TODO: Internal error */
20168 return(-1);
20169 } else if (ret == 0)
20170 break;
20171
20172 }
20173 if (ret == 1)
20174 /* Duplicate found. */
20175 break;
20176 j++;
20177 }
20178 if (j != duplTop) {
20179 /* Duplicate found. */
20180 continue;
20181 }
20182 }
20183 /*
20184 * ... and with every key-sequence of the parent node.
20185 */
20186 j = 0;
20187 while (j < oldNum) {
20188 parNode = parBind->nodeTable[j];
20189 /*
20190 * Compare key by key.
20191 */
20192 for (k = 0; k < parBind->definition->nbFields; k++) {
20193 key = node->keys[k];
20194 parKey = parNode->keys[k];
20195
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020196 ret = xmlSchemaAreValuesEqual(key->val,
20197 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020198 if (ret == -1) {
20199 /* TODO: Internal error */
20200 } else if (ret == 0)
20201 break;
20202
20203 }
20204 if (ret == 1)
20205 /*
20206 * The key-sequences are equal.
20207 */
20208 break;
20209 j++;
20210 }
20211 if (j != oldNum) {
20212 /*
20213 * Handle duplicates.
20214 */
20215 newDupls++;
20216 oldNum--;
20217 parBind->nbNodes--;
20218 /*
20219 * Move last old item to pos of duplicate.
20220 */
20221 parBind->nodeTable[j] =
20222 parBind->nodeTable[oldNum];
20223
20224 if (parBind->nbNodes != oldNum) {
20225 /*
20226 * If new items exist, move last new item to
20227 * last of old items.
20228 */
20229 parBind->nodeTable[oldNum] =
20230 parBind->nodeTable[parBind->nbNodes];
20231 }
20232 /*
20233 * Move duplicate to last pos of new/old items.
20234 */
20235 parBind->nodeTable[parBind->nbNodes] = parNode;
20236
20237 } else {
20238 /*
20239 * Add the node-table entry (node and key-sequence) of
20240 * the child node to the node table of the parent node.
20241 */
20242 if (parBind->nodeTable == NULL) {
20243 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020244 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020245 if (parBind->nodeTable == NULL) {
20246 xmlSchemaVErrMemory(NULL,
20247 "allocating IDC list of node-table items", NULL);
20248 return(-1);
20249 }
20250 parBind->sizeNodes = 1;
20251 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020252 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020253 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
20254 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
20255 sizeof(xmlSchemaPSVIIDCNodePtr));
20256 if (parBind->nodeTable == NULL) {
20257 xmlSchemaVErrMemory(NULL,
20258 "re-allocating IDC list of node-table items", NULL);
20259 return(-1);
20260 }
20261 }
20262
20263 /*
20264 * Move first old duplicate to last position
20265 * of old duplicates +1.
20266 */
20267 if (parBind->nbDupls != 0) {
20268 parBind->nodeTable[duplTop] =
20269 parBind->nodeTable[parBind->nbNodes + newDupls];
20270 }
20271 /*
20272 * Move first new duplicate to last position of
20273 * new duplicates +1.
20274 */
20275 if (newDupls != 0) {
20276 parBind->nodeTable[parBind->nbNodes + newDupls] =
20277 parBind->nodeTable[parBind->nbNodes];
20278 }
20279 /*
20280 * Append the new node-table entry to the 'new node-table
20281 * entries' section.
20282 */
20283 parBind->nodeTable[parBind->nbNodes] = node;
20284 parBind->nbNodes++;
20285 duplTop++;
20286 }
20287 }
20288 parBind->nbDupls += newDupls;
20289 break;
20290 }
20291 if (parBind->next == NULL)
20292 lastParBind = parBind;
20293 parBind = parBind->next;
20294 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020295 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020296 /*
20297 * No binding for the IDC was found: create a new one and
20298 * copy all node-tables.
20299 */
20300 parBind = xmlSchemaIDCNewBinding(bind->definition);
20301 if (parBind == NULL)
20302 return(-1);
20303
20304 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
20305 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
20306 if (parBind->nodeTable == NULL) {
20307 xmlSchemaVErrMemory(NULL,
20308 "allocating an array of IDC node-table items", NULL);
20309 xmlSchemaIDCFreeBinding(parBind);
20310 return(-1);
20311 }
20312 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020313 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020314 memcpy(parBind->nodeTable, bind->nodeTable,
20315 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020316 if (*parTable == NULL)
20317 *parTable = parBind;
20318 else
20319 lastParBind->next = parBind;
20320 }
20321 bind = bind->next;
20322 }
20323 return (0);
20324}
20325
20326/**
20327 * xmlSchemaCheckCVCIDCKeyRef:
20328 * @vctxt: the WXS validation context
20329 * @elemDecl: the element declaration
20330 *
20331 * Check the cvc-idc-keyref constraints.
20332 */
20333static int
20334xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
20335{
20336 xmlSchemaPSVIIDCBindingPtr refbind, bind;
20337
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020338 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020339 /*
20340 * Find a keyref.
20341 */
20342 while (refbind != NULL) {
20343 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20344 int i, j, k, res;
20345 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
20346 xmlSchemaPSVIIDCKeyPtr refKey, key;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000020347 xmlSchemaPSVIIDCNodePtr refNode = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020348
20349 /*
20350 * Find the referred key/unique.
20351 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020352 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020353 do {
20354 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
20355 bind->definition)
20356 break;
20357 bind = bind->next;
20358 } while (bind != NULL);
20359
20360 /*
20361 * Search for a matching key-sequences.
20362 */
20363 for (i = 0; i < refbind->nbNodes; i++) {
20364 res = 0;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000020365 refNode = refbind->nodeTable[i];
20366 if (bind != NULL) {
20367 refKeys = refNode->keys;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020368 for (j = 0; j < bind->nbNodes; j++) {
20369 keys = bind->nodeTable[j]->keys;
20370 for (k = 0; k < bind->definition->nbFields; k++) {
20371 refKey = refKeys[k];
20372 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020373 res = xmlSchemaAreValuesEqual(key->val,
20374 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020375 if (res == 0)
20376 break;
20377 else if (res == -1) {
20378 return (-1);
20379 }
20380 }
20381 if (res == 1) {
20382 /*
20383 * Match found.
20384 */
20385 break;
20386 }
20387 }
20388 }
20389 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020390 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020391 /* TODO: Report the key-sequence. */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000020392 xmlSchemaKeyrefErr(vctxt,
20393 XML_SCHEMAV_CVC_IDC, refNode,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020394 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020395 "No match found for key-sequence %s of key "
20396 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020397 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020398 refbind->nodeTable[i]->keys,
20399 refbind->definition->nbFields),
20400 xmlSchemaFormatQName(&strB,
20401 refbind->definition->targetNamespace,
20402 refbind->definition->name));
20403 FREE_AND_NULL(str);
20404 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020405 }
20406 }
20407 }
20408 refbind = refbind->next;
20409 }
20410 return (0);
20411}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020412
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020413/************************************************************************
20414 * *
20415 * XML Reader validation code *
20416 * *
20417 ************************************************************************/
20418
20419static xmlSchemaAttrInfoPtr
20420xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020421{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020422 xmlSchemaAttrInfoPtr iattr;
20423 /*
20424 * Grow/create list of attribute infos.
20425 */
20426 if (vctxt->attrInfos == NULL) {
20427 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20428 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
20429 vctxt->sizeAttrInfos = 1;
20430 if (vctxt->attrInfos == NULL) {
20431 xmlSchemaVErrMemory(vctxt,
20432 "allocating attribute info list", NULL);
20433 return (NULL);
20434 }
20435 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
20436 vctxt->sizeAttrInfos++;
20437 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20438 xmlRealloc(vctxt->attrInfos,
20439 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
20440 if (vctxt->attrInfos == NULL) {
20441 xmlSchemaVErrMemory(vctxt,
20442 "re-allocating attribute info list", NULL);
20443 return (NULL);
20444 }
20445 } else {
20446 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
20447 if (iattr->localName != NULL) {
20448 VERROR_INT("xmlSchemaGetFreshAttrInfo",
20449 "attr info not cleared");
20450 return (NULL);
20451 }
20452 iattr->nodeType = XML_ATTRIBUTE_NODE;
20453 return (iattr);
20454 }
20455 /*
20456 * Create an attribute info.
20457 */
20458 iattr = (xmlSchemaAttrInfoPtr)
20459 xmlMalloc(sizeof(xmlSchemaAttrInfo));
20460 if (iattr == NULL) {
20461 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
20462 return (NULL);
20463 }
20464 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
20465 iattr->nodeType = XML_ATTRIBUTE_NODE;
20466 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
20467
20468 return (iattr);
20469}
20470
20471static int
20472xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
20473 xmlNodePtr attrNode,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000020474 int nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020475 const xmlChar *localName,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000020476 const xmlChar *nsName,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020477 int ownedNames,
20478 xmlChar *value,
20479 int ownedValue)
20480{
20481 xmlSchemaAttrInfoPtr attr;
20482
20483 attr = xmlSchemaGetFreshAttrInfo(vctxt);
20484 if (attr == NULL) {
20485 VERROR_INT("xmlSchemaPushAttribute",
20486 "calling xmlSchemaGetFreshAttrInfo()");
20487 return (-1);
20488 }
20489 attr->node = attrNode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000020490 attr->nodeLine = nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020491 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
20492 attr->localName = localName;
20493 attr->nsName = nsName;
20494 if (ownedNames)
20495 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
20496 /*
20497 * Evaluate if it's an XSI attribute.
20498 */
20499 if (nsName != NULL) {
20500 if (xmlStrEqual(localName, BAD_CAST "nil")) {
20501 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20502 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
20503 }
20504 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
20505 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20506 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
20507 }
20508 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
20509 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20510 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
20511 }
20512 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
20513 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20514 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
20515 }
20516 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
20517 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
20518 }
20519 }
20520 attr->value = value;
20521 if (ownedValue)
20522 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
20523 if (attr->metaType != 0)
20524 attr->state = XML_SCHEMAS_ATTR_META;
20525 return (0);
20526}
20527
20528static void
20529xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
20530{
20531 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
20532 FREE_AND_NULL(ielem->localName);
20533 FREE_AND_NULL(ielem->nsName);
20534 } else {
20535 ielem->localName = NULL;
20536 ielem->nsName = NULL;
20537 }
20538 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
20539 FREE_AND_NULL(ielem->value);
20540 } else {
20541 ielem->value = NULL;
20542 }
20543 if (ielem->val != NULL) {
20544 xmlSchemaFreeValue(ielem->val);
20545 ielem->val = NULL;
20546 }
20547 if (ielem->idcMatchers != NULL) {
20548 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
20549 ielem->idcMatchers = NULL;
20550 }
20551 if (ielem->idcTable != NULL) {
20552 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
20553 ielem->idcTable = NULL;
20554 }
20555 if (ielem->regexCtxt != NULL) {
20556 xmlRegFreeExecCtxt(ielem->regexCtxt);
20557 ielem->regexCtxt = NULL;
20558 }
20559 if (ielem->nsBindings != NULL) {
20560 xmlFree((xmlChar **)ielem->nsBindings);
20561 ielem->nsBindings = NULL;
20562 ielem->nbNsBindings = 0;
20563 ielem->sizeNsBindings = 0;
20564 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020565}
20566
20567/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020568 * xmlSchemaGetFreshElemInfo:
20569 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020570 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020571 * Creates/reuses and initializes the element info item for
20572 * the currect tree depth.
20573 *
20574 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020575 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020576static xmlSchemaNodeInfoPtr
20577xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020578{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020579 xmlSchemaNodeInfoPtr info = NULL;
20580
20581 if (vctxt->depth > vctxt->sizeElemInfos) {
20582 VERROR_INT("xmlSchemaGetFreshElemInfo",
20583 "inconsistent depth encountered");
20584 return (NULL);
20585 }
20586 if (vctxt->elemInfos == NULL) {
20587 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20588 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
20589 if (vctxt->elemInfos == NULL) {
20590 xmlSchemaVErrMemory(vctxt,
20591 "allocating the element info array", NULL);
20592 return (NULL);
20593 }
20594 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
20595 vctxt->sizeElemInfos = 10;
20596 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
20597 int i = vctxt->sizeElemInfos;
20598
20599 vctxt->sizeElemInfos *= 2;
20600 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20601 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
20602 sizeof(xmlSchemaNodeInfoPtr));
20603 if (vctxt->elemInfos == NULL) {
20604 xmlSchemaVErrMemory(vctxt,
20605 "re-allocating the element info array", NULL);
20606 return (NULL);
20607 }
20608 /*
20609 * We need the new memory to be NULLed.
20610 * TODO: Use memset instead?
20611 */
20612 for (; i < vctxt->sizeElemInfos; i++)
20613 vctxt->elemInfos[i] = NULL;
20614 } else
20615 info = vctxt->elemInfos[vctxt->depth];
20616
20617 if (info == NULL) {
20618 info = (xmlSchemaNodeInfoPtr)
20619 xmlMalloc(sizeof(xmlSchemaNodeInfo));
20620 if (info == NULL) {
20621 xmlSchemaVErrMemory(vctxt,
20622 "allocating an element info", NULL);
20623 return (NULL);
20624 }
20625 vctxt->elemInfos[vctxt->depth] = info;
20626 } else {
20627 if (info->localName != NULL) {
20628 VERROR_INT("xmlSchemaGetFreshElemInfo",
20629 "elem info has not been cleared");
20630 return (NULL);
20631 }
20632 }
20633 memset(info, 0, sizeof(xmlSchemaNodeInfo));
20634 info->nodeType = XML_ELEMENT_NODE;
20635 info->depth = vctxt->depth;
20636
20637 return (info);
20638}
20639
20640#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
20641#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
20642#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
20643
20644static int
20645xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
20646 xmlNodePtr node,
20647 xmlSchemaTypePtr type,
20648 xmlSchemaValType valType,
20649 const xmlChar * value,
20650 xmlSchemaValPtr val,
20651 unsigned long length,
20652 int fireErrors)
20653{
20654 int ret, error = 0;
20655
20656 xmlSchemaTypePtr tmpType;
20657 xmlSchemaFacetLinkPtr facetLink;
20658 xmlSchemaFacetPtr facet;
20659 unsigned long len = 0;
20660 xmlSchemaWhitespaceValueType ws;
20661
20662 /*
20663 * In Libxml2, derived built-in types have currently no explicit facets.
20664 */
20665 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020666 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020667
20668 /*
20669 * NOTE: Do not jump away, if the facetSet of the given type is
20670 * empty: until now, "pattern" and "enumeration" facets of the
20671 * *base types* need to be checked as well.
20672 */
20673 if (type->facetSet == NULL)
20674 goto pattern_and_enum;
20675
20676 if (! VARIETY_ATOMIC(type)) {
20677 if (VARIETY_LIST(type))
20678 goto variety_list;
20679 else
20680 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020681 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020682 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020683 * Whitespace handling is only of importance for string-based
20684 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020685 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020686 tmpType = xmlSchemaGetPrimitiveType(type);
20687 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
20688 IS_ANY_SIMPLE_TYPE(tmpType)) {
20689 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20690 } else
20691 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
20692 /*
20693 * If the value was not computed (for string or
20694 * anySimpleType based types), then use the provided
20695 * type.
20696 */
20697 if (val == NULL)
20698 valType = valType;
20699 else
20700 valType = xmlSchemaGetValType(val);
20701
20702 ret = 0;
20703 for (facetLink = type->facetSet; facetLink != NULL;
20704 facetLink = facetLink->next) {
20705 /*
20706 * Skip the pattern "whiteSpace": it is used to
20707 * format the character content beforehand.
20708 */
20709 switch (facetLink->facet->type) {
20710 case XML_SCHEMA_FACET_WHITESPACE:
20711 case XML_SCHEMA_FACET_PATTERN:
20712 case XML_SCHEMA_FACET_ENUMERATION:
20713 continue;
20714 case XML_SCHEMA_FACET_LENGTH:
20715 case XML_SCHEMA_FACET_MINLENGTH:
20716 case XML_SCHEMA_FACET_MAXLENGTH:
20717 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
20718 valType, value, val, &len, ws);
20719 break;
20720 default:
20721 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
20722 valType, value, val, ws);
20723 break;
20724 }
20725 if (ret < 0) {
20726 AERROR_INT("xmlSchemaValidateFacets",
20727 "validating against a atomic type facet");
20728 return (-1);
20729 } else if (ret > 0) {
20730 if (fireErrors)
20731 xmlSchemaFacetErr(actxt, ret, node,
20732 value, len, type, facetLink->facet, NULL, NULL, NULL);
20733 else
20734 return (ret);
20735 if (error == 0)
20736 error = ret;
20737 }
20738 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020739 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020740
20741variety_list:
20742 if (! VARIETY_LIST(type))
20743 goto pattern_and_enum;
20744 /*
20745 * "length", "minLength" and "maxLength" of list types.
20746 */
20747 ret = 0;
20748 for (facetLink = type->facetSet; facetLink != NULL;
20749 facetLink = facetLink->next) {
20750
20751 switch (facetLink->facet->type) {
20752 case XML_SCHEMA_FACET_LENGTH:
20753 case XML_SCHEMA_FACET_MINLENGTH:
20754 case XML_SCHEMA_FACET_MAXLENGTH:
20755 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
20756 value, length, NULL);
20757 break;
20758 default:
20759 continue;
20760 }
20761 if (ret < 0) {
20762 AERROR_INT("xmlSchemaValidateFacets",
20763 "validating against a list type facet");
20764 return (-1);
20765 } else if (ret > 0) {
20766 if (fireErrors)
20767 xmlSchemaFacetErr(actxt, ret, node,
20768 value, length, type, facetLink->facet, NULL, NULL, NULL);
20769 else
20770 return (ret);
20771 if (error == 0)
20772 error = ret;
20773 }
20774 ret = 0;
20775 }
20776
20777pattern_and_enum:
20778 if (error >= 0) {
20779 int found = 0;
20780 /*
20781 * Process enumerations. Facet values are in the value space
20782 * of the defining type's base type. This seems to be a bug in the
20783 * XML Schema 1.0 spec. Use the whitespace type of the base type.
20784 * Only the first set of enumerations in the ancestor-or-self axis
20785 * is used for validation.
20786 */
20787 ret = 0;
20788 tmpType = type;
20789 do {
20790 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
20791 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
20792 continue;
20793 found = 1;
20794 ret = xmlSchemaAreValuesEqual(facet->val, val);
20795 if (ret == 1)
20796 break;
20797 else if (ret < 0) {
20798 AERROR_INT("xmlSchemaValidateFacets",
20799 "validating against an enumeration facet");
20800 return (-1);
20801 }
20802 }
20803 if (ret != 0)
20804 break;
20805 tmpType = tmpType->baseType;
20806 } while ((tmpType != NULL) &&
20807 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20808 if (found && (ret == 0)) {
20809 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
20810 if (fireErrors) {
20811 xmlSchemaFacetErr(actxt, ret, node,
20812 value, 0, type, NULL, NULL, NULL, NULL);
20813 } else
20814 return (ret);
20815 if (error == 0)
20816 error = ret;
20817 }
20818 }
20819
20820 if (error >= 0) {
20821 int found;
20822 /*
20823 * Process patters. Pattern facets are ORed at type level
20824 * and ANDed if derived. Walk the base type axis.
20825 */
20826 tmpType = type;
20827 facet = NULL;
20828 do {
20829 found = 0;
20830 for (facetLink = tmpType->facetSet; facetLink != NULL;
20831 facetLink = facetLink->next) {
20832 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
20833 continue;
20834 found = 1;
20835 /*
20836 * NOTE that for patterns, @value needs to be the
20837 * normalized vaule.
20838 */
20839 ret = xmlRegexpExec(facetLink->facet->regexp, value);
20840 if (ret == 1)
20841 break;
20842 else if (ret < 0) {
20843 AERROR_INT("xmlSchemaValidateFacets",
20844 "validating against a pattern facet");
20845 return (-1);
20846 } else {
20847 /*
20848 * Save the last non-validating facet.
20849 */
20850 facet = facetLink->facet;
20851 }
20852 }
20853 if (found && (ret != 1)) {
20854 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
20855 if (fireErrors) {
20856 xmlSchemaFacetErr(actxt, ret, node,
20857 value, 0, type, facet, NULL, NULL, NULL);
20858 } else
20859 return (ret);
20860 if (error == 0)
20861 error = ret;
20862 break;
20863 }
20864 tmpType = tmpType->baseType;
20865 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20866 }
20867
20868 return (error);
20869}
20870
20871static xmlChar *
20872xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
20873 const xmlChar *value)
20874{
20875 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
20876 case XML_SCHEMA_WHITESPACE_COLLAPSE:
20877 return (xmlSchemaCollapseString(value));
20878 case XML_SCHEMA_WHITESPACE_REPLACE:
20879 return (xmlSchemaWhiteSpaceReplace(value));
20880 default:
20881 return (NULL);
20882 }
20883}
20884
20885static int
20886xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
20887 const xmlChar *value,
20888 xmlSchemaValPtr *val,
20889 int valNeeded)
20890{
20891 int ret;
20892 const xmlChar *nsName;
20893 xmlChar *local, *prefix = NULL;
20894
20895 ret = xmlValidateQName(value, 1);
20896 if (ret != 0) {
20897 if (ret == -1) {
20898 VERROR_INT("xmlSchemaValidateQName",
20899 "calling xmlValidateQName()");
20900 return (-1);
20901 }
20902 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
20903 }
20904 /*
20905 * NOTE: xmlSplitQName2 will always return a duplicated
20906 * strings.
20907 */
20908 local = xmlSplitQName2(value, &prefix);
20909 if (local == NULL)
20910 local = xmlStrdup(value);
20911 /*
20912 * OPTIMIZE TODO: Use flags for:
20913 * - is there any namespace binding?
20914 * - is there a default namespace?
20915 */
20916 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20917
20918 if (prefix != NULL) {
20919 xmlFree(prefix);
20920 /*
20921 * A namespace must be found if the prefix is
20922 * NOT NULL.
20923 */
20924 if (nsName == NULL) {
20925 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20926 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
20927 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20928 "The QName value '%s' has no "
20929 "corresponding namespace declaration in "
20930 "scope", value, NULL);
20931 if (local != NULL)
20932 xmlFree(local);
20933 return (ret);
20934 }
20935 }
20936 if (valNeeded && val) {
20937 if (nsName != NULL)
20938 *val = xmlSchemaNewQNameValue(
20939 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
20940 else
20941 *val = xmlSchemaNewQNameValue(NULL,
20942 BAD_CAST local);
20943 } else
20944 xmlFree(local);
20945 return (0);
20946}
20947
20948/*
20949* cvc-simple-type
20950*/
20951static int
20952xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
20953 xmlNodePtr node,
20954 xmlSchemaTypePtr type,
20955 const xmlChar *value,
20956 xmlSchemaValPtr *retVal,
20957 int fireErrors,
20958 int normalize,
20959 int isNormalized)
20960{
20961 int ret = 0, valNeeded = (retVal) ? 1 : 0;
20962 xmlSchemaValPtr val = NULL;
20963 xmlSchemaWhitespaceValueType ws;
20964 xmlChar *normValue = NULL;
20965
20966#define NORMALIZE(atype) \
20967 if ((! isNormalized) && \
20968 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
20969 normValue = xmlSchemaNormalizeValue(atype, value); \
20970 if (normValue != NULL) \
20971 value = normValue; \
20972 isNormalized = 1; \
20973 }
20974
20975 if ((retVal != NULL) && (*retVal != NULL)) {
20976 xmlSchemaFreeValue(*retVal);
20977 *retVal = NULL;
20978 }
20979 /*
20980 * 3.14.4 Simple Type Definition Validation Rules
20981 * Validation Rule: String Valid
20982 */
20983 /*
20984 * 1 It is schema-valid with respect to that definition as defined
20985 * by Datatype Valid in [XML Schemas: Datatypes].
20986 */
20987 /*
20988 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
20989 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
20990 * the string must be a ·declared entity name·.
20991 */
20992 /*
20993 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
20994 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
20995 * then every whitespace-delimited substring of the string must be a ·declared
20996 * entity name·.
20997 */
20998 /*
20999 * 2.3 otherwise no further condition applies.
21000 */
21001 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
21002 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000021003 if (value == NULL)
21004 value = BAD_CAST "";
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021005 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
21006 xmlSchemaTypePtr biType; /* The built-in type. */
21007 /*
21008 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
21009 * a literal in the ·lexical space· of {base type definition}"
21010 */
21011 /*
21012 * Whitespace-normalize.
21013 */
21014 NORMALIZE(type);
21015 if (type->type != XML_SCHEMA_TYPE_BASIC) {
21016 /*
21017 * Get the built-in type.
21018 */
21019 biType = type->baseType;
21020 while ((biType != NULL) &&
21021 (biType->type != XML_SCHEMA_TYPE_BASIC))
21022 biType = biType->baseType;
21023
21024 if (biType == NULL) {
21025 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21026 "could not get the built-in type");
21027 goto internal_error;
21028 }
21029 } else
21030 biType = type;
21031 /*
21032 * NOTATIONs need to be processed here, since they need
21033 * to lookup in the hashtable of NOTATION declarations of the schema.
21034 */
21035 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
21036 switch (biType->builtInType) {
21037 case XML_SCHEMAS_NOTATION:
21038 ret = xmlSchemaValidateNotation(
21039 (xmlSchemaValidCtxtPtr) actxt,
21040 ((xmlSchemaValidCtxtPtr) actxt)->schema,
21041 NULL, value, &val, valNeeded);
21042 break;
21043 case XML_SCHEMAS_QNAME:
21044 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
21045 value, &val, valNeeded);
21046 break;
21047 default:
21048 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
21049 if (valNeeded)
21050 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
21051 value, &val, NULL);
21052 else
21053 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
21054 value, NULL, NULL);
21055 break;
21056 }
21057 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
21058 switch (biType->builtInType) {
21059 case XML_SCHEMAS_NOTATION:
21060 ret = xmlSchemaValidateNotation(NULL,
21061 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
21062 value, &val, valNeeded);
21063 break;
21064 default:
21065 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
21066 if (valNeeded)
21067 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
21068 value, &val, node);
21069 else
21070 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
21071 value, NULL, node);
21072 break;
21073 }
21074 } else {
21075 /*
21076 * Validation via a public API is not implemented yet.
21077 */
21078 TODO
21079 goto internal_error;
21080 }
21081 if (ret != 0) {
21082 if (ret < 0) {
21083 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21084 "validating against a built-in type");
21085 goto internal_error;
21086 }
21087 if (VARIETY_LIST(type))
21088 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
21089 else
21090 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
21091 }
21092 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
21093 /*
21094 * Check facets.
21095 */
21096 ret = xmlSchemaValidateFacets(actxt, node, type,
21097 (xmlSchemaValType) biType->builtInType, value, val,
21098 0, fireErrors);
21099 if (ret != 0) {
21100 if (ret < 0) {
21101 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21102 "validating facets of atomic simple type");
21103 goto internal_error;
21104 }
21105 if (VARIETY_LIST(type))
21106 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
21107 else
21108 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
21109 }
21110 }
21111 if (fireErrors && (ret > 0))
21112 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
21113 } else if (VARIETY_LIST(type)) {
21114
21115 xmlSchemaTypePtr itemType;
21116 const xmlChar *cur, *end;
21117 xmlChar *tmpValue = NULL;
21118 unsigned long len = 0;
21119 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
21120 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
21121 * of white space separated tokens, each of which ·match·es a literal
21122 * in the ·lexical space· of {item type definition}
21123 */
21124 /*
21125 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
21126 * the list type has an enum or pattern facet.
21127 */
21128 NORMALIZE(type);
21129 /*
21130 * VAL TODO: Optimize validation of empty values.
21131 * VAL TODO: We do not have computed values for lists.
21132 */
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000021133 itemType = GET_LIST_ITEM_TYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021134 cur = value;
21135 do {
21136 while (IS_BLANK_CH(*cur))
21137 cur++;
21138 end = cur;
21139 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21140 end++;
21141 if (end == cur)
21142 break;
21143 tmpValue = xmlStrndup(cur, end - cur);
21144 len++;
21145
21146 if (valNeeded)
21147 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
21148 tmpValue, &curVal, fireErrors, 0, 1);
21149 else
21150 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
21151 tmpValue, NULL, fireErrors, 0, 1);
21152 FREE_AND_NULL(tmpValue);
21153 if (curVal != NULL) {
21154 /*
21155 * Add to list of computed values.
21156 */
21157 if (val == NULL)
21158 val = curVal;
21159 else
21160 xmlSchemaValueAppend(prevVal, curVal);
21161 prevVal = curVal;
21162 curVal = NULL;
21163 }
21164 if (ret != 0) {
21165 if (ret < 0) {
21166 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21167 "validating an item of list simple type");
21168 goto internal_error;
21169 }
21170 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
21171 break;
21172 }
21173 cur = end;
21174 } while (*cur != 0);
21175 FREE_AND_NULL(tmpValue);
21176 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
21177 /*
21178 * Apply facets (pattern, enumeration).
21179 */
21180 ret = xmlSchemaValidateFacets(actxt, node, type,
21181 XML_SCHEMAS_UNKNOWN, value, val,
21182 len, fireErrors);
21183 if (ret != 0) {
21184 if (ret < 0) {
21185 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21186 "validating facets of list simple type");
21187 goto internal_error;
21188 }
21189 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
21190 }
21191 }
21192 if (fireErrors && (ret > 0)) {
21193 /*
21194 * Report the normalized value.
21195 */
21196 normalize = 1;
21197 NORMALIZE(type);
21198 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
21199 }
21200 } else if (VARIETY_UNION(type)) {
21201 xmlSchemaTypeLinkPtr memberLink;
21202 /*
21203 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
21204 * not apply directly; however, the normalization behavior of ·union·
21205 * types is controlled by the value of whiteSpace on that one of the
21206 * ·memberTypes· against which the ·union· is successfully validated.
21207 *
21208 * This means that the value is normalized by the first validating
21209 * member type, then the facets of the union type are applied. This
21210 * needs changing of the value!
21211 */
21212
21213 /*
21214 * 1.2.3 if {variety} is ·union· then the string must ·match· a
21215 * literal in the ·lexical space· of at least one member of
21216 * {member type definitions}
21217 */
21218 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
21219 if (memberLink == NULL) {
21220 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21221 "union simple type has no member types");
21222 goto internal_error;
21223 }
21224 /*
21225 * Always normalize union type values, since we currently
21226 * cannot store the whitespace information with the value
21227 * itself; otherwise a later value-comparison would be
21228 * not possible.
21229 */
21230 while (memberLink != NULL) {
21231 if (valNeeded)
21232 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
21233 memberLink->type, value, &val, 0, 1, 0);
21234 else
21235 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
21236 memberLink->type, value, NULL, 0, 1, 0);
21237 if (ret <= 0)
21238 break;
21239 memberLink = memberLink->next;
21240 }
21241 if (ret != 0) {
21242 if (ret < 0) {
21243 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21244 "validating members of union simple type");
21245 goto internal_error;
21246 }
21247 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
21248 }
21249 /*
21250 * Apply facets (pattern, enumeration).
21251 */
21252 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
21253 /*
21254 * The normalization behavior of ·union· types is controlled by
21255 * the value of whiteSpace on that one of the ·memberTypes·
21256 * against which the ·union· is successfully validated.
21257 */
21258 NORMALIZE(memberLink->type);
21259 ret = xmlSchemaValidateFacets(actxt, node, type,
21260 XML_SCHEMAS_UNKNOWN, value, val,
21261 0, fireErrors);
21262 if (ret != 0) {
21263 if (ret < 0) {
21264 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21265 "validating facets of union simple type");
21266 goto internal_error;
21267 }
21268 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
21269 }
21270 }
21271 if (fireErrors && (ret > 0))
21272 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
21273 }
21274
21275 if (normValue != NULL)
21276 xmlFree(normValue);
21277 if (ret == 0) {
21278 if (retVal != NULL)
21279 *retVal = val;
21280 else if (val != NULL)
21281 xmlSchemaFreeValue(val);
21282 } else if (val != NULL)
21283 xmlSchemaFreeValue(val);
21284 return (ret);
21285internal_error:
21286 if (normValue != NULL)
21287 xmlFree(normValue);
21288 if (val != NULL)
21289 xmlSchemaFreeValue(val);
21290 return (-1);
21291}
21292
21293static int
21294xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
21295 const xmlChar *value,
21296 const xmlChar **nsName,
21297 const xmlChar **localName)
21298{
21299 int ret = 0;
21300
21301 if ((nsName == NULL) || (localName == NULL))
21302 return (-1);
21303 *nsName = NULL;
21304 *localName = NULL;
21305
21306 ret = xmlValidateQName(value, 1);
21307 if (ret == -1)
21308 return (-1);
21309 if (ret > 0) {
21310 xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
21311 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
21312 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
21313 return (1);
21314 }
21315 {
21316 xmlChar *local = NULL;
21317 xmlChar *prefix;
21318
21319 /*
21320 * NOTE: xmlSplitQName2 will return a duplicated
21321 * string.
21322 */
21323 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021324 if (local == NULL)
21325 *localName = xmlDictLookup(vctxt->dict, value, -1);
21326 else {
21327 *localName = xmlDictLookup(vctxt->dict, local, -1);
21328 xmlFree(local);
21329 }
21330
21331 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
21332
21333 if (prefix != NULL) {
21334 xmlFree(prefix);
21335 /*
21336 * A namespace must be found if the prefix is NOT NULL.
21337 */
21338 if (*nsName == NULL) {
21339 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21340 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
21341 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
21342 "The QName value '%s' has no "
21343 "corresponding namespace declaration in scope",
21344 value, NULL);
21345 return (2);
21346 }
21347 }
21348 }
21349 return (0);
21350}
21351
21352static int
21353xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
21354 xmlSchemaAttrInfoPtr iattr,
21355 xmlSchemaTypePtr *localType,
21356 xmlSchemaElementPtr elemDecl)
21357{
21358 int ret = 0;
21359 /*
21360 * cvc-elt (3.3.4) : (4)
21361 * AND
21362 * Schema-Validity Assessment (Element) (cvc-assess-elt)
21363 * (1.2.1.2.1) - (1.2.1.2.4)
21364 * Handle 'xsi:type'.
21365 */
21366 if (localType == NULL)
21367 return (-1);
21368 *localType = NULL;
21369 if (iattr == NULL)
21370 return (0);
21371 else {
21372 const xmlChar *nsName = NULL, *local = NULL;
21373 /*
21374 * TODO: We should report a *warning* that the type was overriden
21375 * by the instance.
21376 */
21377 ACTIVATE_ATTRIBUTE(iattr);
21378 /*
21379 * (cvc-elt) (3.3.4) : (4.1)
21380 * (cvc-assess-elt) (1.2.1.2.2)
21381 */
21382 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
21383 &nsName, &local);
21384 if (ret != 0) {
21385 if (ret < 0) {
21386 VERROR_INT("xmlSchemaValidateElementByDeclaration",
21387 "calling xmlSchemaQNameExpand() to validate the "
21388 "attribute 'xsi:type'");
21389 goto internal_error;
21390 }
21391 goto exit;
21392 }
21393 /*
21394 * (cvc-elt) (3.3.4) : (4.2)
21395 * (cvc-assess-elt) (1.2.1.2.3)
21396 */
21397 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
21398 if (*localType == NULL) {
21399 xmlChar *str = NULL;
21400
21401 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21402 XML_SCHEMAV_CVC_ELT_4_2, NULL,
21403 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
21404 "The QName value '%s' of the xsi:type attribute does not "
21405 "resolve to a type definition",
21406 xmlSchemaFormatQName(&str, nsName, local), NULL);
21407 FREE_AND_NULL(str);
21408 ret = vctxt->err;
21409 goto exit;
21410 }
21411 if (elemDecl != NULL) {
21412 int set = 0;
21413
21414 /*
21415 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
21416 * "The ·local type definition· must be validly
21417 * derived from the {type definition} given the union of
21418 * the {disallowed substitutions} and the {type definition}'s
21419 * {prohibited substitutions}, as defined in
21420 * Type Derivation OK (Complex) (§3.4.6)
21421 * (if it is a complex type definition),
21422 * or given {disallowed substitutions} as defined in Type
21423 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
21424 * definition)."
21425 *
21426 * {disallowed substitutions}: the "block" on the element decl.
21427 * {prohibited substitutions}: the "block" on the type def.
21428 */
21429 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
21430 (elemDecl->subtypes->flags &
21431 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
21432 set |= SUBSET_EXTENSION;
21433
21434 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
21435 (elemDecl->subtypes->flags &
21436 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
21437 set |= SUBSET_RESTRICTION;
21438
21439 if (xmlSchemaCheckCOSDerivedOK(*localType,
21440 elemDecl->subtypes, set) != 0) {
21441 xmlChar *str = NULL;
21442
21443 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21444 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
21445 "The type definition '%s', specified by xsi:type, is "
21446 "blocked or not validly derived from the type definition "
21447 "of the element declaration",
21448 xmlSchemaFormatQName(&str,
21449 (*localType)->targetNamespace,
21450 (*localType)->name),
21451 NULL);
21452 FREE_AND_NULL(str);
21453 ret = vctxt->err;
21454 *localType = NULL;
21455 }
21456 }
21457 }
21458exit:
21459 ACTIVATE_ELEM;
21460 return (ret);
21461internal_error:
21462 ACTIVATE_ELEM;
21463 return (-1);
21464}
21465
21466static int
21467xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
21468{
21469 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
21470 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
21471
21472 /*
21473 * cvc-elt (3.3.4) : 1
21474 */
21475 if (elemDecl == NULL) {
21476 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
21477 "No matching declaration available");
21478 return (vctxt->err);
21479 }
21480 /*
21481 * cvc-elt (3.3.4) : 2
21482 */
21483 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
21484 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
21485 "The element declaration is abstract");
21486 return (vctxt->err);
21487 }
21488 if (actualType == NULL) {
21489 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21490 "The type definition is absent");
21491 return (XML_SCHEMAV_CVC_TYPE_1);
21492 }
21493 if (vctxt->nbAttrInfos != 0) {
21494 int ret;
21495 xmlSchemaAttrInfoPtr iattr;
21496 /*
21497 * cvc-elt (3.3.4) : 3
21498 * Handle 'xsi:nil'.
21499 */
21500 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21501 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
21502 if (iattr) {
21503 ACTIVATE_ATTRIBUTE(iattr);
21504 /*
21505 * Validate the value.
21506 */
21507 ret = xmlSchemaVCheckCVCSimpleType(
21508 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21509 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
21510 iattr->value, &(iattr->val), 1, 0, 0);
21511 ACTIVATE_ELEM;
21512 if (ret < 0) {
21513 VERROR_INT("xmlSchemaValidateElemDecl",
21514 "calling xmlSchemaVCheckCVCSimpleType() to "
21515 "validate the attribute 'xsi:nil'");
21516 return (-1);
21517 }
21518 if (ret == 0) {
21519 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
21520 /*
21521 * cvc-elt (3.3.4) : 3.1
21522 */
21523 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
21524 "The element is not 'nillable'");
21525 /* Does not return an error on purpose. */
21526 } else {
21527 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
21528 /*
21529 * cvc-elt (3.3.4) : 3.2.2
21530 */
21531 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21532 (elemDecl->value != NULL)) {
21533 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
21534 "The element cannot be 'nilled' because "
21535 "there is a fixed value constraint defined "
21536 "for it");
21537 /* Does not return an error on purpose. */
21538 } else
21539 vctxt->inode->flags |=
21540 XML_SCHEMA_ELEM_INFO_NILLED;
21541 }
21542 }
21543 }
21544 }
21545 /*
21546 * cvc-elt (3.3.4) : 4
21547 * Handle 'xsi:type'.
21548 */
21549 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21550 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21551 if (iattr) {
21552 xmlSchemaTypePtr localType = NULL;
21553
21554 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
21555 elemDecl);
21556 if (ret != 0) {
21557 if (ret == -1) {
21558 VERROR_INT("xmlSchemaValidateElemDecl",
21559 "calling xmlSchemaProcessXSIType() to "
21560 "process the attribute 'xsi:type'");
21561 return (-1);
21562 }
21563 /* Does not return an error on purpose. */
21564 }
21565 if (localType != NULL) {
21566 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
21567 actualType = localType;
21568 }
21569 }
21570 }
21571 /*
21572 * IDC: Register identity-constraint XPath matchers.
21573 */
21574 if ((elemDecl->idcs != NULL) &&
21575 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
21576 return (-1);
21577 /*
21578 * No actual type definition.
21579 */
21580 if (actualType == NULL) {
21581 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21582 "The type definition is absent");
21583 return (XML_SCHEMAV_CVC_TYPE_1);
21584 }
21585 /*
21586 * Remember the actual type definition.
21587 */
21588 vctxt->inode->typeDef = actualType;
21589
21590 return (0);
21591}
21592
21593static int
21594xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
21595{
21596 xmlSchemaAttrInfoPtr iattr;
21597 int ret = 0, i;
21598
21599 /*
21600 * SPEC cvc-type (3.1.1)
21601 * "The attributes of must be empty, excepting those whose namespace
21602 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
21603 * whose local name is one of type, nil, schemaLocation or
21604 * noNamespaceSchemaLocation."
21605 */
21606 if (vctxt->nbAttrInfos == 0)
21607 return (0);
21608 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21609 iattr = vctxt->attrInfos[i];
21610 if (! iattr->metaType) {
21611 ACTIVATE_ATTRIBUTE(iattr)
21612 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21613 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
21614 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
21615 }
21616 }
21617 ACTIVATE_ELEM
21618 return (ret);
21619}
21620
21621/*
21622* Cleanup currently used attribute infos.
21623*/
21624static void
21625xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
21626{
21627 int i;
21628 xmlSchemaAttrInfoPtr attr;
21629
21630 if (vctxt->nbAttrInfos == 0)
21631 return;
21632 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21633 attr = vctxt->attrInfos[i];
21634 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21635 if (attr->localName != NULL)
21636 xmlFree((xmlChar *) attr->localName);
21637 if (attr->nsName != NULL)
21638 xmlFree((xmlChar *) attr->nsName);
21639 }
21640 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21641 if (attr->value != NULL)
21642 xmlFree((xmlChar *) attr->value);
21643 }
21644 if (attr->val != NULL) {
21645 xmlSchemaFreeValue(attr->val);
21646 attr->val = NULL;
21647 }
21648 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
21649 }
21650 vctxt->nbAttrInfos = 0;
21651}
21652
21653/*
21654* 3.4.4 Complex Type Definition Validation Rules
21655* Element Locally Valid (Complex Type) (cvc-complex-type)
21656* 3.2.4 Attribute Declaration Validation Rules
21657* Validation Rule: Attribute Locally Valid (cvc-attribute)
21658* Attribute Locally Valid (Use) (cvc-au)
21659*
21660* Only "assessed" attribute information items will be visible to
21661* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
21662*/
21663static int
21664xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
21665{
21666 xmlSchemaTypePtr type = vctxt->inode->typeDef;
21667 xmlSchemaAttributeLinkPtr attrUseLink;
21668 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
21669 xmlSchemaAttrInfoPtr attr, tmpAttr;
21670 int i, found, nbAttrs;
21671 int xpathRes = 0, res, wildIDs = 0, fixed;
21672
21673 /*
21674 * SPEC (cvc-attribute)
21675 * (1) "The declaration must not be ·absent· (see Missing
21676 * Sub-components (§5.3) for how this can fail to be
21677 * the case)."
21678 * (2) "Its {type definition} must not be absent."
21679 *
21680 * NOTE (1) + (2): This is not handled here, since we currently do not
21681 * allow validation against schemas which have missing sub-components.
21682 *
21683 * SPEC (cvc-complex-type)
21684 * (3) "For each attribute information item in the element information
21685 * item's [attributes] excepting those whose [namespace name] is
21686 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
21687 * [local name] is one of type, nil, schemaLocation or
21688 * noNamespaceSchemaLocation, the appropriate case among the following
21689 * must be true:
21690 *
21691 */
21692 nbAttrs = vctxt->nbAttrInfos;
21693 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
21694 attrUseLink = attrUseLink->next) {
21695
21696 found = 0;
21697 attrUse = attrUseLink->attr;
21698 /*
21699 * VAL TODO: Implement a real "attribute use" component.
21700 */
21701 if (attrUse->refDecl != NULL)
21702 attrDecl = attrUse->refDecl;
21703 else
21704 attrDecl = attrUse;
21705 for (i = 0; i < nbAttrs; i++) {
21706 attr = vctxt->attrInfos[i];
21707 /*
21708 * SPEC (cvc-complex-type) (3)
21709 * Skip meta attributes.
21710 */
21711 if (attr->metaType)
21712 continue;
21713 if (attr->localName[0] != attrDecl->name[0])
21714 continue;
21715 if (!xmlStrEqual(attr->localName, attrDecl->name))
21716 continue;
21717 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
21718 continue;
21719 found = 1;
21720 /*
21721 * SPEC (cvc-complex-type)
21722 * (3.1) "If there is among the {attribute uses} an attribute
21723 * use with an {attribute declaration} whose {name} matches
21724 * the attribute information item's [local name] and whose
21725 * {target namespace} is identical to the attribute information
21726 * item's [namespace name] (where an ·absent· {target namespace}
21727 * is taken to be identical to a [namespace name] with no value),
21728 * then the attribute information must be ·valid· with respect
21729 * to that attribute use as per Attribute Locally Valid (Use)
21730 * (§3.5.4). In this case the {attribute declaration} of that
21731 * attribute use is the ·context-determined declaration· for the
21732 * attribute information item with respect to Schema-Validity
21733 * Assessment (Attribute) (§3.2.4) and
21734 * Assessment Outcome (Attribute) (§3.2.5).
21735 */
21736 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21737 attr->use = attrUse;
21738 /*
21739 * Context-determined declaration.
21740 */
21741 attr->decl = attrDecl;
21742 attr->typeDef = attrDecl->subtypes;
21743 break;
21744 }
21745
21746 if (found)
21747 continue;
21748
21749 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21750 /*
21751 * Handle non-existent, required attributes.
21752 *
21753 * SPEC (cvc-complex-type)
21754 * (4) "The {attribute declaration} of each attribute use in
21755 * the {attribute uses} whose {required} is true matches one
21756 * of the attribute information items in the element information
21757 * item's [attributes] as per clause 3.1 above."
21758 */
21759 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21760 if (tmpAttr == NULL) {
21761 VERROR_INT(
21762 "xmlSchemaVAttributesComplex",
21763 "calling xmlSchemaGetFreshAttrInfo()");
21764 return (-1);
21765 }
21766 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
21767 tmpAttr->use = attrUse;
21768 tmpAttr->decl = attrDecl;
21769 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21770 ((attrUse->defValue != NULL) ||
21771 (attrDecl->defValue != NULL))) {
21772 /*
21773 * Handle non-existent, optional, default/fixed attributes.
21774 */
21775 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21776 if (tmpAttr == NULL) {
21777 VERROR_INT(
21778 "xmlSchemaVAttributesComplex",
21779 "calling xmlSchemaGetFreshAttrInfo()");
21780 return (-1);
21781 }
21782 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
21783 tmpAttr->use = attrUse;
21784 tmpAttr->decl = attrDecl;
21785 tmpAttr->typeDef = attrDecl->subtypes;
21786 tmpAttr->localName = attrDecl->name;
21787 tmpAttr->nsName = attrDecl->targetNamespace;
21788 }
21789 }
21790 if (vctxt->nbAttrInfos == 0)
21791 return (0);
21792 /*
21793 * Validate against the wildcard.
21794 */
21795 if (type->attributeWildcard != NULL) {
21796 /*
21797 * SPEC (cvc-complex-type)
21798 * (3.2.1) "There must be an {attribute wildcard}."
21799 */
21800 for (i = 0; i < nbAttrs; i++) {
21801 attr = vctxt->attrInfos[i];
21802 /*
21803 * SPEC (cvc-complex-type) (3)
21804 * Skip meta attributes.
21805 */
21806 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
21807 continue;
21808 /*
21809 * SPEC (cvc-complex-type)
21810 * (3.2.2) "The attribute information item must be ·valid· with
21811 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
21812 *
21813 * SPEC Item Valid (Wildcard) (cvc-wildcard)
21814 * "... its [namespace name] must be ·valid· with respect to
21815 * the wildcard constraint, as defined in Wildcard allows
21816 * Namespace Name (§3.10.4)."
21817 */
21818 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
21819 attr->nsName)) {
21820 /*
21821 * Handle processContents.
21822 *
21823 * SPEC (cvc-wildcard):
21824 * processContents | context-determined declaration:
21825 * "strict" "mustFind"
21826 * "lax" "none"
21827 * "skip" "skip"
21828 */
21829 if (type->attributeWildcard->processContents ==
21830 XML_SCHEMAS_ANY_SKIP) {
21831 /*
21832 * context-determined declaration = "skip"
21833 *
21834 * SPEC PSVI Assessment Outcome (Attribute)
21835 * [validity] = "notKnown"
21836 * [validation attempted] = "none"
21837 */
21838 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
21839 continue;
21840 }
21841 /*
21842 * Find an attribute declaration.
21843 */
21844 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
21845 attr->localName, attr->nsName);
21846 if (attr->decl != NULL) {
21847 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21848 /*
21849 * SPEC (cvc-complex-type)
21850 * (5) "Let [Definition:] the wild IDs be the set of
21851 * all attribute information item to which clause 3.2
21852 * applied and whose ·validation· resulted in a
21853 * ·context-determined declaration· of mustFind or no
21854 * ·context-determined declaration· at all, and whose
21855 * [local name] and [namespace name] resolve (as
21856 * defined by QName resolution (Instance) (§3.15.4)) to
21857 * an attribute declaration whose {type definition} is
21858 * or is derived from ID. Then all of the following
21859 * must be true:"
21860 */
21861 attr->typeDef = attr->decl->subtypes;
21862 if (xmlSchemaIsDerivedFromBuiltInType(
21863 attr->typeDef, XML_SCHEMAS_ID)) {
21864 /*
21865 * SPEC (5.1) "There must be no more than one
21866 * item in ·wild IDs·."
21867 */
21868 if (wildIDs != 0) {
21869 /* VAL TODO */
21870 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
21871 TODO
21872 continue;
21873 }
21874 wildIDs++;
21875 /*
21876 * SPEC (cvc-complex-type)
21877 * (5.2) "If ·wild IDs· is non-empty, there must not
21878 * be any attribute uses among the {attribute uses}
21879 * whose {attribute declaration}'s {type definition}
21880 * is or is derived from ID."
21881 */
21882 for (attrUseLink = type->attributeUses;
21883 attrUseLink != NULL;
21884 attrUseLink = attrUseLink->next) {
21885 if (xmlSchemaIsDerivedFromBuiltInType(
21886 attrUseLink->attr->subtypes,
21887 XML_SCHEMAS_ID)) {
21888 /* VAL TODO */
21889 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
21890 TODO
21891 }
21892 }
21893 }
21894 } else if (type->attributeWildcard->processContents ==
21895 XML_SCHEMAS_ANY_LAX) {
21896 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
21897 /*
21898 * SPEC PSVI Assessment Outcome (Attribute)
21899 * [validity] = "notKnown"
21900 * [validation attempted] = "none"
21901 */
21902 } else {
21903 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
21904 }
21905 }
21906 }
21907 }
21908
21909
21910 if (vctxt->nbAttrInfos == 0)
21911 return (0);
21912
21913 /*
21914 * Validate values, create default attributes, evaluate IDCs.
21915 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021916 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21917 attr = vctxt->attrInfos[i];
21918 /*
21919 * VAL TODO: Note that we won't try to resolve IDCs to
21920 * "lax" and "skip" validated attributes. Check what to
21921 * do in this case.
21922 */
21923 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
21924 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
21925 continue;
21926 /*
21927 * VAL TODO: What to do if the type definition is missing?
21928 */
21929 if (attr->typeDef == NULL) {
21930 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
21931 continue;
21932 }
21933
21934 ACTIVATE_ATTRIBUTE(attr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021935 fixed = 0;
21936 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021937
21938 if (vctxt->xpathStates != NULL) {
21939 /*
21940 * Evaluate IDCs.
21941 */
21942 xpathRes = xmlSchemaXPathEvaluate(vctxt,
21943 XML_ATTRIBUTE_NODE);
21944 if (xpathRes == -1) {
21945 VERROR_INT("xmlSchemaVAttributesComplex",
21946 "calling xmlSchemaXPathEvaluate()");
21947 goto internal_error;
21948 }
21949 }
21950
21951 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
21952 /*
21953 * Default/fixed attributes.
21954 */
21955 if (xpathRes) {
21956 if (attr->use->defValue == NULL) {
21957 attr->value = (xmlChar *) attr->use->defValue;
21958 attr->val = attr->use->defVal;
21959 } else {
21960 attr->value = (xmlChar *) attr->decl->defValue;
21961 attr->val = attr->decl->defVal;
21962 }
21963 /*
21964 * IDCs will consume the precomputed default value,
21965 * so we need to clone it.
21966 */
21967 if (attr->val == NULL) {
21968 VERROR_INT("xmlSchemaVAttributesComplex",
21969 "default/fixed value on an attribute use was "
21970 "not precomputed");
21971 goto internal_error;
21972 }
21973 attr->val = xmlSchemaCopyValue(attr->val);
21974 if (attr->val == NULL) {
21975 VERROR_INT("xmlSchemaVAttributesComplex",
21976 "calling xmlSchemaCopyValue()");
21977 goto internal_error;
21978 }
21979 }
21980 /*
21981 * PSVI: Add the default attribute to the current element.
21982 * VAL TODO: Should we use the *normalized* value? This currently
21983 * uses the *initial* value.
21984 */
21985 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
21986 (attr->node != NULL) && (attr->node->doc != NULL)) {
21987 xmlChar *normValue;
21988 const xmlChar *value;
21989
21990 value = attr->value;
21991 /*
21992 * Normalize the value.
21993 */
21994 normValue = xmlSchemaNormalizeValue(attr->typeDef,
21995 attr->value);
21996 if (normValue != NULL)
21997 value = BAD_CAST normValue;
21998
21999 if (attr->nsName == NULL) {
22000 if (xmlNewProp(attr->node->parent,
22001 attr->localName, value) == NULL) {
22002 VERROR_INT("xmlSchemaVAttributesComplex",
22003 "callling xmlNewProp()");
22004 if (normValue != NULL)
22005 xmlFree(normValue);
22006 goto internal_error;
22007 }
22008 } else {
22009 xmlNsPtr ns;
22010
22011 ns = xmlSearchNsByHref(attr->node->doc,
22012 attr->node->parent, attr->nsName);
22013 if (ns == NULL) {
22014 xmlChar prefix[12];
22015 int counter = 0;
22016
22017 /*
22018 * Create a namespace declaration on the validation
22019 * root node if no namespace declaration is in scope.
22020 */
22021 do {
22022 snprintf((char *) prefix, 12, "p%d", counter++);
22023 ns = xmlSearchNs(attr->node->doc,
22024 attr->node->parent, BAD_CAST prefix);
22025 if (counter > 1000) {
22026 VERROR_INT(
22027 "xmlSchemaVAttributesComplex",
22028 "could not compute a ns prefix for a "
22029 "default/fixed attribute");
22030 if (normValue != NULL)
22031 xmlFree(normValue);
22032 goto internal_error;
22033 }
22034 } while (ns != NULL);
22035 ns = xmlNewNs(vctxt->validationRoot,
22036 attr->nsName, BAD_CAST prefix);
22037 }
22038 xmlNewNsProp(attr->node->parent, ns,
22039 attr->localName, value);
22040 }
22041 if (normValue != NULL)
22042 xmlFree(normValue);
22043 }
22044 /*
22045 * Go directly to IDC evaluation.
22046 */
22047 goto eval_idcs;
22048 }
22049 /*
22050 * Validate the value.
22051 */
22052 if (vctxt->value != NULL) {
22053 /*
22054 * Free last computed value; just for safety reasons.
22055 */
22056 xmlSchemaFreeValue(vctxt->value);
22057 vctxt->value = NULL;
22058 }
22059 /*
22060 * Note that the attribute *use* can be unavailable, if
22061 * the attribute was a wild attribute.
22062 */
22063 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
22064 ((attr->use != NULL) &&
22065 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
22066 fixed = 1;
22067 else
22068 fixed = 0;
22069 /*
22070 * SPEC (cvc-attribute)
22071 * (3) "The item's ·normalized value· must be locally ·valid·
22072 * with respect to that {type definition} as per
22073 * String Valid (§3.14.4)."
22074 *
22075 * VAL TODO: Do we already have the
22076 * "normalized attribute value" here?
22077 */
22078 if (xpathRes || fixed) {
22079 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22080 /*
22081 * Request a computed value.
22082 */
22083 res = xmlSchemaVCheckCVCSimpleType(
22084 (xmlSchemaAbstractCtxtPtr) vctxt,
22085 attr->node, attr->typeDef, attr->value, &(attr->val),
22086 1, 1, 0);
22087 } else {
22088 res = xmlSchemaVCheckCVCSimpleType(
22089 (xmlSchemaAbstractCtxtPtr) vctxt,
22090 attr->node, attr->typeDef, attr->value, NULL,
22091 1, 0, 0);
22092 }
22093
22094 if (res != 0) {
22095 if (res == -1) {
22096 VERROR_INT("xmlSchemaVAttributesComplex",
22097 "calling xmlSchemaStreamValidateSimpleTypeValue()");
22098 goto internal_error;
22099 }
22100 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
22101 /*
22102 * SPEC PSVI Assessment Outcome (Attribute)
22103 * [validity] = "invalid"
22104 */
22105 goto eval_idcs;
22106 }
22107
22108 if (fixed) {
22109 int ws;
22110 /*
22111 * SPEC Attribute Locally Valid (Use) (cvc-au)
22112 * "For an attribute information item to be·valid·
22113 * with respect to an attribute use its *normalized*
22114 * value· must match the *canonical* lexical
22115 * representation of the attribute use's {value
22116 * constraint}value, if it is present and fixed."
22117 *
22118 * VAL TODO: The requirement for the *canonical* value
22119 * will be removed in XML Schema 1.1.
22120 */
22121 /*
22122 * SPEC Attribute Locally Valid (cvc-attribute)
22123 * (4) "The item's *actual* value· must match the *value* of
22124 * the {value constraint}, if it is present and fixed."
22125 */
22126 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
22127 if (attr->val == NULL) {
22128 /* VAL TODO: A value was not precomputed. */
22129 TODO
22130 goto eval_idcs;
22131 }
22132 if ((attr->use != NULL) &&
22133 (attr->use->defValue != NULL)) {
22134 if (attr->use->defVal == NULL) {
22135 /* VAL TODO: A default value was not precomputed. */
22136 TODO
22137 goto eval_idcs;
22138 }
22139 attr->vcValue = attr->use->defValue;
22140 /*
22141 if (xmlSchemaCompareValuesWhtsp(attr->val,
22142 (xmlSchemaWhitespaceValueType) ws,
22143 attr->use->defVal,
22144 (xmlSchemaWhitespaceValueType) ws) != 0) {
22145 */
22146 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
22147 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
22148 } else {
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000022149 if (attr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022150 /* VAL TODO: A default value was not precomputed. */
22151 TODO
22152 goto eval_idcs;
22153 }
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000022154 attr->vcValue = attr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022155 /*
22156 if (xmlSchemaCompareValuesWhtsp(attr->val,
22157 (xmlSchemaWhitespaceValueType) ws,
22158 attrDecl->defVal,
22159 (xmlSchemaWhitespaceValueType) ws) != 0) {
22160 */
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000022161 if (! xmlSchemaAreValuesEqual(attr->val, attr->decl->defVal))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022162 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
22163 }
22164 /*
22165 * [validity] = "valid"
22166 */
22167 }
22168eval_idcs:
22169 /*
22170 * Evaluate IDCs.
22171 */
22172 if (xpathRes) {
22173 if (xmlSchemaXPathProcessHistory(vctxt,
22174 vctxt->depth +1) == -1) {
22175 VERROR_INT("xmlSchemaVAttributesComplex",
22176 "calling xmlSchemaXPathEvaluate()");
22177 goto internal_error;
22178 }
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000022179 } else if (vctxt->xpathStates != NULL)
22180 xmlSchemaXPathPop(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022181 }
22182
22183 /*
22184 * Report errors.
22185 */
22186 for (i = 0; i < vctxt->nbAttrInfos; i++) {
22187 attr = vctxt->attrInfos[i];
22188 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
22189 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
22190 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
22191 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
22192 continue;
22193 ACTIVATE_ATTRIBUTE(attr);
22194 switch (attr->state) {
22195 case XML_SCHEMAS_ATTR_ERR_MISSING: {
22196 xmlChar *str = NULL;
22197 ACTIVATE_ELEM;
22198 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22199 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
22200 "The attribute '%s' is required but missing",
22201 xmlSchemaFormatQName(&str,
22202 attr->decl->targetNamespace,
22203 attr->decl->name),
22204 NULL);
22205 FREE_AND_NULL(str)
22206 break;
22207 }
22208 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
22209 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
22210 "The type definition is absent");
22211 break;
22212 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
22213 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22214 XML_SCHEMAV_CVC_AU, NULL, NULL,
22215 "The value '%s' does not match the fixed "
22216 "value constraint '%s'",
22217 attr->value, attr->vcValue);
22218 break;
22219 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
22220 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
22221 "No matching global attribute declaration available, but "
22222 "demanded by the strict wildcard");
22223 break;
22224 case XML_SCHEMAS_ATTR_UNKNOWN:
22225 if (attr->metaType)
22226 break;
22227 /*
22228 * MAYBE VAL TODO: One might report different error messages
22229 * for the following errors.
22230 */
22231 if (type->attributeWildcard == NULL) {
22232 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
22233 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
22234 } else {
22235 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
22236 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
22237 }
22238 break;
22239 default:
22240 break;
22241 }
22242 }
22243
22244 ACTIVATE_ELEM;
22245 return (0);
22246internal_error:
22247 ACTIVATE_ELEM;
22248 return (-1);
22249}
22250
22251static int
22252xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
22253 int *skip)
22254{
22255 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
22256 /*
22257 * The namespace of the element was already identified to be
22258 * matching the wildcard.
22259 */
22260 if ((skip == NULL) || (wild == NULL) ||
22261 (wild->type != XML_SCHEMA_TYPE_ANY)) {
22262 VERROR_INT("xmlSchemaValidateElemWildcard",
22263 "bad arguments");
22264 return (-1);
22265 }
22266 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022267 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
22268 /*
22269 * URGENT VAL TODO: Either we need to position the stream to the
22270 * next sibling, or walk the whole subtree.
22271 */
22272 *skip = 1;
22273 return (0);
22274 }
22275 {
22276 xmlSchemaElementPtr decl = NULL;
22277
22278 decl = xmlHashLookup3(vctxt->schema->elemDecl,
22279 vctxt->inode->localName, vctxt->inode->nsName,
22280 NULL);
22281 if (decl != NULL) {
22282 vctxt->inode->decl = decl;
22283 return (0);
22284 }
22285 }
22286 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
22287 /* VAL TODO: Change to proper error code. */
22288 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
22289 "No matching global element declaration available, but "
22290 "demanded by the strict wildcard");
22291 return (vctxt->err);
22292 }
22293 if (vctxt->nbAttrInfos != 0) {
22294 xmlSchemaAttrInfoPtr iattr;
22295 /*
22296 * SPEC Validation Rule: Schema-Validity Assessment (Element)
22297 * (1.2.1.2.1) - (1.2.1.2.3 )
22298 *
22299 * Use the xsi:type attribute for the type definition.
22300 */
22301 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22302 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22303 if (iattr != NULL) {
22304 if (xmlSchemaProcessXSIType(vctxt, iattr,
22305 &(vctxt->inode->typeDef), NULL) == -1) {
22306 VERROR_INT("xmlSchemaValidateElemWildcard",
22307 "calling xmlSchemaProcessXSIType() to "
22308 "process the attribute 'xsi:nil'");
22309 return (-1);
22310 }
22311 /*
22312 * Don't return an error on purpose.
22313 */
22314 return (0);
22315 }
22316 }
22317 /*
22318 * SPEC Validation Rule: Schema-Validity Assessment (Element)
22319 *
22320 * Fallback to "anyType".
22321 */
22322 vctxt->inode->typeDef =
22323 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
22324 return (0);
22325}
22326
22327/*
22328* xmlSchemaCheckCOSValidDefault:
22329*
22330* This will be called if: not nilled, no content and a default/fixed
22331* value is provided.
22332*/
22333
22334static int
22335xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
22336 const xmlChar *value,
22337 xmlSchemaValPtr *val)
22338{
22339 int ret = 0;
22340 xmlSchemaNodeInfoPtr inode = vctxt->inode;
22341
22342 /*
22343 * cos-valid-default:
22344 * Schema Component Constraint: Element Default Valid (Immediate)
22345 * For a string to be a valid default with respect to a type
22346 * definition the appropriate case among the following must be true:
22347 */
22348 if IS_COMPLEX_TYPE(inode->typeDef) {
22349 /*
22350 * Complex type.
22351 *
22352 * SPEC (2.1) "its {content type} must be a simple type definition
22353 * or mixed."
22354 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
22355 * type}'s particle must be ·emptiable· as defined by
22356 * Particle Emptiable (§3.9.6)."
22357 */
22358 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
22359 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
22360 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
22361 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
22362 /* NOTE that this covers (2.2.2) as well. */
22363 VERROR(ret, NULL,
22364 "For a string to be a valid default, the type definition "
22365 "must be a simple type or a complex type with simple content "
22366 "or mixed content and a particle emptiable");
22367 return(ret);
22368 }
22369 }
22370 /*
22371 * 1 If the type definition is a simple type definition, then the string
22372 * must be ·valid· with respect to that definition as defined by String
22373 * Valid (§3.14.4).
22374 *
22375 * AND
22376 *
22377 * 2.2.1 If the {content type} is a simple type definition, then the
22378 * string must be ·valid· with respect to that simple type definition
22379 * as defined by String Valid (§3.14.4).
22380 */
22381 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22382
22383 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22384 NULL, inode->typeDef, value, val, 1, 1, 0);
22385
22386 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22387
22388 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22389 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
22390 }
22391 if (ret < 0) {
22392 VERROR_INT("xmlSchemaCheckCOSValidDefault",
22393 "calling xmlSchemaVCheckCVCSimpleType()");
22394 }
22395 return (ret);
22396}
22397
22398static void
22399xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22400 const xmlChar * name ATTRIBUTE_UNUSED,
22401 xmlSchemaElementPtr item,
22402 xmlSchemaNodeInfoPtr inode)
22403{
22404 inode->decl = item;
22405#ifdef DEBUG_CONTENT
22406 {
22407 xmlChar *str = NULL;
22408
22409 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
22410 xmlGenericError(xmlGenericErrorContext,
22411 "AUTOMATON callback for '%s' [declaration]\n",
22412 xmlSchemaFormatQName(&str,
22413 inode->localName, inode->nsName));
22414 } else {
22415 xmlGenericError(xmlGenericErrorContext,
22416 "AUTOMATON callback for '%s' [wildcard]\n",
22417 xmlSchemaFormatQName(&str,
22418 inode->localName, inode->nsName));
22419
22420 }
22421 FREE_AND_NULL(str)
22422 }
22423#endif
22424}
22425
22426static int
22427xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022428{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022429 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
22430 if (vctxt->inode == NULL) {
22431 VERROR_INT("xmlSchemaValidatorPushElem",
22432 "calling xmlSchemaGetFreshElemInfo()");
22433 return (-1);
22434 }
22435 vctxt->nbAttrInfos = 0;
22436 return (0);
22437}
22438
22439static int
22440xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
22441 xmlSchemaNodeInfoPtr inode,
22442 xmlSchemaTypePtr type,
22443 const xmlChar *value)
22444{
22445 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
22446 return (xmlSchemaVCheckCVCSimpleType(
22447 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22448 type, value, &(inode->val), 1, 1, 0));
22449 else
22450 return (xmlSchemaVCheckCVCSimpleType(
22451 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22452 type, value, NULL, 1, 0, 0));
22453}
22454
22455
22456
22457/*
22458* Process END of element.
22459*/
22460static int
22461xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
22462{
22463 int ret = 0;
22464 xmlSchemaNodeInfoPtr inode = vctxt->inode;
22465
22466 if (vctxt->nbAttrInfos != 0)
22467 xmlSchemaClearAttrInfos(vctxt);
22468 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
22469 /*
22470 * This element was not expected;
22471 * we will not validate child elements of broken parents.
22472 * Skip validation of all content of the parent.
22473 */
22474 vctxt->skipDepth = vctxt->depth -1;
22475 goto end_elem;
22476 }
22477 if ((inode->typeDef == NULL) ||
22478 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
22479 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022480 * 1. the type definition might be missing if the element was
22481 * error prone
22482 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022483 */
22484 goto end_elem;
22485 }
22486 /*
22487 * Check the content model.
22488 */
22489 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
22490 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
22491
22492 /*
22493 * Workaround for "anyType".
22494 */
22495 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
22496 goto character_content;
22497
22498 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
22499 xmlChar *values[10];
22500 int terminal, nbval = 10, nbneg;
22501
22502 if (inode->regexCtxt == NULL) {
22503 /*
22504 * Create the regex context.
22505 */
22506 inode->regexCtxt =
22507 xmlRegNewExecCtxt(inode->typeDef->contModel,
22508 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22509 vctxt);
22510 if (inode->regexCtxt == NULL) {
22511 VERROR_INT("xmlSchemaValidatorPopElem",
22512 "failed to create a regex context");
22513 goto internal_error;
22514 }
22515#ifdef DEBUG_AUTOMATA
22516 xmlGenericError(xmlGenericErrorContext,
22517 "AUTOMATON create on '%s'\n", inode->localName);
22518#endif
22519 }
22520 /*
22521 * Get hold of the still expected content, since a further
22522 * call to xmlRegExecPushString() will loose this information.
22523 */
22524 xmlRegExecNextValues(inode->regexCtxt,
22525 &nbval, &nbneg, &values[0], &terminal);
22526 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
22527 if (ret <= 0) {
22528 /*
22529 * Still missing something.
22530 */
22531 ret = 1;
22532 inode->flags |=
22533 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22534 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22535 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
22536 "Missing child element(s)",
22537 nbval, nbneg, values);
22538#ifdef DEBUG_AUTOMATA
22539 xmlGenericError(xmlGenericErrorContext,
22540 "AUTOMATON missing ERROR on '%s'\n",
22541 inode->localName);
22542#endif
22543 } else {
22544 /*
22545 * Content model is satisfied.
22546 */
22547 ret = 0;
22548#ifdef DEBUG_AUTOMATA
22549 xmlGenericError(xmlGenericErrorContext,
22550 "AUTOMATON succeeded on '%s'\n",
22551 inode->localName);
22552#endif
22553 }
22554
22555 }
22556 }
22557 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
22558 goto end_elem;
22559
22560character_content:
22561
22562 if (vctxt->value != NULL) {
22563 xmlSchemaFreeValue(vctxt->value);
22564 vctxt->value = NULL;
22565 }
22566 /*
22567 * Check character content.
22568 */
22569 if (inode->decl == NULL) {
22570 /*
22571 * Speedup if no declaration exists.
22572 */
22573 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22574 ret = xmlSchemaVCheckINodeDataType(vctxt,
22575 inode, inode->typeDef, inode->value);
22576 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22577 ret = xmlSchemaVCheckINodeDataType(vctxt,
22578 inode, inode->typeDef->contentTypeDef,
22579 inode->value);
22580 }
22581 if (ret < 0) {
22582 VERROR_INT("xmlSchemaValidatorPopElem",
22583 "calling xmlSchemaVCheckCVCSimpleType()");
22584 goto internal_error;
22585 }
22586 goto end_elem;
22587 }
22588 /*
22589 * cvc-elt (3.3.4) : 5
22590 * The appropriate case among the following must be true:
22591 */
22592 /*
22593 * cvc-elt (3.3.4) : 5.1
22594 * If the declaration has a {value constraint},
22595 * the item has neither element nor character [children] and
22596 * clause 3.2 has not applied, then all of the following must be true:
22597 */
22598 if ((inode->decl->value != NULL) &&
22599 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
22600 (! INODE_NILLED(inode))) {
22601 /*
22602 * cvc-elt (3.3.4) : 5.1.1
22603 * If the ·actual type definition· is a ·local type definition·
22604 * then the canonical lexical representation of the {value constraint}
22605 * value must be a valid default for the ·actual type definition· as
22606 * defined in Element Default Valid (Immediate) (§3.3.6).
22607 */
22608 /*
22609 * NOTE: 'local' above means types aquired by xsi:type.
22610 * NOTE: Although the *canonical* value is stated, it is not
22611 * relevant if canonical or not. Additionally XML Schema 1.1
22612 * will removed this requirement as well.
22613 */
22614 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
22615
22616 ret = xmlSchemaCheckCOSValidDefault(vctxt,
22617 inode->decl->value, &(inode->val));
22618 if (ret != 0) {
22619 if (ret < 0) {
22620 VERROR_INT("xmlSchemaValidatorPopElem",
22621 "calling xmlSchemaCheckCOSValidDefault()");
22622 goto internal_error;
22623 }
22624 goto end_elem;
22625 }
22626 /*
22627 * Stop here, to avoid redundant validation of the value
22628 * (see following).
22629 */
22630 goto default_psvi;
22631 }
22632 /*
22633 * cvc-elt (3.3.4) : 5.1.2
22634 * The element information item with the canonical lexical
22635 * representation of the {value constraint} value used as its
22636 * ·normalized value· must be ·valid· with respect to the
22637 * ·actual type definition· as defined by Element Locally Valid (Type)
22638 * (§3.3.4).
22639 */
22640 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22641 ret = xmlSchemaVCheckINodeDataType(vctxt,
22642 inode, inode->typeDef, inode->decl->value);
22643 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22644 ret = xmlSchemaVCheckINodeDataType(vctxt,
22645 inode, inode->typeDef->contentTypeDef,
22646 inode->decl->value);
22647 }
22648 if (ret != 0) {
22649 if (ret < 0) {
22650 VERROR_INT("xmlSchemaValidatorPopElem",
22651 "calling xmlSchemaVCheckCVCSimpleType()");
22652 goto internal_error;
22653 }
22654 goto end_elem;
22655 }
22656
22657default_psvi:
22658 /*
22659 * PSVI: Create a text node on the instance element.
22660 */
22661 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22662 (inode->node != NULL)) {
22663 xmlNodePtr textChild;
22664 xmlChar *normValue;
22665 /*
22666 * VAL TODO: Normalize the value.
22667 */
22668 normValue = xmlSchemaNormalizeValue(inode->typeDef,
22669 inode->decl->value);
22670 if (normValue != NULL) {
22671 textChild = xmlNewText(BAD_CAST normValue);
22672 xmlFree(normValue);
22673 } else
22674 textChild = xmlNewText(inode->decl->value);
22675 if (textChild == NULL) {
22676 VERROR_INT("xmlSchemaValidatorPopElem",
22677 "calling xmlNewText()");
22678 goto internal_error;
22679 } else
22680 xmlAddChild(inode->node, textChild);
22681 }
22682
22683 } else if (! INODE_NILLED(inode)) {
22684 /*
22685 * 5.2.1 The element information item must be ·valid· with respect
22686 * to the ·actual type definition· as defined by Element Locally
22687 * Valid (Type) (§3.3.4).
22688 */
22689 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22690 /*
22691 * SPEC (cvc-type) (3.1)
22692 * "If the type definition is a simple type definition, ..."
22693 * (3.1.3) "If clause 3.2 of Element Locally Valid
22694 * (Element) (§3.3.4) did not apply, then the ·normalized value·
22695 * must be ·valid· with respect to the type definition as defined
22696 * by String Valid (§3.14.4).
22697 */
22698 ret = xmlSchemaVCheckINodeDataType(vctxt,
22699 inode, inode->typeDef, inode->value);
22700 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22701 /*
22702 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
22703 * definition, then the element information item must be
22704 * ·valid· with respect to the type definition as per
22705 * Element Locally Valid (Complex Type) (§3.4.4);"
22706 *
22707 * SPEC (cvc-complex-type) (2.2)
22708 * "If the {content type} is a simple type definition, ...
22709 * the ·normalized value· of the element information item is
22710 * ·valid· with respect to that simple type definition as
22711 * defined by String Valid (§3.14.4)."
22712 */
22713 ret = xmlSchemaVCheckINodeDataType(vctxt,
22714 inode, inode->typeDef->contentTypeDef, inode->value);
22715 }
22716 if (ret != 0) {
22717 if (ret < 0) {
22718 VERROR_INT("xmlSchemaValidatorPopElem",
22719 "calling xmlSchemaVCheckCVCSimpleType()");
22720 goto internal_error;
22721 }
22722 goto end_elem;
22723 }
22724 /*
22725 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
22726 * not applied, all of the following must be true:
22727 */
22728 if ((inode->decl->value != NULL) &&
22729 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
22730
22731 /*
22732 * TODO: We will need a computed value, when comparison is
22733 * done on computed values.
22734 */
22735 /*
22736 * 5.2.2.1 The element information item must have no element
22737 * information item [children].
22738 */
22739 if (inode->flags &
22740 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
22741 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
22742 VERROR(ret, NULL,
22743 "The content must not containt element nodes since "
22744 "there is a fixed value constraint");
22745 goto end_elem;
22746 } else {
22747 /*
22748 * 5.2.2.2 The appropriate case among the following must
22749 * be true:
22750 */
22751 if (HAS_MIXED_CONTENT(inode->typeDef)) {
22752 /*
22753 * 5.2.2.2.1 If the {content type} of the ·actual type
22754 * definition· is mixed, then the *initial value* of the
22755 * item must match the canonical lexical representation
22756 * of the {value constraint} value.
22757 *
22758 * ... the *initial value* of an element information
22759 * item is the string composed of, in order, the
22760 * [character code] of each character information item in
22761 * the [children] of that element information item.
22762 */
22763 if (! xmlStrEqual(inode->value, inode->decl->value)){
22764 /*
22765 * VAL TODO: Report invalid & expected values as well.
22766 * VAL TODO: Implement the canonical stuff.
22767 */
22768 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
22769 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22770 ret, NULL, NULL,
22771 "The initial value '%s' does not match the fixed "
22772 "value constraint '%s'",
22773 inode->value, inode->decl->value);
22774 goto end_elem;
22775 }
22776 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22777 /*
22778 * 5.2.2.2.2 If the {content type} of the ·actual type
22779 * definition· is a simple type definition, then the
22780 * *actual value* of the item must match the canonical
22781 * lexical representation of the {value constraint} value.
22782 */
22783 /*
22784 * VAL TODO: *actual value* is the normalized value, impl.
22785 * this.
22786 * VAL TODO: Report invalid & expected values as well.
22787 * VAL TODO: Implement a comparison with the computed values.
22788 */
22789 if (! xmlStrEqual(inode->value,
22790 inode->decl->value)) {
22791 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
22792 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22793 ret, NULL, NULL,
22794 "The actual value '%s' does not match the fixed "
22795 "value constraint '%s'",
22796 inode->value,
22797 inode->decl->value);
22798 goto end_elem;
22799 }
22800 }
22801 }
22802 }
22803 }
22804
22805end_elem:
22806 if (vctxt->depth < 0) {
22807 /* TODO: raise error? */
22808 return (0);
22809 }
22810 if (vctxt->depth == vctxt->skipDepth)
22811 vctxt->skipDepth = -1;
22812 /*
22813 * Evaluate the history of XPath state objects.
22814 */
22815 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
22816 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022817 /*
22818 * TODO: 6 The element information item must be ·valid· with respect to each of
22819 * the {identity-constraint definitions} as per Identity-constraint
22820 * Satisfied (§3.11.4).
22821 */
22822 /*
22823 * Validate IDC keyrefs.
22824 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022825 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
22826 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022827 /*
22828 * Merge/free the IDC table.
22829 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022830 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022831#ifdef DEBUG_IDC
22832 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022833 inode->nsName,
22834 inode->localName,
22835 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022836#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022837 if (vctxt->depth > 0) {
22838 /*
22839 * Merge the IDC node table with the table of the parent node.
22840 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022841 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
22842 goto internal_error;
22843 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022844 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022845 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022846 * Clear the current ielem.
22847 * VAL TODO: Don't free the PSVI IDC tables if they are
22848 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022849 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022850 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022851 /*
22852 * Skip further processing if we are on the validation root.
22853 */
22854 if (vctxt->depth == 0) {
22855 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022856 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022857 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022858 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022859 /*
22860 * Reset the bubbleDepth if needed.
22861 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022862 if (vctxt->aidcs != NULL) {
22863 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
22864 do {
22865 if (aidc->bubbleDepth == vctxt->depth) {
22866 /*
22867 * A bubbleDepth of a key/unique IDC matches the current
22868 * depth, this means that we are leaving the scope of the
22869 * top-most keyref IDC.
22870 */
22871 aidc->bubbleDepth = -1;
22872 }
22873 aidc = aidc->next;
22874 } while (aidc != NULL);
22875 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022876 vctxt->depth--;
22877 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022878 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022879 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022880 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
22881 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022882 return (ret);
22883
22884internal_error:
22885 vctxt->err = -1;
22886 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022887}
22888
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022889/*
22890* 3.4.4 Complex Type Definition Validation Rules
22891* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
22892*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000022893static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022894xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000022895{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022896 xmlSchemaNodeInfoPtr pielem;
22897 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022898 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022899
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022900 if (vctxt->depth <= 0) {
22901 VERROR_INT("xmlSchemaValidateChildElem",
22902 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022903 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022904 }
22905 pielem = vctxt->elemInfos[vctxt->depth -1];
22906 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
22907 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022908 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022909 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022910 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022911 if (INODE_NILLED(pielem)) {
22912 /*
22913 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
22914 */
22915 ACTIVATE_PARENT_ELEM;
22916 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
22917 VERROR(ret, NULL,
22918 "Neither character nor element content is allowed, "
22919 "because the element was 'nilled'");
22920 ACTIVATE_ELEM;
22921 goto unexpected_elem;
22922 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022923
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022924 ptype = pielem->typeDef;
22925
22926 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
22927 /*
22928 * Workaround for "anyType": we have currently no content model
22929 * assigned for "anyType", so handle it explicitely.
22930 * "anyType" has an unbounded, lax "any" wildcard.
22931 */
22932 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22933 vctxt->inode->localName,
22934 vctxt->inode->nsName);
22935
22936 if (vctxt->inode->decl == NULL) {
22937 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022938 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022939 * Process "xsi:type".
22940 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022941 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022942 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22943 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22944 if (iattr != NULL) {
22945 ret = xmlSchemaProcessXSIType(vctxt, iattr,
22946 &(vctxt->inode->typeDef), NULL);
22947 if (ret != 0) {
22948 if (ret == -1) {
22949 VERROR_INT("xmlSchemaValidateChildElem",
22950 "calling xmlSchemaProcessXSIType() to "
22951 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022952 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022953 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022954 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000022955 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022956 } else {
22957 /*
22958 * Fallback to "anyType".
22959 *
22960 * SPEC (cvc-assess-elt)
22961 * "If the item cannot be ·strictly assessed·, [...]
22962 * an element information item's schema validity may be laxly
22963 * assessed if its ·context-determined declaration· is not
22964 * skip by ·validating· with respect to the ·ur-type
22965 * definition· as per Element Locally Valid (Type) (§3.3.4)."
22966 */
22967 vctxt->inode->typeDef =
22968 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022969 }
22970 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022971 return (0);
22972 }
22973
22974 switch (ptype->contentType) {
22975 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022976 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022977 * SPEC (2.1) "If the {content type} is empty, then the
22978 * element information item has no character or element
22979 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022980 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022981 ACTIVATE_PARENT_ELEM
22982 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
22983 VERROR(ret, NULL,
22984 "Element content is not allowed, "
22985 "because the content type is empty");
22986 ACTIVATE_ELEM
22987 goto unexpected_elem;
22988 break;
22989
22990 case XML_SCHEMA_CONTENT_MIXED:
22991 case XML_SCHEMA_CONTENT_ELEMENTS: {
22992 xmlRegExecCtxtPtr regexCtxt;
22993 xmlChar *values[10];
22994 int terminal, nbval = 10, nbneg;
22995
22996 /* VAL TODO: Optimized "anyType" validation.*/
22997
22998 if (ptype->contModel == NULL) {
22999 VERROR_INT("xmlSchemaValidateChildElem",
23000 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023001 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000023002 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023003 /*
23004 * Safety belf for evaluation if the cont. model was already
23005 * examined to be invalid.
23006 */
23007 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
23008 VERROR_INT("xmlSchemaValidateChildElem",
23009 "validating elem, but elem content is already invalid");
23010 return (-1);
23011 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000023012
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023013 regexCtxt = pielem->regexCtxt;
23014 if (regexCtxt == NULL) {
23015 /*
23016 * Create the regex context.
23017 */
23018 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
23019 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
23020 vctxt);
23021 if (regexCtxt == NULL) {
23022 VERROR_INT("xmlSchemaValidateChildElem",
23023 "failed to create a regex context");
23024 return (-1);
23025 }
23026 pielem->regexCtxt = regexCtxt;
23027#ifdef DEBUG_AUTOMATA
23028 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
23029 pielem->localName);
23030#endif
23031 }
23032
23033 /*
23034 * SPEC (2.4) "If the {content type} is element-only or mixed,
23035 * then the sequence of the element information item's
23036 * element information item [children], if any, taken in
23037 * order, is ·valid· with respect to the {content type}'s
23038 * particle, as defined in Element Sequence Locally Valid
23039 * (Particle) (§3.9.4)."
23040 */
23041 ret = xmlRegExecPushString2(regexCtxt,
23042 vctxt->inode->localName,
23043 vctxt->inode->nsName,
23044 vctxt->inode);
23045#ifdef DEBUG_AUTOMATA
23046 if (ret < 0)
23047 xmlGenericError(xmlGenericErrorContext,
23048 "AUTOMATON push ERROR for '%s' on '%s'\n",
23049 vctxt->inode->localName, pielem->localName);
23050 else
23051 xmlGenericError(xmlGenericErrorContext,
23052 "AUTOMATON push OK for '%s' on '%s'\n",
23053 vctxt->inode->localName, pielem->localName);
23054#endif
23055 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
23056 VERROR_INT("xmlSchemaValidateChildElem",
23057 "calling xmlRegExecPushString2()");
23058 return (-1);
23059 }
23060 if (ret < 0) {
23061 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
23062 &values[0], &terminal);
23063 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
23064 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
23065 "This element is not expected",
23066 nbval, nbneg, values);
23067 ret = vctxt->err;
23068 goto unexpected_elem;
23069 } else
23070 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000023071 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023072 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023073 case XML_SCHEMA_CONTENT_SIMPLE:
23074 case XML_SCHEMA_CONTENT_BASIC:
23075 ACTIVATE_PARENT_ELEM
23076 if (IS_COMPLEX_TYPE(ptype)) {
23077 /*
23078 * SPEC (cvc-complex-type) (2.2)
23079 * "If the {content type} is a simple type definition, then
23080 * the element information item has no element information
23081 * item [children], ..."
23082 */
23083 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
23084 VERROR(ret, NULL, "Element content is not allowed, "
23085 "because the content type is a simple type definition");
23086 } else {
23087 /*
23088 * SPEC (cvc-type) (3.1.2) "The element information item must
23089 * have no element information item [children]."
23090 */
23091 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
23092 VERROR(ret, NULL, "Element content is not allowed, "
23093 "because the type definition is simple");
23094 }
23095 ACTIVATE_ELEM
23096 ret = vctxt->err;
23097 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023098 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023099
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023100 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023101 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023102 }
23103 return (ret);
23104unexpected_elem:
23105 /*
23106 * Pop this element and set the skipDepth to skip
23107 * all further content of the parent element.
23108 */
23109 vctxt->skipDepth = vctxt->depth;
23110 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
23111 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
23112 return (ret);
23113}
23114
23115#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
23116#define XML_SCHEMA_PUSH_TEXT_CREATED 2
23117#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
23118
23119static int
23120xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
23121 int nodeType, const xmlChar *value, int len,
23122 int mode, int *consumed)
23123{
23124 /*
23125 * Unfortunately we have to duplicate the text sometimes.
23126 * OPTIMIZE: Maybe we could skip it, if:
23127 * 1. content type is simple
23128 * 2. whitespace is "collapse"
23129 * 3. it consists of whitespace only
23130 *
23131 * Process character content.
23132 */
23133 if (consumed != NULL)
23134 *consumed = 0;
23135 if (INODE_NILLED(vctxt->inode)) {
23136 /*
23137 * SPEC cvc-elt (3.3.4 - 3.2.1)
23138 * "The element information item must have no character or
23139 * element information item [children]."
23140 */
23141 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
23142 "Neither character nor element content is allowed "
23143 "because the element is 'nilled'");
23144 return (vctxt->err);
23145 }
23146 /*
23147 * SPEC (2.1) "If the {content type} is empty, then the
23148 * element information item has no character or element
23149 * information item [children]."
23150 */
23151 if (vctxt->inode->typeDef->contentType ==
23152 XML_SCHEMA_CONTENT_EMPTY) {
23153 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
23154 "Character content is not allowed, "
23155 "because the content type is empty");
23156 return (vctxt->err);
23157 }
23158
23159 if (vctxt->inode->typeDef->contentType ==
23160 XML_SCHEMA_CONTENT_ELEMENTS) {
23161 if ((nodeType != XML_TEXT_NODE) ||
23162 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
23163 /*
23164 * SPEC cvc-complex-type (2.3)
23165 * "If the {content type} is element-only, then the
23166 * element information item has no character information
23167 * item [children] other than those whose [character
23168 * code] is defined as a white space in [XML 1.0 (Second
23169 * Edition)]."
23170 */
23171 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
23172 "Character content other than whitespace is not allowed "
23173 "because the content type is 'element-only'");
23174 return (vctxt->err);
23175 }
23176 return (0);
23177 }
23178
23179 if ((value == NULL) || (value[0] == 0))
23180 return (0);
23181 /*
23182 * Save the value.
23183 * NOTE that even if the content type is *mixed*, we need the
23184 * *initial value* for default/fixed value constraints.
23185 */
23186 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
23187 ((vctxt->inode->decl == NULL) ||
23188 (vctxt->inode->decl->value == NULL)))
23189 return (0);
23190
23191 if (vctxt->inode->value == NULL) {
23192 /*
23193 * Set the value.
23194 */
23195 switch (mode) {
23196 case XML_SCHEMA_PUSH_TEXT_PERSIST:
23197 /*
23198 * When working on a tree.
23199 */
23200 vctxt->inode->value = value;
23201 break;
23202 case XML_SCHEMA_PUSH_TEXT_CREATED:
23203 /*
23204 * When working with the reader.
23205 * The value will be freed by the element info.
23206 */
23207 vctxt->inode->value = value;
23208 if (consumed != NULL)
23209 *consumed = 1;
23210 vctxt->inode->flags |=
23211 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23212 break;
23213 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
23214 /*
23215 * When working with SAX.
23216 * The value will be freed by the element info.
23217 */
23218 if (len != -1)
23219 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
23220 else
23221 vctxt->inode->value = BAD_CAST xmlStrdup(value);
23222 vctxt->inode->flags |=
23223 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23224 break;
23225 default:
23226 break;
23227 }
23228 } else {
23229 /*
23230 * Concat the value.
23231 */
23232 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000023233 vctxt->inode->value = BAD_CAST xmlStrncat(
23234 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023235 } else {
23236 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023237 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023238 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23239 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023240 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023241
23242 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000023243}
23244
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023245static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023246xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000023247{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023248 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000023249
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023250 if ((vctxt->skipDepth != -1) &&
23251 (vctxt->depth >= vctxt->skipDepth)) {
23252 VERROR_INT("xmlSchemaValidateElem",
23253 "in skip-state");
23254 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023255 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023256 if (vctxt->xsiAssemble) {
23257 if (xmlSchemaAssembleByXSI(vctxt) == -1)
23258 goto internal_error;
23259 }
23260 if (vctxt->depth > 0) {
23261 /*
23262 * Validate this element against the content model
23263 * of the parent.
23264 */
23265 ret = xmlSchemaValidateChildElem(vctxt);
23266 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023267 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023268 VERROR_INT("xmlSchemaValidateElem",
23269 "calling xmlSchemaStreamValidateChildElement()");
23270 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023271 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023272 goto exit;
23273 }
23274 if (vctxt->depth == vctxt->skipDepth)
23275 goto exit;
23276 if ((vctxt->inode->decl == NULL) &&
23277 (vctxt->inode->typeDef == NULL)) {
23278 VERROR_INT("xmlSchemaValidateElem",
23279 "the child element was valid but neither the "
23280 "declaration nor the type was set");
23281 goto internal_error;
23282 }
23283 } else {
23284 /*
23285 * Get the declaration of the validation root.
23286 */
23287 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
23288 vctxt->inode->localName,
23289 vctxt->inode->nsName);
23290 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000023291 ret = XML_SCHEMAV_CVC_ELT_1;
23292 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023293 "No matching global declaration available "
23294 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023295 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023296 }
23297 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023298
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023299 if (vctxt->inode->decl == NULL)
23300 goto type_validation;
23301
23302 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
23303 int skip;
23304 /*
23305 * Wildcards.
23306 */
23307 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
23308 if (ret != 0) {
23309 if (ret < 0) {
23310 VERROR_INT("xmlSchemaValidateElem",
23311 "calling xmlSchemaValidateElemWildcard()");
23312 goto internal_error;
23313 }
23314 goto exit;
23315 }
23316 if (skip) {
23317 vctxt->skipDepth = vctxt->depth;
23318 goto exit;
23319 }
23320 /*
23321 * The declaration might be set by the wildcard validation,
23322 * when the processContents is "lax" or "strict".
23323 */
23324 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
23325 /*
23326 * Clear the "decl" field to not confuse further processing.
23327 */
23328 vctxt->inode->decl = NULL;
23329 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023330 }
Daniel Veillard4255d502002-04-16 15:50:10 +000023331 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023332 /*
23333 * Validate against the declaration.
23334 */
23335 ret = xmlSchemaValidateElemDecl(vctxt);
23336 if (ret != 0) {
23337 if (ret < 0) {
23338 VERROR_INT("xmlSchemaValidateElem",
23339 "calling xmlSchemaValidateElemDecl()");
23340 goto internal_error;
23341 }
23342 goto exit;
23343 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000023344 /*
23345 * Validate against the type definition.
23346 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023347type_validation:
23348
23349 if (vctxt->inode->typeDef == NULL) {
23350 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
23351 ret = XML_SCHEMAV_CVC_TYPE_1;
23352 VERROR(ret, NULL,
23353 "The type definition is absent");
23354 goto exit;
23355 }
23356 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
23357 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
23358 ret = XML_SCHEMAV_CVC_TYPE_2;
23359 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023360 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023361 goto exit;
23362 }
23363 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000023364 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023365 * during validation against the declaration. This must be done
23366 * _before_ attribute validation.
23367 */
23368 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
23369 if (ret == -1) {
23370 VERROR_INT("xmlSchemaValidateElem",
23371 "calling xmlSchemaXPathEvaluate()");
23372 goto internal_error;
23373 }
23374 /*
23375 * Validate attributes.
23376 */
23377 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
23378 if ((vctxt->nbAttrInfos != 0) ||
23379 (vctxt->inode->typeDef->attributeUses != NULL)) {
23380
23381 ret = xmlSchemaVAttributesComplex(vctxt);
23382 }
23383 } else if (vctxt->nbAttrInfos != 0) {
23384
23385 ret = xmlSchemaVAttributesSimple(vctxt);
23386 }
23387 /*
23388 * Clear registered attributes.
23389 */
23390 if (vctxt->nbAttrInfos != 0)
23391 xmlSchemaClearAttrInfos(vctxt);
23392 if (ret == -1) {
23393 VERROR_INT("xmlSchemaValidateElem",
23394 "calling attributes validation");
23395 goto internal_error;
23396 }
23397 /*
23398 * Don't return an error if attributes are invalid on purpose.
23399 */
23400 ret = 0;
23401
23402exit:
23403 if (ret != 0)
23404 vctxt->skipDepth = vctxt->depth;
23405 return (ret);
23406internal_error:
23407 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023408}
23409
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023410#ifdef XML_SCHEMA_READER_ENABLED
23411static int
23412xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023413{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023414 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
23415 int depth, nodeType, ret = 0, consumed;
23416 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023417
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023418 vctxt->depth = -1;
23419 ret = xmlTextReaderRead(vctxt->reader);
23420 /*
23421 * Move to the document element.
23422 */
23423 while (ret == 1) {
23424 nodeType = xmlTextReaderNodeType(vctxt->reader);
23425 if (nodeType == XML_ELEMENT_NODE)
23426 goto root_found;
23427 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023428 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023429 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023430
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023431root_found:
23432
23433 do {
23434 depth = xmlTextReaderDepth(vctxt->reader);
23435 nodeType = xmlTextReaderNodeType(vctxt->reader);
23436
23437 if (nodeType == XML_ELEMENT_NODE) {
23438
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023439 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023440 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23441 VERROR_INT("xmlSchemaVReaderWalk",
23442 "calling xmlSchemaValidatorPushElem()");
23443 goto internal_error;
23444 }
23445 ielem = vctxt->inode;
23446 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
23447 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
23448 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23449 /*
23450 * Is the element empty?
23451 */
23452 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
23453 if (ret == -1) {
23454 VERROR_INT("xmlSchemaVReaderWalk",
23455 "calling xmlTextReaderIsEmptyElement()");
23456 goto internal_error;
23457 }
23458 if (ret) {
23459 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23460 }
23461 /*
23462 * Register attributes.
23463 */
23464 vctxt->nbAttrInfos = 0;
23465 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
23466 if (ret == -1) {
23467 VERROR_INT("xmlSchemaVReaderWalk",
23468 "calling xmlTextReaderMoveToFirstAttribute()");
23469 goto internal_error;
23470 }
23471 if (ret == 1) {
23472 do {
23473 /*
23474 * VAL TODO: How do we know that the reader works on a
23475 * node tree, to be able to pass a node here?
23476 */
23477 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
23478 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
23479 xmlTextReaderNamespaceUri(vctxt->reader), 1,
23480 xmlTextReaderValue(vctxt->reader), 1) == -1) {
23481
23482 VERROR_INT("xmlSchemaVReaderWalk",
23483 "calling xmlSchemaValidatorPushAttribute()");
23484 goto internal_error;
23485 }
23486 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
23487 if (ret == -1) {
23488 VERROR_INT("xmlSchemaVReaderWalk",
23489 "calling xmlTextReaderMoveToFirstAttribute()");
23490 goto internal_error;
23491 }
23492 } while (ret == 1);
23493 /*
23494 * Back to element position.
23495 */
23496 ret = xmlTextReaderMoveToElement(vctxt->reader);
23497 if (ret == -1) {
23498 VERROR_INT("xmlSchemaVReaderWalk",
23499 "calling xmlTextReaderMoveToElement()");
23500 goto internal_error;
23501 }
23502 }
23503 /*
23504 * Validate the element.
23505 */
23506 ret= xmlSchemaValidateElem(vctxt);
23507 if (ret != 0) {
23508 if (ret == -1) {
23509 VERROR_INT("xmlSchemaVReaderWalk",
23510 "calling xmlSchemaValidateElem()");
23511 goto internal_error;
23512 }
23513 goto exit;
23514 }
23515 if (vctxt->depth == vctxt->skipDepth) {
23516 int curDepth;
23517 /*
23518 * Skip all content.
23519 */
23520 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
23521 ret = xmlTextReaderRead(vctxt->reader);
23522 curDepth = xmlTextReaderDepth(vctxt->reader);
23523 while ((ret == 1) && (curDepth != depth)) {
23524 ret = xmlTextReaderRead(vctxt->reader);
23525 curDepth = xmlTextReaderDepth(vctxt->reader);
23526 }
23527 if (ret < 0) {
23528 /*
23529 * VAL TODO: A reader error occured; what to do here?
23530 */
23531 ret = 1;
23532 goto exit;
23533 }
23534 }
23535 goto leave_elem;
23536 }
23537 /*
23538 * READER VAL TODO: Is an END_ELEM really never called
23539 * if the elem is empty?
23540 */
23541 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23542 goto leave_elem;
23543 } else if (nodeType == END_ELEM) {
23544 /*
23545 * Process END of element.
23546 */
23547leave_elem:
23548 ret = xmlSchemaValidatorPopElem(vctxt);
23549 if (ret != 0) {
23550 if (ret < 0) {
23551 VERROR_INT("xmlSchemaVReaderWalk",
23552 "calling xmlSchemaValidatorPopElem()");
23553 goto internal_error;
23554 }
23555 goto exit;
23556 }
23557 if (vctxt->depth >= 0)
23558 ielem = vctxt->inode;
23559 else
23560 ielem = NULL;
23561 } else if ((nodeType == XML_TEXT_NODE) ||
23562 (nodeType == XML_CDATA_SECTION_NODE) ||
23563 (nodeType == WHTSP) ||
23564 (nodeType == SIGN_WHTSP)) {
23565 /*
23566 * Process character content.
23567 */
23568 xmlChar *value;
23569
23570 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
23571 nodeType = XML_TEXT_NODE;
23572
23573 value = xmlTextReaderValue(vctxt->reader);
23574 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
23575 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
23576 if (! consumed)
23577 xmlFree(value);
23578 if (ret == -1) {
23579 VERROR_INT("xmlSchemaVReaderWalk",
23580 "calling xmlSchemaVPushText()");
23581 goto internal_error;
23582 }
23583 } else if ((nodeType == XML_ENTITY_NODE) ||
23584 (nodeType == XML_ENTITY_REF_NODE)) {
23585 /*
23586 * VAL TODO: What to do with entities?
23587 */
23588 TODO
23589 }
23590 /*
23591 * Read next node.
23592 */
23593 ret = xmlTextReaderRead(vctxt->reader);
23594 } while (ret == 1);
23595
23596exit:
23597 return (ret);
23598internal_error:
23599 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023600}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023601#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000023602
23603/************************************************************************
23604 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023605 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000023606 * *
23607 ************************************************************************/
23608
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023609#ifdef XML_SCHEMA_SAX_ENABLED
23610/*
23611* Process text content.
23612*/
23613static void
23614xmlSchemaSAXHandleText(void *ctx,
23615 const xmlChar * ch,
23616 int len)
23617{
23618 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23619
23620 if (vctxt->depth < 0)
23621 return;
23622 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23623 return;
23624 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23625 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23626 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
23627 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23628 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23629 "calling xmlSchemaVPushText()");
23630 vctxt->err = -1;
23631 xmlStopParser(vctxt->parserCtxt);
23632 }
23633}
23634
23635/*
23636* Process CDATA content.
23637*/
23638static void
23639xmlSchemaSAXHandleCDataSection(void *ctx,
23640 const xmlChar * ch,
23641 int len)
23642{
23643 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23644
23645 if (vctxt->depth < 0)
23646 return;
23647 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23648 return;
23649 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23650 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23651 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
23652 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23653 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23654 "calling xmlSchemaVPushText()");
23655 vctxt->err = -1;
23656 xmlStopParser(vctxt->parserCtxt);
23657 }
23658}
23659
23660static void
23661xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
23662 const xmlChar * name ATTRIBUTE_UNUSED)
23663{
23664 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23665
23666 if (vctxt->depth < 0)
23667 return;
23668 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23669 return;
23670 /* SAX VAL TODO: What to do here? */
23671 TODO
23672}
23673
23674static void
23675xmlSchemaSAXHandleStartElementNs(void *ctx,
23676 const xmlChar * localname,
23677 const xmlChar * prefix ATTRIBUTE_UNUSED,
23678 const xmlChar * URI,
23679 int nb_namespaces,
23680 const xmlChar ** namespaces,
23681 int nb_attributes,
23682 int nb_defaulted ATTRIBUTE_UNUSED,
23683 const xmlChar ** attributes)
23684{
23685 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23686 int ret;
23687 xmlSchemaNodeInfoPtr ielem;
23688 int i, j;
23689
23690 /*
23691 * SAX VAL TODO: What to do with nb_defaulted?
23692 */
23693 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023694 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023695 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023696 vctxt->depth++;
23697 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023698 return;
23699 /*
23700 * Push the element.
23701 */
23702 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23703 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23704 "calling xmlSchemaValidatorPushElem()");
23705 goto internal_error;
23706 }
23707 ielem = vctxt->inode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023708 /*
23709 * TODO: Is this OK?
23710 */
23711 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023712 ielem->localName = localname;
23713 ielem->nsName = URI;
23714 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23715 /*
23716 * Register namespaces on the elem info.
23717 */
23718 if (nb_namespaces != 0) {
23719 /*
23720 * Although the parser builds its own namespace list,
23721 * we have no access to it, so we'll use an own one.
23722 */
23723 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
23724 /*
23725 * Store prefix and namespace name.
23726 */
23727 if (ielem->nsBindings == NULL) {
23728 ielem->nsBindings =
23729 (const xmlChar **) xmlMalloc(10 *
23730 sizeof(const xmlChar *));
23731 if (ielem->nsBindings == NULL) {
23732 xmlSchemaVErrMemory(vctxt,
23733 "allocating namespace bindings for SAX validation",
23734 NULL);
23735 goto internal_error;
23736 }
23737 ielem->nbNsBindings = 0;
23738 ielem->sizeNsBindings = 5;
23739 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
23740 ielem->sizeNsBindings *= 2;
23741 ielem->nsBindings =
23742 (const xmlChar **) xmlRealloc(
23743 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023744 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023745 if (ielem->nsBindings == NULL) {
23746 xmlSchemaVErrMemory(vctxt,
23747 "re-allocating namespace bindings for SAX validation",
23748 NULL);
23749 goto internal_error;
23750 }
23751 }
23752
23753 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
23754 if (namespaces[j+1][0] == 0) {
23755 /*
23756 * Handle xmlns="".
23757 */
23758 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
23759 } else
23760 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
23761 namespaces[j+1];
23762 ielem->nbNsBindings++;
23763 }
23764 }
23765 /*
23766 * Register attributes.
23767 * SAX VAL TODO: We are not adding namespace declaration
23768 * attributes yet.
23769 */
23770 if (nb_attributes != 0) {
23771 xmlChar *value;
23772
23773 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
23774 /*
23775 * Duplicate the value.
23776 */
23777 value = xmlStrndup(attributes[j+3],
23778 attributes[j+4] - attributes[j+3]);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023779 /*
23780 * TODO: Set the node line.
23781 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023782 ret = xmlSchemaValidatorPushAttribute(vctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023783 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023784 value, 1);
23785 if (ret == -1) {
23786 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23787 "calling xmlSchemaValidatorPushAttribute()");
23788 goto internal_error;
23789 }
23790 }
23791 }
23792 /*
23793 * Validate the element.
23794 */
23795 ret = xmlSchemaValidateElem(vctxt);
23796 if (ret != 0) {
23797 if (ret == -1) {
23798 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23799 "calling xmlSchemaValidateElem()");
23800 goto internal_error;
23801 }
23802 goto exit;
23803 }
23804
23805exit:
23806 return;
23807internal_error:
23808 vctxt->err = -1;
23809 xmlStopParser(vctxt->parserCtxt);
23810 return;
23811}
23812
23813static void
23814xmlSchemaSAXHandleEndElementNs(void *ctx,
23815 const xmlChar * localname ATTRIBUTE_UNUSED,
23816 const xmlChar * prefix ATTRIBUTE_UNUSED,
23817 const xmlChar * URI ATTRIBUTE_UNUSED)
23818{
23819 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23820 int res;
23821
23822 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023823 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023824 */
23825 if (vctxt->skipDepth != -1) {
23826 if (vctxt->depth > vctxt->skipDepth) {
23827 vctxt->depth--;
23828 return;
23829 } else
23830 vctxt->skipDepth = -1;
23831 }
23832 /*
23833 * SAX VAL TODO: Just a temporary check.
23834 */
23835 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
23836 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
23837 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23838 "elem pop mismatch");
23839 }
23840 res = xmlSchemaValidatorPopElem(vctxt);
23841 if (res != 0) {
23842 if (res < 0) {
23843 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23844 "calling xmlSchemaValidatorPopElem()");
23845 goto internal_error;
23846 }
23847 goto exit;
23848 }
23849exit:
23850 return;
23851internal_error:
23852 vctxt->err = -1;
23853 xmlStopParser(vctxt->parserCtxt);
23854 return;
23855}
23856#endif
23857
Daniel Veillard4255d502002-04-16 15:50:10 +000023858/************************************************************************
23859 * *
23860 * Validation interfaces *
23861 * *
23862 ************************************************************************/
23863
23864/**
23865 * xmlSchemaNewValidCtxt:
23866 * @schema: a precompiled XML Schemas
23867 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023868 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023869 *
23870 * Returns the validation context or NULL in case of error
23871 */
23872xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023873xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23874{
Daniel Veillard4255d502002-04-16 15:50:10 +000023875 xmlSchemaValidCtxtPtr ret;
23876
23877 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23878 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023879 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023880 return (NULL);
23881 }
23882 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023883 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023884 ret->dict = xmlDictCreate();
23885 ret->nodeQNames = xmlSchemaNewItemList();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023886 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023887 return (ret);
23888}
23889
23890/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023891 * xmlSchemaClearValidCtxt:
23892 * @ctxt: the schema validation context
23893 *
23894 * Free the resources associated to the schema validation context;
23895 * leaves some fields alive intended for reuse of the context.
23896 */
23897static void
23898xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23899{
23900 if (vctxt == NULL)
23901 return;
23902
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023903 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023904 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023905 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023906#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023907 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023908#endif
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023909 if (vctxt->value != NULL) {
23910 xmlSchemaFreeValue(vctxt->value);
23911 vctxt->value = NULL;
23912 }
23913 /*
23914 * Augmented IDC information.
23915 */
23916 if (vctxt->aidcs != NULL) {
23917 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23918 do {
23919 next = cur->next;
23920 xmlFree(cur);
23921 cur = next;
23922 } while (cur != NULL);
23923 vctxt->aidcs = NULL;
23924 }
23925 if (vctxt->idcNodes != NULL) {
23926 int i;
23927 xmlSchemaPSVIIDCNodePtr item;
23928
23929 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023930 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023931 xmlFree(item->keys);
23932 xmlFree(item);
23933 }
23934 xmlFree(vctxt->idcNodes);
23935 vctxt->idcNodes = NULL;
23936 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023937 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023938 * Note that we won't delete the XPath state pool here.
23939 */
23940 if (vctxt->xpathStates != NULL) {
23941 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23942 vctxt->xpathStates = NULL;
23943 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023944 /*
23945 * Attribute info.
23946 */
23947 if (vctxt->nbAttrInfos != 0) {
23948 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023949 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023950 /*
23951 * Element info.
23952 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023953 if (vctxt->elemInfos != NULL) {
23954 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023955 xmlSchemaNodeInfoPtr ei;
23956
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023957 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023958 ei = vctxt->elemInfos[i];
23959 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023960 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023961 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023962 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023963 }
23964 xmlSchemaItemListClear(vctxt->nodeQNames);
23965 /* Recreate the dict. */
23966 xmlDictFree(vctxt->dict);
23967 vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023968}
23969
23970/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023971 * xmlSchemaFreeValidCtxt:
23972 * @ctxt: the schema validation context
23973 *
23974 * Free the resources associated to the schema validation context
23975 */
23976void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023977xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23978{
Daniel Veillard4255d502002-04-16 15:50:10 +000023979 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023980 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000023981 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023982 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023983 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023984 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023985 if (ctxt->idcNodes != NULL) {
23986 int i;
23987 xmlSchemaPSVIIDCNodePtr item;
23988
23989 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023990 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023991 xmlFree(item->keys);
23992 xmlFree(item);
23993 }
23994 xmlFree(ctxt->idcNodes);
23995 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023996 if (ctxt->idcKeys != NULL) {
23997 int i;
23998 for (i = 0; i < ctxt->nbIdcKeys; i++)
23999 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
24000 xmlFree(ctxt->idcKeys);
24001 }
24002
24003 if (ctxt->xpathStates != NULL)
24004 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
24005 if (ctxt->xpathStatePool != NULL)
24006 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
24007
24008 /*
24009 * Augmented IDC information.
24010 */
24011 if (ctxt->aidcs != NULL) {
24012 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
24013 do {
24014 next = cur->next;
24015 xmlFree(cur);
24016 cur = next;
24017 } while (cur != NULL);
24018 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024019 if (ctxt->attrInfos != NULL) {
24020 int i;
24021 xmlSchemaAttrInfoPtr attr;
24022
24023 /* Just a paranoid call to the cleanup. */
24024 if (ctxt->nbAttrInfos != 0)
24025 xmlSchemaClearAttrInfos(ctxt);
24026 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
24027 attr = ctxt->attrInfos[i];
24028 xmlFree(attr);
24029 }
24030 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000024031 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024032 if (ctxt->elemInfos != NULL) {
24033 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024034 xmlSchemaNodeInfoPtr ei;
24035
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024036 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024037 ei = ctxt->elemInfos[i];
24038 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024039 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024040 xmlSchemaClearElemInfo(ei);
24041 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024042 }
24043 xmlFree(ctxt->elemInfos);
24044 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024045 if (ctxt->nodeQNames != NULL)
24046 xmlSchemaFreeItemList(ctxt->nodeQNames);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024047 if (ctxt->dict != NULL)
24048 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000024049 xmlFree(ctxt);
24050}
24051
24052/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000024053 * xmlSchemaIsValid:
24054 * @ctxt: the schema validation context
24055 *
24056 * Check if any error was detected during validation.
24057 *
24058 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
24059 * of internal error.
24060 */
24061int
24062xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
24063{
24064 if (ctxt == NULL)
24065 return(-1);
24066 return(ctxt->err == 0);
24067}
24068
24069/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024070 * xmlSchemaSetValidErrors:
24071 * @ctxt: a schema validation context
24072 * @err: the error function
24073 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000024074 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000024075 *
William M. Brack2f2a6632004-08-20 23:09:47 +000024076 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000024077 */
24078void
24079xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024080 xmlSchemaValidityErrorFunc err,
24081 xmlSchemaValidityWarningFunc warn, void *ctx)
24082{
Daniel Veillard4255d502002-04-16 15:50:10 +000024083 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024084 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000024085 ctxt->error = err;
24086 ctxt->warning = warn;
24087 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024088 if (ctxt->pctxt != NULL)
24089 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000024090}
24091
24092/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000024093 * xmlSchemaSetValidStructuredErrors:
24094 * @ctxt: a schema validation context
24095 * @serror: the structured error function
24096 * @ctx: the functions context
24097 *
24098 * Set the structured error callback
24099 */
24100void
24101xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
24102 xmlStructuredErrorFunc serror, void *ctx)
24103{
24104 if (ctxt == NULL)
24105 return;
24106 ctxt->serror = serror;
24107 ctxt->error = NULL;
24108 ctxt->warning = NULL;
24109 ctxt->userData = ctx;
24110}
24111
24112/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000024113 * xmlSchemaGetValidErrors:
24114 * @ctxt: a XML-Schema validation context
24115 * @err: the error function result
24116 * @warn: the warning function result
24117 * @ctx: the functions context result
24118 *
24119 * Get the error and warning callback informations
24120 *
24121 * Returns -1 in case of error and 0 otherwise
24122 */
24123int
24124xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
24125 xmlSchemaValidityErrorFunc * err,
24126 xmlSchemaValidityWarningFunc * warn, void **ctx)
24127{
24128 if (ctxt == NULL)
24129 return (-1);
24130 if (err != NULL)
24131 *err = ctxt->error;
24132 if (warn != NULL)
24133 *warn = ctxt->warning;
24134 if (ctx != NULL)
24135 *ctx = ctxt->userData;
24136 return (0);
24137}
24138
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024139
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024140/**
Daniel Veillard6927b102004-10-27 17:29:04 +000024141 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024142 * @ctxt: a schema validation context
24143 * @options: a combination of xmlSchemaValidOption
24144 *
24145 * Sets the options to be used during the validation.
24146 *
24147 * Returns 0 in case of success, -1 in case of an
24148 * API error.
24149 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024150int
24151xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
24152 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024153
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024154{
24155 int i;
24156
24157 if (ctxt == NULL)
24158 return (-1);
24159 /*
24160 * WARNING: Change the start value if adding to the
24161 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024162 * TODO: Is there an other, more easy to maintain,
24163 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024164 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024165 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024166 if (options & 1<<i)
24167 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024168 }
24169 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024170 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024171}
24172
24173/**
Daniel Veillard6927b102004-10-27 17:29:04 +000024174 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024175 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024176 *
William M. Brack21e4ef22005-01-02 09:53:13 +000024177 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024178 *
William M. Brack21e4ef22005-01-02 09:53:13 +000024179 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024180 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024181int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024182xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024183
24184{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024185 if (ctxt == NULL)
24186 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024187 else
24188 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024189}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024190
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024191static int
24192xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
24193{
24194 xmlAttrPtr attr;
24195 int ret = 0;
24196 xmlSchemaNodeInfoPtr ielem = NULL;
24197 xmlNodePtr node, valRoot;
24198 const xmlChar *nsName;
24199
24200 /* DOC VAL TODO: Move this to the start function. */
24201 valRoot = xmlDocGetRootElement(vctxt->doc);
24202 if (valRoot == NULL) {
24203 /* VAL TODO: Error code? */
24204 VERROR(1, NULL, "The document has no document element");
24205 return (1);
24206 }
24207 vctxt->depth = -1;
24208 vctxt->validationRoot = valRoot;
24209 node = valRoot;
24210 while (node != NULL) {
24211 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
24212 goto next_sibling;
24213 if (node->type == XML_ELEMENT_NODE) {
24214
24215 /*
24216 * Init the node-info.
24217 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000024218 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024219 if (xmlSchemaValidatorPushElem(vctxt) == -1)
24220 goto internal_error;
24221 ielem = vctxt->inode;
24222 ielem->node = node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024223 ielem->nodeLine = node->line;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024224 ielem->localName = node->name;
24225 if (node->ns != NULL)
24226 ielem->nsName = node->ns->href;
24227 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
24228 /*
24229 * Register attributes.
24230 * DOC VAL TODO: We do not register namespace declaration
24231 * attributes yet.
24232 */
24233 vctxt->nbAttrInfos = 0;
24234 if (node->properties != NULL) {
24235 attr = node->properties;
24236 do {
24237 if (attr->ns != NULL)
24238 nsName = attr->ns->href;
24239 else
24240 nsName = NULL;
24241 ret = xmlSchemaValidatorPushAttribute(vctxt,
24242 (xmlNodePtr) attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024243 /*
24244 * Note that we give it the line number of the
24245 * parent element.
24246 */
24247 ielem->nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024248 attr->name, nsName, 0,
24249 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
24250 if (ret == -1) {
24251 VERROR_INT("xmlSchemaDocWalk",
24252 "calling xmlSchemaValidatorPushAttribute()");
24253 goto internal_error;
24254 }
24255 attr = attr->next;
24256 } while (attr);
24257 }
24258 /*
24259 * Validate the element.
24260 */
24261 ret = xmlSchemaValidateElem(vctxt);
24262 if (ret != 0) {
24263 if (ret == -1) {
24264 VERROR_INT("xmlSchemaDocWalk",
24265 "calling xmlSchemaValidateElem()");
24266 goto internal_error;
24267 }
24268 /*
24269 * Don't stop validation; just skip the content
24270 * of this element.
24271 */
24272 goto leave_node;
24273 }
24274 if ((vctxt->skipDepth != -1) &&
24275 (vctxt->depth >= vctxt->skipDepth))
24276 goto leave_node;
24277 } else if ((node->type == XML_TEXT_NODE) ||
24278 (node->type == XML_CDATA_SECTION_NODE)) {
24279 /*
24280 * Process character content.
24281 */
24282 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
24283 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
24284 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
24285 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
24286 if (ret < 0) {
24287 VERROR_INT("xmlSchemaVDocWalk",
24288 "calling xmlSchemaVPushText()");
24289 goto internal_error;
24290 }
24291 /*
24292 * DOC VAL TODO: Should we skip further validation of the
24293 * element content here?
24294 */
24295 } else if ((node->type == XML_ENTITY_NODE) ||
24296 (node->type == XML_ENTITY_REF_NODE)) {
24297 /*
24298 * DOC VAL TODO: What to do with entities?
24299 */
24300 TODO
24301 } else {
24302 goto leave_node;
24303 /*
24304 * DOC VAL TODO: XInclude nodes, etc.
24305 */
24306 }
24307 /*
24308 * Walk the doc.
24309 */
24310 if (node->children != NULL) {
24311 node = node->children;
24312 continue;
24313 }
24314leave_node:
24315 if (node->type == XML_ELEMENT_NODE) {
24316 /*
24317 * Leaving the scope of an element.
24318 */
24319 if (node != vctxt->inode->node) {
24320 VERROR_INT("xmlSchemaVDocWalk",
24321 "element position mismatch");
24322 goto internal_error;
24323 }
24324 ret = xmlSchemaValidatorPopElem(vctxt);
24325 if (ret != 0) {
24326 if (ret < 0) {
24327 VERROR_INT("xmlSchemaVDocWalk",
24328 "calling xmlSchemaValidatorPopElem()");
24329 goto internal_error;
24330 }
24331 }
24332 if (node == valRoot)
24333 goto exit;
24334 }
24335next_sibling:
24336 if (node->next != NULL)
24337 node = node->next;
24338 else {
24339 node = node->parent;
24340 goto leave_node;
24341 }
24342 }
24343
24344exit:
24345 return (ret);
24346internal_error:
24347 return (-1);
24348}
24349
24350static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000024351xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024352 /*
24353 * Some initialization.
24354 */
24355 vctxt->err = 0;
24356 vctxt->nberrors = 0;
24357 vctxt->depth = -1;
24358 vctxt->skipDepth = -1;
24359 /*
24360 * Create a schema + parser if necessary.
24361 */
24362 if (vctxt->schema == NULL) {
24363
24364 if ((vctxt->pctxt == NULL) &&
24365 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24366 return (-1);
24367
24368 vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
24369 if (vctxt->schema == NULL) {
24370 VERROR_INT("xmlSchemaVStartValidation",
24371 "creating a schema");
24372 return (-1);
24373 }
24374 vctxt->xsiAssemble = 1;
24375 } else
24376 vctxt->xsiAssemble = 0;
24377 /*
24378 * Augment the IDC definitions.
24379 */
24380 if (vctxt->schema->idcDef != NULL) {
24381 xmlHashScan(vctxt->schema->idcDef,
24382 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
24383 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000024384 return(0);
24385}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024386
Daniel Veillardf10ae122005-07-10 19:03:16 +000024387static void
24388xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024389 if (vctxt->xsiAssemble) {
24390 if (vctxt->schema != NULL) {
24391 xmlSchemaFree(vctxt->schema);
24392 vctxt->schema = NULL;
24393 }
24394 }
24395 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000024396}
24397
24398static int
24399xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
24400{
24401 int ret = 0;
24402
24403 if (xmlSchemaPreRun(vctxt) < 0)
24404 return(-1);
24405
24406 if (vctxt->doc != NULL) {
24407 /*
24408 * Tree validation.
24409 */
24410 ret = xmlSchemaVDocWalk(vctxt);
24411#ifdef LIBXML_READER_ENABLED
24412 } else if (vctxt->reader != NULL) {
24413 /*
24414 * XML Reader validation.
24415 */
24416#ifdef XML_SCHEMA_READER_ENABLED
24417 ret = xmlSchemaVReaderWalk(vctxt);
24418#endif
24419#endif
24420 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
24421 /*
24422 * SAX validation.
24423 */
24424 ret = xmlParseDocument(vctxt->parserCtxt);
24425 } else {
24426 VERROR_INT("xmlSchemaVStartValidation",
24427 "no instance to validate");
24428 ret = -1;
24429 }
24430
24431 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024432 if (ret == 0)
24433 ret = vctxt->err;
24434 return (ret);
24435}
24436
24437/**
24438 * xmlSchemaValidateOneElement:
24439 * @ctxt: a schema validation context
24440 * @elem: an element node
24441 *
24442 * Validate a branch of a tree, starting with the given @elem.
24443 *
24444 * Returns 0 if the element and its subtree is valid, a positive error
24445 * code number otherwise and -1 in case of an internal or API error.
24446 */
24447int
24448xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
24449{
24450 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
24451 return (-1);
24452
24453 if (ctxt->schema == NULL)
24454 return (-1);
24455
24456 ctxt->doc = elem->doc;
24457 ctxt->node = elem;
24458 ctxt->validationRoot = elem;
24459 return(xmlSchemaVStart(ctxt));
24460}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024461
Daniel Veillard259f0df2004-08-18 09:13:18 +000024462/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024463 * xmlSchemaValidateDoc:
24464 * @ctxt: a schema validation context
24465 * @doc: a parsed document tree
24466 *
24467 * Validate a document tree in memory.
24468 *
24469 * Returns 0 if the document is schemas valid, a positive error code
24470 * number otherwise and -1 in case of internal or API error.
24471 */
24472int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024473xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
24474{
Daniel Veillard4255d502002-04-16 15:50:10 +000024475 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024476 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000024477
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024478 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024479 ctxt->node = xmlDocGetRootElement(doc);
24480 if (ctxt->node == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024481 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024482 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
24483 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024484 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024485 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024486 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024487 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024488 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000024489}
24490
Daniel Veillardcdc82732005-07-08 15:04:06 +000024491
24492/************************************************************************
24493 * *
24494 * Function and data for SAX streaming API *
24495 * *
24496 ************************************************************************/
24497typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
24498typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
24499
24500struct _xmlSchemaSplitSAXData {
24501 xmlSAXHandlerPtr user_sax;
24502 void *user_data;
24503 xmlSchemaValidCtxtPtr ctxt;
24504 xmlSAXHandlerPtr schemas_sax;
24505};
24506
Daniel Veillard971771e2005-07-09 17:32:57 +000024507#define XML_SAX_PLUG_MAGIC 0xdc43ba21
24508
24509struct _xmlSchemaSAXPlug {
24510 unsigned int magic;
24511
24512 /* the original callbacks informations */
24513 xmlSAXHandlerPtr *user_sax_ptr;
24514 xmlSAXHandlerPtr user_sax;
24515 void **user_data_ptr;
24516 void *user_data;
24517
24518 /* the block plugged back and validation informations */
24519 xmlSAXHandler schemas_sax;
24520 xmlSchemaValidCtxtPtr ctxt;
24521};
24522
Daniel Veillardcdc82732005-07-08 15:04:06 +000024523/* All those functions just bounces to the user provided SAX handlers */
24524static void
24525internalSubsetSplit(void *ctx, const xmlChar *name,
24526 const xmlChar *ExternalID, const xmlChar *SystemID)
24527{
Daniel Veillard971771e2005-07-09 17:32:57 +000024528 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024529 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24530 (ctxt->user_sax->internalSubset != NULL))
24531 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24532 SystemID);
24533}
24534
24535static int
24536isStandaloneSplit(void *ctx)
24537{
Daniel Veillard971771e2005-07-09 17:32:57 +000024538 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024539 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24540 (ctxt->user_sax->isStandalone != NULL))
24541 return(ctxt->user_sax->isStandalone(ctxt->user_data));
24542 return(0);
24543}
24544
24545static int
24546hasInternalSubsetSplit(void *ctx)
24547{
Daniel Veillard971771e2005-07-09 17:32:57 +000024548 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024549 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24550 (ctxt->user_sax->hasInternalSubset != NULL))
24551 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
24552 return(0);
24553}
24554
24555static int
24556hasExternalSubsetSplit(void *ctx)
24557{
Daniel Veillard971771e2005-07-09 17:32:57 +000024558 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024559 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24560 (ctxt->user_sax->hasExternalSubset != NULL))
24561 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
24562 return(0);
24563}
24564
24565static void
24566externalSubsetSplit(void *ctx, const xmlChar *name,
24567 const xmlChar *ExternalID, const xmlChar *SystemID)
24568{
Daniel Veillard971771e2005-07-09 17:32:57 +000024569 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024570 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24571 (ctxt->user_sax->internalSubset != NULL))
24572 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24573 SystemID);
24574}
24575
24576static xmlParserInputPtr
24577resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
24578{
Daniel Veillard971771e2005-07-09 17:32:57 +000024579 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024580 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24581 (ctxt->user_sax->resolveEntity != NULL))
24582 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
24583 systemId));
24584 return(NULL);
24585}
24586
24587static xmlEntityPtr
24588getEntitySplit(void *ctx, const xmlChar *name)
24589{
Daniel Veillard971771e2005-07-09 17:32:57 +000024590 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024591 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24592 (ctxt->user_sax->getEntity != NULL))
24593 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
24594 return(NULL);
24595}
24596
24597static xmlEntityPtr
24598getParameterEntitySplit(void *ctx, const xmlChar *name)
24599{
Daniel Veillard971771e2005-07-09 17:32:57 +000024600 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024601 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24602 (ctxt->user_sax->getParameterEntity != NULL))
24603 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
24604 return(NULL);
24605}
24606
24607
24608static void
24609entityDeclSplit(void *ctx, const xmlChar *name, int type,
24610 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
24611{
Daniel Veillard971771e2005-07-09 17:32:57 +000024612 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024613 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24614 (ctxt->user_sax->entityDecl != NULL))
24615 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
24616 systemId, content);
24617}
24618
24619static void
24620attributeDeclSplit(void *ctx, const xmlChar * elem,
24621 const xmlChar * name, int type, int def,
24622 const xmlChar * defaultValue, xmlEnumerationPtr tree)
24623{
Daniel Veillard971771e2005-07-09 17:32:57 +000024624 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024625 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24626 (ctxt->user_sax->attributeDecl != NULL)) {
24627 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
24628 def, defaultValue, tree);
24629 } else {
24630 xmlFreeEnumeration(tree);
24631 }
24632}
24633
24634static void
24635elementDeclSplit(void *ctx, const xmlChar *name, int type,
24636 xmlElementContentPtr content)
24637{
Daniel Veillard971771e2005-07-09 17:32:57 +000024638 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024639 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24640 (ctxt->user_sax->elementDecl != NULL))
24641 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
24642}
24643
24644static void
24645notationDeclSplit(void *ctx, const xmlChar *name,
24646 const xmlChar *publicId, const xmlChar *systemId)
24647{
Daniel Veillard971771e2005-07-09 17:32:57 +000024648 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024649 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24650 (ctxt->user_sax->notationDecl != NULL))
24651 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
24652 systemId);
24653}
24654
24655static void
24656unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
24657 const xmlChar *publicId, const xmlChar *systemId,
24658 const xmlChar *notationName)
24659{
Daniel Veillard971771e2005-07-09 17:32:57 +000024660 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024661 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24662 (ctxt->user_sax->unparsedEntityDecl != NULL))
24663 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
24664 systemId, notationName);
24665}
24666
24667static void
24668setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
24669{
Daniel Veillard971771e2005-07-09 17:32:57 +000024670 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024671 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24672 (ctxt->user_sax->setDocumentLocator != NULL))
24673 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
24674}
24675
24676static void
24677startDocumentSplit(void *ctx)
24678{
Daniel Veillard971771e2005-07-09 17:32:57 +000024679 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024680 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24681 (ctxt->user_sax->startDocument != NULL))
24682 ctxt->user_sax->startDocument(ctxt->user_data);
24683}
24684
24685static void
24686endDocumentSplit(void *ctx)
24687{
Daniel Veillard971771e2005-07-09 17:32:57 +000024688 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024689 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24690 (ctxt->user_sax->endDocument != NULL))
24691 ctxt->user_sax->endDocument(ctxt->user_data);
24692}
24693
24694static void
24695processingInstructionSplit(void *ctx, const xmlChar *target,
24696 const xmlChar *data)
24697{
Daniel Veillard971771e2005-07-09 17:32:57 +000024698 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024699 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24700 (ctxt->user_sax->processingInstruction != NULL))
24701 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
24702}
24703
24704static void
24705commentSplit(void *ctx, const xmlChar *value)
24706{
Daniel Veillard971771e2005-07-09 17:32:57 +000024707 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024708 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24709 (ctxt->user_sax->comment != NULL))
24710 ctxt->user_sax->comment(ctxt->user_data, value);
24711}
24712
24713/*
24714 * Varargs error callbacks to the user application, harder ...
24715 */
24716
Daniel Veillardffa3c742005-07-21 13:24:09 +000024717static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024718warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024719 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024720 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24721 (ctxt->user_sax->warning != NULL)) {
24722 TODO
24723 }
24724}
Daniel Veillardffa3c742005-07-21 13:24:09 +000024725static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024726errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024727 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024728 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24729 (ctxt->user_sax->error != NULL)) {
24730 TODO
24731 }
24732}
Daniel Veillardffa3c742005-07-21 13:24:09 +000024733static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024734fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024735 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024736 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24737 (ctxt->user_sax->fatalError != NULL)) {
24738 TODO
24739 }
24740}
24741
24742/*
24743 * Those are function where both the user handler and the schemas handler
24744 * need to be called.
24745 */
24746static void
24747charactersSplit(void *ctx, const xmlChar *ch, int len)
24748{
Daniel Veillard971771e2005-07-09 17:32:57 +000024749 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024750 if (ctxt == NULL)
24751 return;
24752 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
24753 ctxt->user_sax->characters(ctxt->user_data, ch, len);
24754 if (ctxt->ctxt != NULL)
24755 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24756}
24757
24758static void
24759ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
24760{
Daniel Veillard971771e2005-07-09 17:32:57 +000024761 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024762 if (ctxt == NULL)
24763 return;
24764 if ((ctxt->user_sax != NULL) &&
24765 (ctxt->user_sax->ignorableWhitespace != NULL))
24766 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
24767 if (ctxt->ctxt != NULL)
24768 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24769}
24770
24771static void
24772cdataBlockSplit(void *ctx, const xmlChar *value, int len)
24773{
Daniel Veillard971771e2005-07-09 17:32:57 +000024774 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024775 if (ctxt == NULL)
24776 return;
24777 if ((ctxt->user_sax != NULL) &&
24778 (ctxt->user_sax->ignorableWhitespace != NULL))
24779 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
24780 if (ctxt->ctxt != NULL)
24781 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
24782}
24783
24784static void
24785referenceSplit(void *ctx, const xmlChar *name)
24786{
Daniel Veillard971771e2005-07-09 17:32:57 +000024787 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024788 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24789 (ctxt->user_sax->reference != NULL))
24790 ctxt->user_sax->reference(ctxt->user_data, name);
24791 if (ctxt->ctxt != NULL)
24792 xmlSchemaSAXHandleReference(ctxt->user_data, name);
24793}
24794
24795static void
24796startElementNsSplit(void *ctx, const xmlChar * localname,
24797 const xmlChar * prefix, const xmlChar * URI,
24798 int nb_namespaces, const xmlChar ** namespaces,
24799 int nb_attributes, int nb_defaulted,
24800 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024801 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024802 if (ctxt == NULL)
24803 return;
24804 if ((ctxt->user_sax != NULL) &&
24805 (ctxt->user_sax->startElementNs != NULL))
24806 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
24807 URI, nb_namespaces, namespaces,
24808 nb_attributes, nb_defaulted,
24809 attributes);
24810 if (ctxt->ctxt != NULL)
24811 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
24812 URI, nb_namespaces, namespaces,
24813 nb_attributes, nb_defaulted,
24814 attributes);
24815}
24816
24817static void
24818endElementNsSplit(void *ctx, const xmlChar * localname,
24819 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024820 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024821 if (ctxt == NULL)
24822 return;
24823 if ((ctxt->user_sax != NULL) &&
24824 (ctxt->user_sax->endElementNs != NULL))
24825 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
24826 if (ctxt->ctxt != NULL)
24827 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
24828}
24829
Daniel Veillard4255d502002-04-16 15:50:10 +000024830/**
Daniel Veillard971771e2005-07-09 17:32:57 +000024831 * xmlSchemaSAXPlug:
24832 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000024833 * @sax: a pointer to the original xmlSAXHandlerPtr
24834 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000024835 *
24836 * Plug a SAX based validation layer in a SAX parsing event flow.
24837 * The original @saxptr and @dataptr data are replaced by new pointers
24838 * but the calls to the original will be maintained.
24839 *
24840 * Returns a pointer to a data structure needed to unplug the validation layer
24841 * or NULL in case of errors.
24842 */
24843xmlSchemaSAXPlugPtr
24844xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
24845 xmlSAXHandlerPtr *sax, void **user_data)
24846{
24847 xmlSchemaSAXPlugPtr ret;
24848 xmlSAXHandlerPtr old_sax;
24849
24850 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
24851 return(NULL);
24852
24853 /*
24854 * We only allow to plug into SAX2 event streams
24855 */
24856 old_sax = *sax;
24857 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
24858 return(NULL);
24859 if ((old_sax != NULL) &&
24860 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
24861 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
24862 return(NULL);
24863
24864 /*
24865 * everything seems right allocate the local data needed for that layer
24866 */
24867 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
24868 if (ret == NULL) {
24869 return(NULL);
24870 }
24871 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
24872 ret->magic = XML_SAX_PLUG_MAGIC;
24873 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
24874 ret->ctxt = ctxt;
24875 ret->user_sax_ptr = sax;
24876 ret->user_sax = old_sax;
24877 if (old_sax == NULL) {
24878 /*
24879 * go direct, no need for the split block and functions.
24880 */
24881 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
24882 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
24883 /*
24884 * Note that we use the same text-function for both, to prevent
24885 * the parser from testing for ignorable whitespace.
24886 */
24887 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
24888 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
24889
24890 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
24891 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
24892
24893 ret->user_data = ctxt;
24894 *user_data = ctxt;
24895 } else {
24896 /*
24897 * for each callback unused by Schemas initialize it to the Split
24898 * routine only if non NULL in the user block, this can speed up
24899 * things at the SAX level.
24900 */
24901 if (old_sax->internalSubset != NULL)
24902 ret->schemas_sax.internalSubset = internalSubsetSplit;
24903 if (old_sax->isStandalone != NULL)
24904 ret->schemas_sax.isStandalone = isStandaloneSplit;
24905 if (old_sax->hasInternalSubset != NULL)
24906 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
24907 if (old_sax->hasExternalSubset != NULL)
24908 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
24909 if (old_sax->resolveEntity != NULL)
24910 ret->schemas_sax.resolveEntity = resolveEntitySplit;
24911 if (old_sax->getEntity != NULL)
24912 ret->schemas_sax.getEntity = getEntitySplit;
24913 if (old_sax->entityDecl != NULL)
24914 ret->schemas_sax.entityDecl = entityDeclSplit;
24915 if (old_sax->notationDecl != NULL)
24916 ret->schemas_sax.notationDecl = notationDeclSplit;
24917 if (old_sax->attributeDecl != NULL)
24918 ret->schemas_sax.attributeDecl = attributeDeclSplit;
24919 if (old_sax->elementDecl != NULL)
24920 ret->schemas_sax.elementDecl = elementDeclSplit;
24921 if (old_sax->unparsedEntityDecl != NULL)
24922 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
24923 if (old_sax->setDocumentLocator != NULL)
24924 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
24925 if (old_sax->startDocument != NULL)
24926 ret->schemas_sax.startDocument = startDocumentSplit;
24927 if (old_sax->endDocument != NULL)
24928 ret->schemas_sax.endDocument = endDocumentSplit;
24929 if (old_sax->processingInstruction != NULL)
24930 ret->schemas_sax.processingInstruction = processingInstructionSplit;
24931 if (old_sax->comment != NULL)
24932 ret->schemas_sax.comment = commentSplit;
24933 if (old_sax->warning != NULL)
24934 ret->schemas_sax.warning = warningSplit;
24935 if (old_sax->error != NULL)
24936 ret->schemas_sax.error = errorSplit;
24937 if (old_sax->fatalError != NULL)
24938 ret->schemas_sax.fatalError = fatalErrorSplit;
24939 if (old_sax->getParameterEntity != NULL)
24940 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
24941 if (old_sax->externalSubset != NULL)
24942 ret->schemas_sax.externalSubset = externalSubsetSplit;
24943
24944 /*
24945 * the 6 schemas callback have to go to the splitter functions
24946 * Note that we use the same text-function for ignorableWhitespace
24947 * if possible, to prevent the parser from testing for ignorable
24948 * whitespace.
24949 */
24950 ret->schemas_sax.characters = charactersSplit;
24951 if ((old_sax->ignorableWhitespace != NULL) &&
24952 (old_sax->ignorableWhitespace != old_sax->characters))
24953 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
24954 else
24955 ret->schemas_sax.ignorableWhitespace = charactersSplit;
24956 ret->schemas_sax.cdataBlock = cdataBlockSplit;
24957 ret->schemas_sax.reference = referenceSplit;
24958 ret->schemas_sax.startElementNs = startElementNsSplit;
24959 ret->schemas_sax.endElementNs = endElementNsSplit;
24960
24961 ret->user_data_ptr = user_data;
24962 ret->user_data = *user_data;
24963 *user_data = ret;
24964 }
24965
24966 /*
24967 * plug the pointers back.
24968 */
24969 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000024970 ctxt->sax = *sax;
24971 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24972 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024973 return(ret);
24974}
24975
24976/**
24977 * xmlSchemaSAXUnplug:
24978 * @plug: a data structure returned by xmlSchemaSAXPlug
24979 *
24980 * Unplug a SAX based validation layer in a SAX parsing event flow.
24981 * The original pointers used in the call are restored.
24982 *
24983 * Returns 0 in case of success and -1 in case of failure.
24984 */
24985int
24986xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
24987{
24988 xmlSAXHandlerPtr *sax;
24989 void **user_data;
24990
24991 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
24992 return(-1);
24993 plug->magic = 0;
24994
Daniel Veillardf10ae122005-07-10 19:03:16 +000024995 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024996 /* restore the data */
24997 sax = plug->user_sax_ptr;
24998 *sax = plug->user_sax;
24999 if (plug->user_sax != NULL) {
25000 user_data = plug->user_data_ptr;
25001 *user_data = plug->user_data;
25002 }
25003
25004 /* free and return */
25005 xmlFree(plug);
25006 return(0);
25007}
25008
25009/**
Daniel Veillard4255d502002-04-16 15:50:10 +000025010 * xmlSchemaValidateStream:
25011 * @ctxt: a schema validation context
25012 * @input: the input to use for reading the data
25013 * @enc: an optional encoding information
25014 * @sax: a SAX handler for the resulting events
25015 * @user_data: the context to provide to the SAX handler.
25016 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000025017 * Validate an input based on a flow of SAX event from the parser
25018 * and forward the events to the @sax handler with the provided @user_data
25019 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000025020 *
25021 * Returns 0 if the document is schemas valid, a positive error code
25022 * number otherwise and -1 in case of internal or API error.
25023 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000025024int
Daniel Veillard4255d502002-04-16 15:50:10 +000025025xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000025026 xmlParserInputBufferPtr input, xmlCharEncoding enc,
25027 xmlSAXHandlerPtr sax, void *user_data)
25028{
Daniel Veillard971771e2005-07-09 17:32:57 +000025029 xmlSchemaSAXPlugPtr plug = NULL;
25030 xmlSAXHandlerPtr old_sax = NULL;
25031 xmlParserCtxtPtr pctxt = NULL;
25032 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025033 int ret;
25034
Daniel Veillard4255d502002-04-16 15:50:10 +000025035 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000025036 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000025037
Daniel Veillardcdc82732005-07-08 15:04:06 +000025038 /*
25039 * prepare the parser
25040 */
25041 pctxt = xmlNewParserCtxt();
25042 if (pctxt == NULL)
25043 return (-1);
25044 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000025045 pctxt->sax = sax;
25046 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025047#if 0
25048 if (options)
25049 xmlCtxtUseOptions(pctxt, options);
25050#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000025051 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025052
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000025053 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025054 if (inputStream == NULL) {
25055 ret = -1;
25056 goto done;
25057 }
25058 inputPush(pctxt, inputStream);
25059 ctxt->parserCtxt = pctxt;
25060 ctxt->input = input;
25061
25062 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000025063 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000025064 */
Daniel Veillard971771e2005-07-09 17:32:57 +000025065 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
25066 if (plug == NULL) {
25067 ret = -1;
25068 goto done;
25069 }
25070 ctxt->input = input;
25071 ctxt->enc = enc;
25072 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025073 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
25074 ret = xmlSchemaVStart(ctxt);
25075
25076 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
25077 ret = ctxt->parserCtxt->errNo;
25078 if (ret == 0)
25079 ret = 1;
25080 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000025081
25082done:
Daniel Veillard971771e2005-07-09 17:32:57 +000025083 ctxt->parserCtxt = NULL;
25084 ctxt->sax = NULL;
25085 ctxt->input = NULL;
25086 if (plug != NULL) {
25087 xmlSchemaSAXUnplug(plug);
25088 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000025089 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000025090 if (pctxt != NULL) {
25091 pctxt->sax = old_sax;
25092 xmlFreeParserCtxt(pctxt);
25093 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000025094 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000025095}
25096
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025097/**
25098 * xmlSchemaValidateFile:
25099 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000025100 * @filename: the URI of the instance
25101 * @options: a future set of options, currently unused
25102 *
25103 * Do a schemas validation of the given resource, it will use the
25104 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025105 *
25106 * Returns 0 if the document is valid, a positive error code
25107 * number otherwise and -1 in case of an internal or API error.
25108 */
25109int
25110xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000025111 const char * filename,
25112 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025113{
Daniel Veillard81562d22005-06-15 13:27:56 +000025114#ifdef XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025115 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000025116 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025117
25118 if ((ctxt == NULL) || (filename == NULL))
25119 return (-1);
25120
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000025121 input = xmlParserInputBufferCreateFilename(filename,
25122 XML_CHAR_ENCODING_NONE);
25123 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025124 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000025125 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
25126 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025127 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000025128#else
25129 return (-1);
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000025130#endif /* XML_SCHEMA_SAX_ENABLED */
Daniel Veillard81562d22005-06-15 13:27:56 +000025131}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025132
Daniel Veillard5d4644e2005-04-01 13:11:58 +000025133#define bottom_xmlschemas
25134#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000025135#endif /* LIBXML_SCHEMAS_ENABLED */