blob: 3948562a258008d1ab5d4c84ba9129cb024e1ef2 [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";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000103static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000104 "complex type";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000105static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000106 "model group";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000107#if 0
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000108static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000109 "model group ref.";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000110#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000111
Daniel Veillard4255d502002-04-16 15:50:10 +0000112#define IS_SCHEMA(node, type) \
113 ((node != NULL) && (node->ns != NULL) && \
114 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
115 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
116
Daniel Veillardc0826a72004-08-10 14:17:33 +0000117#define FREE_AND_NULL(str) \
118 if (str != NULL) { \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000119 xmlFree((xmlChar *) str); \
Daniel Veillardc0826a72004-08-10 14:17:33 +0000120 str = NULL; \
121 }
122
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000123#define IS_ANYTYPE(item) \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000124 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
125 (item->builtInType == XML_SCHEMAS_ANYTYPE))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000126
127#define IS_COMPLEX_TYPE(item) \
128 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
129 (item->builtInType == XML_SCHEMAS_ANYTYPE))
130
131#define IS_SIMPLE_TYPE(item) \
132 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
133 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000134 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000135
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000136#define IS_ANY_SIMPLE_TYPE(item) \
137 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000138 (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000139
140#define IS_NOT_TYPEFIXED(item) \
141 ((item->type != XML_SCHEMA_TYPE_BASIC) && \
142 ((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
143
144#define HAS_COMPLEX_CONTENT(item) \
145 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
146 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
147 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
148
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000149#define HAS_SIMPLE_CONTENT(item) \
150 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
151 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
152
153#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
154
155#define IS_PARTICLE_EMPTIABLE(item) \
156 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
157
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000158#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
159
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000160#define GET_LIST_ITEM_TYPE(item) item->subtypes
161
162#define VARIETY_ATOMIC(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
163#define VARIETY_LIST(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
164#define VARIETY_UNION(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
165
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000166#define IS_MODEL_GROUP(item) \
167 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
168 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
169 (item->type == XML_SCHEMA_TYPE_ALL))
170
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000171#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
172
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000173#define ELEM_TYPE(item) item->subtypes
174
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000175#define GET_PARTICLE(item) (xmlSchemaParticlePtr) item->subtypes;
176
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000177#define SUBST_GROUP_AFF(item) item->refDecl
178
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000179#if 0
180#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
181#endif
182
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000183#define SUBSET_RESTRICTION 1<<0
184#define SUBSET_EXTENSION 1<<1
185#define SUBSET_SUBSTITUTION 1<<2
186#define SUBSET_LIST 1<<3
187#define SUBSET_UNION 1<<4
188
Daniel Veillard4255d502002-04-16 15:50:10 +0000189#define XML_SCHEMAS_PARSE_ERROR 1
190
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000191#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
192
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000193typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
194typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000195
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000196
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000197typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000198typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000199
200typedef struct _xmlSchemaItemList xmlSchemaItemList;
201typedef xmlSchemaItemList *xmlSchemaItemListPtr;
202
203struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000204 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000205 int nbItems; /* used for dynamic addition of schemata */
206 int sizeItems; /* used for dynamic addition of schemata */
207};
208
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000209typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
210typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
211struct _xmlSchemaAbstractCtxt {
212 int type;
213};
214
215#define XML_SCHEMA_CTXT_PARSER 1
216#define XML_SCHEMA_CTXT_VALIDATOR 2
217
Daniel Veillard4255d502002-04-16 15:50:10 +0000218struct _xmlSchemaParserCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000219 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000220 void *userData; /* user specific data block */
221 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
222 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000223 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000224 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000225 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000226
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000227 xmlSchemaPtr topschema; /* The main schema */
228 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
229
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000230 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000231 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000232 int counter;
233
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000234 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000235 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000236 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000237
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000238 const char *buffer;
239 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000240
Daniel Veillard4255d502002-04-16 15:50:10 +0000241 /*
242 * Used to build complex element content models
243 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000244 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000245 xmlAutomataStatePtr start;
246 xmlAutomataStatePtr end;
247 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000248
249 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000250 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000251 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
252 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000253 xmlSchemaAssemblePtr assemble;
254 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000255 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000256 const xmlChar **localImports; /* list of locally imported namespaces */
257 int sizeLocalImports;
258 int nbLocalImports;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000259 xmlHashTablePtr substGroups;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +0000260 int isS4S;
Daniel Veillard4255d502002-04-16 15:50:10 +0000261};
262
Daniel Veillard4255d502002-04-16 15:50:10 +0000263#define XML_SCHEMAS_ATTR_UNKNOWN 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000264#define XML_SCHEMAS_ATTR_ASSESSED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000265#define XML_SCHEMAS_ATTR_PROHIBITED 3
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000266#define XML_SCHEMAS_ATTR_ERR_MISSING 4
Daniel Veillard3646d642004-06-02 19:19:14 +0000267#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000268#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
269#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000270#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000271#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000272#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
273#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
274#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
275#define XML_SCHEMAS_ATTR_WILD_SKIP 13
276#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
277#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
278#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
279#define XML_SCHEMAS_ATTR_META 17
Daniel Veillard4255d502002-04-16 15:50:10 +0000280
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000281/**
282 * xmlSchemaBasicItem:
283 *
284 * The abstract base type for schema components.
285 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000286typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
287typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
288struct _xmlSchemaBasicItem {
289 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000290};
291
292/**
293 * xmlSchemaAnnotItem:
294 *
295 * The abstract base type for annotated schema components.
296 * (Extends xmlSchemaBasicItem)
297 */
298typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
299typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
300struct _xmlSchemaAnnotItem {
301 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000302 xmlSchemaAnnotPtr annot;
303};
304
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000305/**
306 * xmlSchemaTreeItem:
307 *
308 * The abstract base type for tree-like structured schema components.
309 * (Extends xmlSchemaAnnotItem)
310 */
311typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
312typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
313struct _xmlSchemaTreeItem {
314 xmlSchemaTypeType type;
315 xmlSchemaAnnotPtr annot;
316 xmlSchemaTreeItemPtr next;
317 xmlSchemaTreeItemPtr children;
318};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000319
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000320/**
321 * xmlSchemaQNameRef:
322 *
323 * A component reference item (not a schema component)
324 * (Extends xmlSchemaBasicItem)
325 */
326typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
327typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
328struct _xmlSchemaQNameRef {
329 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000330 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000331 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000332 const xmlChar *name;
333 const xmlChar *targetNamespace;
334};
335
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000336/**
337 * xmlSchemaParticle:
338 *
339 * A particle component.
340 * (Extends xmlSchemaTreeItem)
341 */
342typedef struct _xmlSchemaParticle xmlSchemaParticle;
343typedef xmlSchemaParticle *xmlSchemaParticlePtr;
344struct _xmlSchemaParticle {
345 xmlSchemaTypeType type;
346 xmlSchemaAnnotPtr annot;
347 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
348 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
349 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000350 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000351 xmlNodePtr node;
352};
353
354/**
355 * xmlSchemaModelGroup:
356 *
357 * A model group component.
358 * (Extends xmlSchemaTreeItem)
359 */
360typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
361typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
362struct _xmlSchemaModelGroup {
363 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
364 xmlSchemaAnnotPtr annot;
365 xmlSchemaTreeItemPtr next; /* not used */
366 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
367 xmlNodePtr node;
368};
369
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000370#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000371/**
372 * xmlSchemaModelGroupDef:
373 *
374 * A model group definition component.
375 * (Extends xmlSchemaTreeItem)
376 */
377typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
378typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
379struct _xmlSchemaModelGroupDef {
380 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
381 xmlSchemaAnnotPtr annot;
382 xmlSchemaTreeItemPtr next; /* not used */
383 xmlSchemaTreeItemPtr children; /* the "model group" */
384 const xmlChar *name;
385 const xmlChar *targetNamespace;
386 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000387 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000388};
389
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000390typedef struct _xmlSchemaIDC xmlSchemaIDC;
391typedef xmlSchemaIDC *xmlSchemaIDCPtr;
392
393/**
394 * xmlSchemaIDCSelect:
395 *
396 * The identity-constraint "field" and "selector" item, holding the
397 * XPath expression.
398 */
399typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
400typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000401struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000402 xmlSchemaIDCSelectPtr next;
403 xmlSchemaIDCPtr idc;
404 int index; /* an index position if significant for IDC key-sequences */
405 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000406 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000407};
408
409/**
410 * xmlSchemaIDC:
411 *
412 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000413 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000414 */
415
416struct _xmlSchemaIDC {
417 xmlSchemaTypeType type;
418 xmlSchemaAnnotPtr annot;
419 xmlSchemaIDCPtr next;
420 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000421 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000422 const xmlChar *targetNamespace;
423 xmlSchemaIDCSelectPtr selector;
424 xmlSchemaIDCSelectPtr fields;
425 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000426 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000427};
428
429/**
430 * xmlSchemaIDCAug:
431 *
432 * The augmented IDC information used for validation.
433 */
434typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
435typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
436struct _xmlSchemaIDCAug {
437 xmlSchemaIDCAugPtr next; /* next in a list */
438 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000439 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000440 tables need to be bubbled upwards */
441};
442
443/**
444 * xmlSchemaPSVIIDCKeySequence:
445 *
446 * The key sequence of a node table item.
447 */
448typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
449typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
450struct _xmlSchemaPSVIIDCKey {
451 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000452 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000453};
454
455/**
456 * xmlSchemaPSVIIDCNode:
457 *
458 * The node table item of a node table.
459 */
460typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
461typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
462struct _xmlSchemaPSVIIDCNode {
463 xmlNodePtr node;
464 xmlSchemaPSVIIDCKeyPtr *keys;
465};
466
467/**
468 * xmlSchemaPSVIIDCBinding:
469 *
470 * The identity-constraint binding item of the [identity-constraint table].
471 */
472typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
473typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
474struct _xmlSchemaPSVIIDCBinding {
475 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
476 xmlSchemaIDCPtr definition; /* the IDC definition */
477 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
478 int nbNodes; /* number of entries in the node table */
479 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000480 int nbDupls; /* number of already identified duplicates in the node
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000481 table */
482 /* int nbKeys; number of keys in each key-sequence */
483};
484
485#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
486#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
487
488#define XPATH_STATE_OBJ_MATCHES -2
489#define XPATH_STATE_OBJ_BLOCKED -3
490
491typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
492typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
493
494/**
495 * xmlSchemaIDCStateObj:
496 *
497 * The state object used to evaluate XPath expressions.
498 */
499typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
500typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
501struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000502 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000503 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000504 int depth; /* depth of creation */
505 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000506 int nbHistory;
507 int sizeHistory;
508 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
509 matcher */
510 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000511 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000512};
513
514#define IDC_MATCHER 0
515
516/**
517 * xmlSchemaIDCMatcher:
518 *
519 * Used to IDC selectors (and fields) successively.
520 */
521struct _xmlSchemaIDCMatcher {
522 int type;
523 int depth; /* the tree depth at creation time */
524 xmlSchemaIDCMatcherPtr next; /* next in the list */
525 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
526 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
527 elements */
528 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000529 int targetDepth;
530};
531
532/*
533* Element info flags.
534*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000535#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
536#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
537#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
538#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
539
540#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
541#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
542#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
543
544#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
545#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
546#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
547#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000548
549/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000550 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000551 *
552 * Holds information of an element node.
553 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000554struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000555 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000556 int nodeType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000557 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000558 const xmlChar *nsName;
559 const xmlChar *value;
560 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000561 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000562 int flags; /* combination of node info flags */
563 int valNeeded;
564 int normVal;
565
566 xmlSchemaElementPtr decl; /* the element/attribute declaration */
567 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000568 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
569 for the scope element*/
570 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
571 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000572 xmlRegExecCtxtPtr regexCtxt;
573
574 const xmlChar **nsBindings; /* Namespace bindings on this element */
575 int nbNsBindings;
576 int sizeNsBindings;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000577};
578
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000579/*
580* @metaType values of xmlSchemaAttrInfo.
581*/
582#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
583#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
584#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
585#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
586#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000587
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000588typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
589typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
590struct _xmlSchemaAttrInfo {
591 xmlNodePtr node;
592 int nodeType;
593 const xmlChar *localName;
594 const xmlChar *nsName;
595 const xmlChar *value;
596 xmlSchemaValPtr val; /* the pre-computed value if any */
597 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
598 int flags; /* combination of node info flags */
599
600 xmlSchemaAttributePtr decl; /* the attribute declaration */
601 xmlSchemaAttributePtr use; /* the attribute use */
602 int state;
603 int metaType;
604 const xmlChar *vcValue; /* the value constraint value */
605 xmlSchemaNodeInfoPtr parent;
606};
607
608
609#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000610/**
611 * xmlSchemaValidCtxt:
612 *
613 * A Schemas validation context
614 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000615struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000616 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000617 void *userData; /* user specific data block */
618 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000619 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000620 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000621
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000622 xmlSchemaPtr schema; /* The schema in use */
623 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000624 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000625 xmlCharEncoding enc;
626 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000627 xmlParserCtxtPtr parserCtxt;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000628 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000629
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000630 int err;
631 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000632
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000633 xmlNodePtr node;
634 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000635 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000636
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000637 xmlRegExecCtxtPtr regexp;
638 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000639
Daniel Veillardc0826a72004-08-10 14:17:33 +0000640 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000641 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000642 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000643 xmlSchemaParserCtxtPtr pctxt;
644 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000645
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000646 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000647 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000648 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000649 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000650
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000651 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
652
653 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
654 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000655
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000656 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
657 int nbIdcNodes;
658 int sizeIdcNodes;
659
660 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
661 int nbIdcKeys;
662 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000663
664 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000665
666 xmlDictPtr dict;
667
Daniel Veillard39e5c892005-07-03 22:48:50 +0000668#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000669 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +0000670#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000671
672 xmlSchemaAttrInfoPtr *attrInfos;
673 int nbAttrInfos;
674 int sizeAttrInfos;
675
676 int skipDepth;
Daniel Veillard4255d502002-04-16 15:50:10 +0000677};
678
Daniel Veillard1d913862003-11-21 00:28:39 +0000679/*
680 * These are the entries in the schemas importSchemas hash table
681 */
682typedef struct _xmlSchemaImport xmlSchemaImport;
683typedef xmlSchemaImport *xmlSchemaImportPtr;
684struct _xmlSchemaImport {
685 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000686 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000687 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000688 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000689};
Daniel Veillard4255d502002-04-16 15:50:10 +0000690
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000691/*
692 * These are the entries associated to includes in a schemas
693 */
694typedef struct _xmlSchemaInclude xmlSchemaInclude;
695typedef xmlSchemaInclude *xmlSchemaIncludePtr;
696struct _xmlSchemaInclude {
697 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000698 const xmlChar *schemaLocation;
699 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000700 const xmlChar *origTargetNamespace;
701 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000702};
703
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000704/**
705 * xmlSchemaSubstGroup:
706 *
707 *
708 */
709typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
710typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
711struct _xmlSchemaSubstGroup {
712 xmlSchemaElementPtr head;
713 xmlSchemaItemListPtr members;
714};
715
Daniel Veillard4255d502002-04-16 15:50:10 +0000716/************************************************************************
717 * *
718 * Some predeclarations *
719 * *
720 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000721
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000722static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
723 xmlSchemaPtr schema,
724 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000725static void
726xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
727 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000728static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000729xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
730static int
William M. Brack2f2a6632004-08-20 23:09:47 +0000731xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
732 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000733static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000734xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
735 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000736static void
737xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000738static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000739xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000740static xmlSchemaTreeItemPtr
741xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
742 xmlNodePtr node, xmlSchemaTypeType type,
743 int withParticle);
744static const xmlChar *
745xmlSchemaCompTypeToString(xmlSchemaTypeType type);
746static xmlSchemaTypeLinkPtr
747xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000748static void
749xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
750 const char *funcName,
751 const char *message);
752static int
753xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
754 xmlSchemaTypePtr baseType,
755 int subset);
756static void
757xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
758 xmlSchemaParserCtxtPtr ctxt,
759 const xmlChar * name ATTRIBUTE_UNUSED);
William M. Brack87640d52004-04-17 14:58:15 +0000760
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000761/************************************************************************
762 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000763 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000764 * *
765 ************************************************************************/
766
767/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000768 * xmlSchemaCompTypeToString:
769 * @type: the type of the schema item
770 *
771 * Returns the component name of a schema item.
772 */
773static const xmlChar *
774xmlSchemaCompTypeToString(xmlSchemaTypeType type)
775{
776 switch (type) {
777 case XML_SCHEMA_TYPE_SIMPLE:
778 return(BAD_CAST "simple type definition");
779 case XML_SCHEMA_TYPE_COMPLEX:
780 return(BAD_CAST "complex type definition");
781 case XML_SCHEMA_TYPE_ELEMENT:
782 return(BAD_CAST "element declaration");
783 case XML_SCHEMA_TYPE_ATTRIBUTE:
784 return(BAD_CAST "attribute declaration");
785 case XML_SCHEMA_TYPE_GROUP:
786 return(BAD_CAST "model group definition");
787 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
788 return(BAD_CAST "attribute group definition");
789 case XML_SCHEMA_TYPE_NOTATION:
790 return(BAD_CAST "notation declaration");
791 case XML_SCHEMA_TYPE_SEQUENCE:
792 return(BAD_CAST "model group (sequence)");
793 case XML_SCHEMA_TYPE_CHOICE:
794 return(BAD_CAST "model group (choice)");
795 case XML_SCHEMA_TYPE_ALL:
796 return(BAD_CAST "model group (all)");
797 case XML_SCHEMA_TYPE_PARTICLE:
798 return(BAD_CAST "particle");
799 default:
800 return(BAD_CAST "Not a schema component");
801 }
802}
803
804/**
805 * xmlSchemaGetComponentNode:
806 * @item: a schema component
807 *
808 * Returns node associated with the schema component.
809 * NOTE that such a node need not be available; plus, a component's
810 * node need not to reflect the component directly, since there is no
811 * one-to-one relationship between the XML Schema representation and
812 * the component representation.
813 */
814static xmlNodePtr
815xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
816{
817 switch (item->type) {
818 case XML_SCHEMA_TYPE_ELEMENT:
819 return (((xmlSchemaElementPtr) item)->node);
820 case XML_SCHEMA_TYPE_ATTRIBUTE:
821 return (((xmlSchemaAttributePtr) item)->node);
822 case XML_SCHEMA_TYPE_COMPLEX:
823 case XML_SCHEMA_TYPE_SIMPLE:
824 return (((xmlSchemaTypePtr) item)->node);
825 case XML_SCHEMA_TYPE_ANY:
826 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
827 return (((xmlSchemaWildcardPtr) item)->node);
828 case XML_SCHEMA_TYPE_PARTICLE:
829 return (((xmlSchemaParticlePtr) item)->node);
830 case XML_SCHEMA_TYPE_SEQUENCE:
831 case XML_SCHEMA_TYPE_CHOICE:
832 case XML_SCHEMA_TYPE_ALL:
833 return (((xmlSchemaModelGroupPtr) item)->node);
834 case XML_SCHEMA_TYPE_GROUP:
835 return (((xmlSchemaModelGroupDefPtr) item)->node);
836 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
837 return (((xmlSchemaAttributeGroupPtr) item)->node);
838 case XML_SCHEMA_TYPE_IDC_UNIQUE:
839 case XML_SCHEMA_TYPE_IDC_KEY:
840 case XML_SCHEMA_TYPE_IDC_KEYREF:
841 return (((xmlSchemaIDCPtr) item)->node);
842 default:
843 return (NULL);
844 }
845}
846
847#if 0
848/**
849 * xmlSchemaGetNextComponent:
850 * @item: a schema component
851 *
852 * Returns the next sibling of the schema component.
853 */
854static xmlSchemaBasicItemPtr
855xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
856{
857 switch (item->type) {
858 case XML_SCHEMA_TYPE_ELEMENT:
859 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
860 case XML_SCHEMA_TYPE_ATTRIBUTE:
861 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
862 case XML_SCHEMA_TYPE_COMPLEX:
863 case XML_SCHEMA_TYPE_SIMPLE:
864 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
865 case XML_SCHEMA_TYPE_ANY:
866 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
867 return (NULL);
868 case XML_SCHEMA_TYPE_PARTICLE:
869 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
870 case XML_SCHEMA_TYPE_SEQUENCE:
871 case XML_SCHEMA_TYPE_CHOICE:
872 case XML_SCHEMA_TYPE_ALL:
873 return (NULL);
874 case XML_SCHEMA_TYPE_GROUP:
875 return (NULL);
876 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
877 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
878 case XML_SCHEMA_TYPE_IDC_UNIQUE:
879 case XML_SCHEMA_TYPE_IDC_KEY:
880 case XML_SCHEMA_TYPE_IDC_KEYREF:
881 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
882 default:
883 return (NULL);
884 }
885}
886#endif
887
888/**
889 * xmlSchemaGetAttrName:
890 * @attr: the attribute declaration/use
891 *
892 * Returns the name of the attribute; if the attribute
893 * is a reference, the name of the referenced global type will be returned.
894 */
895static const xmlChar *
896xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
897{
898 if (attr->ref != NULL)
899 return(attr->ref);
900 else
901 return(attr->name);
902}
903
904/**
905 * xmlSchemaGetAttrTargetNsURI:
906 * @type: the type (element or attribute)
907 *
908 * Returns the target namespace URI of the type; if the type is a reference,
909 * the target namespace of the referenced type will be returned.
910 */
911static const xmlChar *
912xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
913{
914 if (attr->ref != NULL)
915 return (attr->refNs);
916 else
917 return(attr->targetNamespace);
918}
919
920/**
921 * xmlSchemaFormatQName:
922 * @buf: the string buffer
923 * @namespaceName: the namespace name
924 * @localName: the local name
925 *
926 * Returns the given QName in the format "{namespaceName}localName" or
927 * just "localName" if @namespaceName is NULL.
928 *
929 * Returns the localName if @namespaceName is NULL, a formatted
930 * string otherwise.
931 */
932static const xmlChar*
933xmlSchemaFormatQName(xmlChar **buf,
934 const xmlChar *namespaceName,
935 const xmlChar *localName)
936{
937 FREE_AND_NULL(*buf)
938 if (namespaceName == NULL)
939 return(localName);
940
941 *buf = xmlStrdup(BAD_CAST "{");
942 *buf = xmlStrcat(*buf, namespaceName);
943 *buf = xmlStrcat(*buf, BAD_CAST "}");
944 *buf = xmlStrcat(*buf, localName);
945
946 return ((const xmlChar *) *buf);
947}
948
949static const xmlChar*
950xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
951{
952 if (ns != NULL)
953 return (xmlSchemaFormatQName(buf, ns->href, localName));
954 else
955 return (xmlSchemaFormatQName(buf, NULL, localName));
956}
957
958static const xmlChar *
959xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
960{
961 switch (item->type) {
962 case XML_SCHEMA_TYPE_ELEMENT:
963 return (((xmlSchemaElementPtr) item)->name);
964 case XML_SCHEMA_TYPE_ATTRIBUTE:
965 return (((xmlSchemaAttributePtr) item)->name);
966 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
967 return (((xmlSchemaAttributeGroupPtr) item)->name);
968 case XML_SCHEMA_TYPE_BASIC:
969 case XML_SCHEMA_TYPE_SIMPLE:
970 case XML_SCHEMA_TYPE_COMPLEX:
971 return (((xmlSchemaTypePtr) item)->name);
972 case XML_SCHEMA_TYPE_GROUP:
973 return (((xmlSchemaModelGroupDefPtr) item)->name);
974 case XML_SCHEMA_TYPE_IDC_KEY:
975 case XML_SCHEMA_TYPE_IDC_UNIQUE:
976 case XML_SCHEMA_TYPE_IDC_KEYREF:
977 return (((xmlSchemaIDCPtr) item)->name);
978 default:
979 /*
980 * Other components cannot have names.
981 */
982 break;
983 }
984 return (NULL);
985}
986
987static const xmlChar *
988xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
989{
990 switch (item->type) {
991 case XML_SCHEMA_TYPE_ELEMENT:
992 return (((xmlSchemaElementPtr) item)->targetNamespace);
993 case XML_SCHEMA_TYPE_ATTRIBUTE:
994 return (((xmlSchemaAttributePtr) item)->targetNamespace);
995 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
996 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
997 case XML_SCHEMA_TYPE_BASIC:
998 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
999 case XML_SCHEMA_TYPE_SIMPLE:
1000 case XML_SCHEMA_TYPE_COMPLEX:
1001 return (((xmlSchemaTypePtr) item)->targetNamespace);
1002 case XML_SCHEMA_TYPE_GROUP:
1003 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1004 case XML_SCHEMA_TYPE_IDC_KEY:
1005 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1006 case XML_SCHEMA_TYPE_IDC_KEYREF:
1007 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1008 default:
1009 /*
1010 * Other components cannot have names.
1011 */
1012 break;
1013 }
1014 return (NULL);
1015}
1016
1017static const xmlChar*
1018xmlSchemaGetComponentQName(xmlChar **buf,
1019 void *item)
1020{
1021 return (xmlSchemaFormatQName(buf,
1022 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1023 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1024}
1025
1026/**
1027 * xmlSchemaWildcardPCToString:
1028 * @pc: the type of processContents
1029 *
1030 * Returns a string representation of the type of
1031 * processContents.
1032 */
1033static const xmlChar *
1034xmlSchemaWildcardPCToString(int pc)
1035{
1036 switch (pc) {
1037 case XML_SCHEMAS_ANY_SKIP:
1038 return (BAD_CAST "skip");
1039 case XML_SCHEMAS_ANY_LAX:
1040 return (BAD_CAST "lax");
1041 case XML_SCHEMAS_ANY_STRICT:
1042 return (BAD_CAST "strict");
1043 default:
1044 return (BAD_CAST "invalid process contents");
1045 }
1046}
1047
1048/**
1049 * xmlSchemaGetCanonValueWhtspExt:
1050 * @val: the precomputed value
1051 * @retValue: the returned value
1052 * @ws: the whitespace type of the value
1053 *
1054 * Get a the cononical representation of the value.
1055 * The caller has to free the returned retValue.
1056 *
1057 * Returns 0 if the value could be built and -1 in case of
1058 * API errors or if the value type is not supported yet.
1059 */
1060static int
1061xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1062 xmlSchemaWhitespaceValueType ws,
1063 xmlChar **retValue)
1064{
1065 int list;
1066 xmlSchemaValType valType;
1067 const xmlChar *value, *value2 = NULL;
1068
1069
1070 if ((retValue == NULL) || (val == NULL))
1071 return (-1);
1072 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1073 *retValue = NULL;
1074 do {
1075 value = NULL;
1076 valType = xmlSchemaGetValType(val);
1077 switch (valType) {
1078 case XML_SCHEMAS_STRING:
1079 case XML_SCHEMAS_NORMSTRING:
1080 case XML_SCHEMAS_ANYSIMPLETYPE:
1081 value = xmlSchemaValueGetAsString(val);
1082 if (value != NULL) {
1083 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1084 value2 = xmlSchemaCollapseString(value);
1085 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1086 value2 = xmlSchemaWhiteSpaceReplace(value);
1087 if (value2 != NULL)
1088 value = value2;
1089 }
1090 break;
1091 default:
1092 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1093 if (value2 != NULL)
1094 xmlFree((xmlChar *) value2);
1095 goto internal_error;
1096 }
1097 value = value2;
1098 }
1099 if (*retValue == NULL)
1100 if (value == NULL) {
1101 if (! list)
1102 *retValue = xmlStrdup(BAD_CAST "");
1103 } else
1104 *retValue = xmlStrdup(value);
1105 else if (value != NULL) {
1106 /* List. */
1107 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1108 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1109 }
1110 FREE_AND_NULL(value2)
1111 val = xmlSchemaValueGetNext(val);
1112 } while (val != NULL);
1113
1114 return (0);
1115internal_error:
1116 if (*retValue != NULL)
1117 xmlFree((xmlChar *) (*retValue));
1118 if (value2 != NULL)
1119 xmlFree((xmlChar *) value2);
1120 return (-1);
1121}
1122
1123/**
1124 * xmlSchemaFormatItemForReport:
1125 * @buf: the string buffer
1126 * @itemDes: the designation of the item
1127 * @itemName: the name of the item
1128 * @item: the item as an object
1129 * @itemNode: the node of the item
1130 * @local: the local name
1131 * @parsing: if the function is used during the parse
1132 *
1133 * Returns a representation of the given item used
1134 * for error reports.
1135 *
1136 * The following order is used to build the resulting
1137 * designation if the arguments are not NULL:
1138 * 1a. If itemDes not NULL -> itemDes
1139 * 1b. If (itemDes not NULL) and (itemName not NULL)
1140 * -> itemDes + itemName
1141 * 2. If the preceding was NULL and (item not NULL) -> item
1142 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1143 *
1144 * If the itemNode is an attribute node, the name of the attribute
1145 * will be appended to the result.
1146 *
1147 * Returns the formatted string and sets @buf to the resulting value.
1148 */
1149static xmlChar*
1150xmlSchemaFormatItemForReport(xmlChar **buf,
1151 const xmlChar *itemDes,
1152 xmlSchemaTypePtr item,
1153 xmlNodePtr itemNode)
1154{
1155 xmlChar *str = NULL;
1156 int named = 1;
1157
1158 if (*buf != NULL) {
1159 xmlFree(*buf);
1160 *buf = NULL;
1161 }
1162
1163 if (itemDes != NULL) {
1164 *buf = xmlStrdup(itemDes);
1165 } else if (item != NULL) {
1166 switch (item->type) {
1167 case XML_SCHEMA_TYPE_BASIC:
1168 if (VARIETY_ATOMIC(item))
1169 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1170 else if (VARIETY_LIST(item))
1171 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1172 else if (VARIETY_UNION(item))
1173 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1174 else
1175 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1176 *buf = xmlStrcat(*buf, item->name);
1177 *buf = xmlStrcat(*buf, BAD_CAST "'");
1178 break;
1179 case XML_SCHEMA_TYPE_SIMPLE:
1180 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1181 *buf = xmlStrdup(BAD_CAST"");
1182 } else {
1183 *buf = xmlStrdup(BAD_CAST "local ");
1184 }
1185 if (VARIETY_ATOMIC(item))
1186 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1187 else if (VARIETY_LIST(item))
1188 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1189 else if (VARIETY_UNION(item))
1190 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1191 else
1192 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1193 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1194 *buf = xmlStrcat(*buf, BAD_CAST " '");
1195 *buf = xmlStrcat(*buf, item->name);
1196 *buf = xmlStrcat(*buf, BAD_CAST "'");
1197 }
1198 break;
1199 case XML_SCHEMA_TYPE_COMPLEX:
1200 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1201 *buf = xmlStrdup(BAD_CAST "");
1202 else
1203 *buf = xmlStrdup(BAD_CAST "local ");
1204 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1205 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1206 *buf = xmlStrcat(*buf, BAD_CAST " '");
1207 *buf = xmlStrcat(*buf, item->name);
1208 *buf = xmlStrcat(*buf, BAD_CAST "'");
1209 }
1210 break;
1211 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1212 xmlSchemaAttributePtr attr;
1213
1214 attr = (xmlSchemaAttributePtr) item;
1215 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
1216 (attr->ref == NULL)) {
1217 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1218 *buf = xmlStrcat(*buf, BAD_CAST " '");
1219 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1220 attr->targetNamespace, attr->name));
1221 FREE_AND_NULL(str)
1222 *buf = xmlStrcat(*buf, BAD_CAST "'");
1223 } else {
1224 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1225 *buf = xmlStrcat(*buf, BAD_CAST " '");
1226 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1227 attr->refNs, attr->ref));
1228 FREE_AND_NULL(str)
1229 *buf = xmlStrcat(*buf, BAD_CAST "'");
1230 }
1231 }
1232 break;
1233 case XML_SCHEMA_TYPE_ELEMENT: {
1234 xmlSchemaElementPtr elem;
1235
1236 elem = (xmlSchemaElementPtr) item;
1237 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
1238 (elem->ref == NULL)) {
1239 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1240 *buf = xmlStrcat(*buf, BAD_CAST " '");
1241 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1242 elem->targetNamespace, elem->name));
1243 *buf = xmlStrcat(*buf, BAD_CAST "'");
1244 }
1245 }
1246 break;
1247 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1248 case XML_SCHEMA_TYPE_IDC_KEY:
1249 case XML_SCHEMA_TYPE_IDC_KEYREF:
1250 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1251 *buf = xmlStrdup(BAD_CAST "unique '");
1252 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1253 *buf = xmlStrdup(BAD_CAST "key '");
1254 else
1255 *buf = xmlStrdup(BAD_CAST "keyRef '");
1256 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1257 *buf = xmlStrcat(*buf, BAD_CAST "'");
1258 break;
1259 case XML_SCHEMA_TYPE_ANY:
1260 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1261 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1262 ((xmlSchemaWildcardPtr) item)->processContents));
1263 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1264 break;
1265 case XML_SCHEMA_FACET_MININCLUSIVE:
1266 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1267 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1268 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1269 case XML_SCHEMA_FACET_TOTALDIGITS:
1270 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1271 case XML_SCHEMA_FACET_PATTERN:
1272 case XML_SCHEMA_FACET_ENUMERATION:
1273 case XML_SCHEMA_FACET_WHITESPACE:
1274 case XML_SCHEMA_FACET_LENGTH:
1275 case XML_SCHEMA_FACET_MAXLENGTH:
1276 case XML_SCHEMA_FACET_MINLENGTH:
1277 *buf = xmlStrdup(BAD_CAST "facet '");
1278 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1279 *buf = xmlStrcat(*buf, BAD_CAST "'");
1280 break;
1281 case XML_SCHEMA_TYPE_NOTATION:
1282 *buf = xmlStrdup(BAD_CAST "notation");
1283 break;
1284 case XML_SCHEMA_TYPE_GROUP: {
1285 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1286 *buf = xmlStrcat(*buf, BAD_CAST " '");
1287 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1288 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1289 ((xmlSchemaModelGroupDefPtr) item)->name));
1290 *buf = xmlStrcat(*buf, BAD_CAST "'");
1291 FREE_AND_NULL(str)
1292 }
1293 break;
1294 case XML_SCHEMA_TYPE_SEQUENCE:
1295 case XML_SCHEMA_TYPE_CHOICE:
1296 case XML_SCHEMA_TYPE_ALL:
1297 case XML_SCHEMA_TYPE_PARTICLE:
1298 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1299 break;
1300 default:
1301 named = 0;
1302 }
1303 } else
1304 named = 0;
1305
1306 if ((named == 0) && (itemNode != NULL)) {
1307 xmlNodePtr elem;
1308
1309 if (itemNode->type == XML_ATTRIBUTE_NODE)
1310 elem = itemNode->parent;
1311 else
1312 elem = itemNode;
1313 *buf = xmlStrdup(BAD_CAST "Element '");
1314 if (elem->ns != NULL) {
1315 *buf = xmlStrcat(*buf,
1316 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1317 FREE_AND_NULL(str)
1318 } else
1319 *buf = xmlStrcat(*buf, elem->name);
1320 *buf = xmlStrcat(*buf, BAD_CAST "'");
1321
1322 }
1323 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1324 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1325 if (itemNode->ns != NULL) {
1326 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1327 itemNode->ns->href, itemNode->name));
1328 FREE_AND_NULL(str)
1329 } else
1330 *buf = xmlStrcat(*buf, itemNode->name);
1331 *buf = xmlStrcat(*buf, BAD_CAST "'");
1332 }
1333 FREE_AND_NULL(str)
1334
1335 return (*buf);
1336}
1337
1338/**
1339 * xmlSchemaFormatFacetEnumSet:
1340 * @buf: the string buffer
1341 * @type: the type holding the enumeration facets
1342 *
1343 * Builds a string consisting of all enumeration elements.
1344 *
1345 * Returns a string of all enumeration elements.
1346 */
1347static const xmlChar *
1348xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1349 xmlChar **buf, xmlSchemaTypePtr type)
1350{
1351 xmlSchemaFacetPtr facet;
1352 xmlSchemaWhitespaceValueType ws;
1353 xmlChar *value = NULL;
1354 int res;
1355
1356 if (*buf != NULL)
1357 xmlFree(*buf);
1358 *buf = NULL;
1359
1360 do {
1361 /*
1362 * Use the whitespace type of the base type.
1363 */
1364 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1365 for (facet = type->facets; facet != NULL; facet = facet->next) {
1366 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1367 continue;
1368 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1369 ws, &value);
1370 if (res == -1) {
1371 xmlSchemaInternalErr(actxt,
1372 "xmlSchemaFormatFacetEnumSet",
1373 "compute the canonical lexical representation");
1374 if (*buf != NULL)
1375 xmlFree(*buf);
1376 *buf = NULL;
1377 return (NULL);
1378 }
1379 if (*buf == NULL)
1380 *buf = xmlStrdup(BAD_CAST "'");
1381 else
1382 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1383 *buf = xmlStrcat(*buf, BAD_CAST value);
1384 *buf = xmlStrcat(*buf, BAD_CAST "'");
1385 if (value != NULL) {
1386 xmlFree((xmlChar *)value);
1387 value = NULL;
1388 }
1389 }
1390 type = type->baseType;
1391 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1392
1393 return ((const xmlChar *) *buf);
1394}
1395
1396/************************************************************************
1397 * *
1398 * Error functions *
1399 * *
1400 ************************************************************************/
1401
1402#if 0
1403static void
1404xmlSchemaErrMemory(const char *msg)
1405{
1406 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1407 msg);
1408}
1409#endif
1410
1411/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001412 * xmlSchemaPErrMemory:
1413 * @node: a context node
1414 * @extra: extra informations
1415 *
1416 * Handle an out of memory condition
1417 */
1418static void
1419xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1420 const char *extra, xmlNodePtr node)
1421{
1422 if (ctxt != NULL)
1423 ctxt->nberrors++;
1424 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1425 extra);
1426}
1427
1428/**
1429 * xmlSchemaPErr:
1430 * @ctxt: the parsing context
1431 * @node: the context node
1432 * @error: the error code
1433 * @msg: the error message
1434 * @str1: extra data
1435 * @str2: extra data
1436 *
1437 * Handle a parser error
1438 */
1439static void
1440xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1441 const char *msg, const xmlChar * str1, const xmlChar * str2)
1442{
1443 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001444 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001445 void *data = NULL;
1446
1447 if (ctxt != NULL) {
1448 ctxt->nberrors++;
1449 channel = ctxt->error;
1450 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001451 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001452 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001453 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001454 error, XML_ERR_ERROR, NULL, 0,
1455 (const char *) str1, (const char *) str2, NULL, 0, 0,
1456 msg, str1, str2);
1457}
1458
1459/**
1460 * xmlSchemaPErr2:
1461 * @ctxt: the parsing context
1462 * @node: the context node
1463 * @node: the current child
1464 * @error: the error code
1465 * @msg: the error message
1466 * @str1: extra data
1467 * @str2: extra data
1468 *
1469 * Handle a parser error
1470 */
1471static void
1472xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1473 xmlNodePtr child, int error,
1474 const char *msg, const xmlChar * str1, const xmlChar * str2)
1475{
1476 if (child != NULL)
1477 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1478 else
1479 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1480}
1481
Daniel Veillard01fa6152004-06-29 17:04:39 +00001482
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001483/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001484 * xmlSchemaPErrExt:
1485 * @ctxt: the parsing context
1486 * @node: the context node
1487 * @error: the error code
1488 * @strData1: extra data
1489 * @strData2: extra data
1490 * @strData3: extra data
1491 * @msg: the message
1492 * @str1: extra parameter for the message display
1493 * @str2: extra parameter for the message display
1494 * @str3: extra parameter for the message display
1495 * @str4: extra parameter for the message display
1496 * @str5: extra parameter for the message display
1497 *
1498 * Handle a parser error
1499 */
1500static void
1501xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1502 const xmlChar * strData1, const xmlChar * strData2,
1503 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1504 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1505 const xmlChar * str5)
1506{
1507
1508 xmlGenericErrorFunc channel = NULL;
1509 xmlStructuredErrorFunc schannel = NULL;
1510 void *data = NULL;
1511
1512 if (ctxt != NULL) {
1513 ctxt->nberrors++;
1514 channel = ctxt->error;
1515 data = ctxt->userData;
1516 schannel = ctxt->serror;
1517 }
1518 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1519 error, XML_ERR_ERROR, NULL, 0,
1520 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001521 (const char *) strData3, 0, 0, msg, str1, str2,
1522 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001523}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001524
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001525/************************************************************************
1526 * *
1527 * Allround error functions *
1528 * *
1529 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001530
1531/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001532 * xmlSchemaVTypeErrMemory:
1533 * @node: a context node
1534 * @extra: extra informations
1535 *
1536 * Handle an out of memory condition
1537 */
1538static void
1539xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1540 const char *extra, xmlNodePtr node)
1541{
1542 if (ctxt != NULL) {
1543 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001544 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001545 }
1546 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1547 extra);
1548}
1549
1550/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001551 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001552 * @ctxt: the validation context
1553 * @node: the context node
1554 * @error: the error code
1555 * @msg: the error message
1556 * @str1: extra data
1557 * @str2: extra data
1558 * @str3: extra data
1559 *
1560 * Handle a validation error
1561 */
1562static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001563xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt,
1564 int error, xmlNodePtr node, const char *msg,
1565 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001566{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001567 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001568 xmlGenericErrorFunc channel = NULL;
1569 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001570
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001571 if (ctxt != NULL) {
1572 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1573 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00001574 int line = 0;
1575 const char *file = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001576
1577 vctxt->nberrors++;
1578 vctxt->err = error;
1579 channel = vctxt->error;
1580 schannel = vctxt->serror;
1581 data = vctxt->userData;
1582 if ((node == NULL) && (vctxt->depth >= 0) &&
Daniel Veillard971771e2005-07-09 17:32:57 +00001583 (vctxt->inode != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001584 node = vctxt->inode->node;
Daniel Veillard971771e2005-07-09 17:32:57 +00001585 }
1586 if ((node == NULL) && (vctxt->parserCtxt != NULL) &&
1587 (vctxt->parserCtxt->input != NULL)) {
1588 file = vctxt->parserCtxt->input->filename;
1589 line = vctxt->parserCtxt->input->line;
1590 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001591 __xmlRaiseError(schannel, channel, data, ctxt,
1592 node, XML_FROM_SCHEMASV,
Daniel Veillard971771e2005-07-09 17:32:57 +00001593 error, XML_ERR_ERROR, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001594 (const char *) str1, (const char *) str2,
1595 (const char *) str3, 0, 0, msg, str1, str2, str3);
1596
1597 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
1598 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
1599
1600 pctxt->nberrors++;
1601 pctxt->err = error;
1602 channel = pctxt->error;
1603 schannel = pctxt->serror;
1604 data = pctxt->userData;
1605 __xmlRaiseError(schannel, channel, data, ctxt,
1606 node, XML_FROM_SCHEMASP,
1607 error, XML_ERR_ERROR, NULL, 0,
1608 (const char *) str1, (const char *) str2,
1609 (const char *) str3, 0, 0, msg, str1, str2, str3);
1610 } else {
1611 TODO
1612 }
1613 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001614}
1615
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001616static void
1617xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
1618 int error, xmlNodePtr node, const char *msg,
1619 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001620{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001621 xmlSchemaErr3(actxt, error, node, msg, str1, str2, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001622}
1623
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001624static xmlChar *
1625xmlSchemaFormatNodeForError(xmlChar ** msg,
1626 xmlSchemaAbstractCtxtPtr actxt,
1627 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001628{
1629 xmlChar *str = NULL;
1630
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001631 if (node != NULL) {
1632 /*
1633 * Work on tree nodes.
1634 */
1635 if (node->type == XML_ATTRIBUTE_NODE) {
1636 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001637
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001638 *msg = xmlStrdup(BAD_CAST "Element '");
1639 if (elem->ns != NULL)
1640 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1641 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001642 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001643 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1644 NULL, elem->name));
1645 FREE_AND_NULL(str);
1646 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1647 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1648 } else {
1649 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001650 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001651 if (node->ns != NULL)
1652 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1653 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001654 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001655 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1656 NULL, node->name));
1657 FREE_AND_NULL(str);
1658 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1659 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1660 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
1661 /*
1662 * Work on node infos.
1663 */
1664 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
1665 xmlSchemaNodeInfoPtr ielem =
1666 vctxt->elemInfos[vctxt->depth];
1667
1668 *msg = xmlStrdup(BAD_CAST "Element '");
1669 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1670 ielem->nsName, ielem->localName));
1671 FREE_AND_NULL(str);
1672 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1673 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1674 } else {
1675 *msg = xmlStrdup(BAD_CAST "Element '");
1676 }
1677 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1678 vctxt->inode->nsName, vctxt->inode->localName));
1679 FREE_AND_NULL(str);
1680 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1681 } else {
1682 TODO
1683 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001684 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001685 /*
1686 * VAL TODO: The output of the given schema component is currently
1687 * disabled.
1688 */
1689#if 0
1690 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
1691 *msg = xmlStrcat(*msg, BAD_CAST " [");
1692 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
1693 NULL, type, NULL, 0));
1694 FREE_AND_NULL(str)
1695 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001696 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001697#endif
1698 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001699}
1700
Daniel Veillardc0826a72004-08-10 14:17:33 +00001701static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001702xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1703 const char *funcName,
1704 const char *message)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001705{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001706 xmlChar *msg = NULL;
1707
1708 msg = xmlStrdup(BAD_CAST "Internal error: ");
1709 msg = xmlStrcat(msg, BAD_CAST funcName);
1710 msg = xmlStrcat(msg, BAD_CAST ", ");
1711 msg = xmlStrcat(msg, BAD_CAST message);
1712 msg = xmlStrcat(msg, BAD_CAST ".\n");
1713
1714 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
1715 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
1716 (const char *) msg, NULL, NULL);
1717
1718 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
1719 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
1720 (const char *) msg, NULL, NULL);
1721
1722 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001723}
1724
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001725static void
1726xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
1727 xmlParserErrors error,
1728 xmlNodePtr node,
1729 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1730 const char *message,
1731 const xmlChar *str1,
1732 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001733{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001734 xmlChar *msg = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001735
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001736 xmlSchemaFormatNodeForError(&msg, actxt, node);
1737 msg = xmlStrcat(msg, (const xmlChar *) message);
1738 msg = xmlStrcat(msg, BAD_CAST ".\n");
1739 xmlSchemaErr(actxt, error, node,
1740 (const char *) msg, str1, str2);
1741 FREE_AND_NULL(msg)
1742}
1743
1744static int
1745xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
1746 xmlNodePtr node)
1747{
1748 if (node != NULL)
1749 return (node->type);
1750 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
1751 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
1752 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
1753 return (-1);
1754}
1755
1756static int
1757xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1758{
1759 switch (item->type) {
1760 case XML_SCHEMA_TYPE_COMPLEX:
1761 case XML_SCHEMA_TYPE_SIMPLE:
1762 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1763 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001764 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001765 case XML_SCHEMA_TYPE_GROUP:
1766 return (1);
1767 case XML_SCHEMA_TYPE_ELEMENT:
1768 if ( ((xmlSchemaElementPtr) item)->flags &
1769 XML_SCHEMAS_ELEM_GLOBAL)
1770 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001771 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001772 case XML_SCHEMA_TYPE_ATTRIBUTE:
1773 if ( ((xmlSchemaAttributePtr) item)->flags &
1774 XML_SCHEMAS_ATTR_GLOBAL)
1775 return(1);
1776 break;
1777 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001778 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001779 return(1);
1780 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001781 return (0);
1782}
1783
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001784static void
1785xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1786 xmlParserErrors error,
1787 xmlNodePtr node,
1788 const xmlChar *value,
1789 xmlSchemaTypePtr type,
1790 int displayValue)
1791{
1792 xmlChar *msg = NULL;
1793
1794 xmlSchemaFormatNodeForError(&msg, actxt, node);
1795
1796 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1797 XML_ATTRIBUTE_NODE))
1798 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
1799 else
1800 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
1801 "value of ");
1802
1803 if (! xmlSchemaIsGlobalItem(type))
1804 msg = xmlStrcat(msg, BAD_CAST "the local ");
1805 else
1806 msg = xmlStrcat(msg, BAD_CAST "the ");
1807
1808 if (VARIETY_ATOMIC(type))
1809 msg = xmlStrcat(msg, BAD_CAST "atomic type");
1810 else if (VARIETY_LIST(type))
1811 msg = xmlStrcat(msg, BAD_CAST "list type");
1812 else if (VARIETY_UNION(type))
1813 msg = xmlStrcat(msg, BAD_CAST "union type");
1814
1815 if (xmlSchemaIsGlobalItem(type)) {
1816 xmlChar *str = NULL;
1817 msg = xmlStrcat(msg, BAD_CAST " '");
1818 if (type->builtInType != 0) {
1819 msg = xmlStrcat(msg, BAD_CAST "xs:");
1820 msg = xmlStrcat(msg, type->name);
1821 } else
1822 msg = xmlStrcat(msg,
1823 xmlSchemaFormatQName(&str,
1824 type->targetNamespace, type->name));
1825 msg = xmlStrcat(msg, BAD_CAST "'");
1826 FREE_AND_NULL(str);
1827 }
1828 msg = xmlStrcat(msg, BAD_CAST ".\n");
1829 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1830 XML_ATTRIBUTE_NODE))
1831 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
1832 else
1833 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
1834 FREE_AND_NULL(msg)
1835}
1836
Daniel Veillardc0826a72004-08-10 14:17:33 +00001837static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001838xmlSchemaFormatErrorNodeQName(xmlChar ** str,
1839 xmlSchemaNodeInfoPtr ni,
1840 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001841{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001842 if (node != NULL) {
1843 if (node->ns != NULL)
1844 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
1845 else
1846 return (xmlSchemaFormatQName(str, NULL, node->name));
1847 } else if (ni != NULL)
1848 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
1849 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001850}
1851
Daniel Veillardc0826a72004-08-10 14:17:33 +00001852static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001853xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
1854 xmlParserErrors error,
1855 xmlSchemaAttrInfoPtr ni,
1856 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001857{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001858 xmlChar *msg = NULL, *str = NULL;
1859
1860 xmlSchemaFormatNodeForError(&msg, actxt, node);
1861 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
1862 xmlSchemaErr(actxt, error, node, (const char *) msg,
1863 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
1864 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001865 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001866 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001867}
1868
Daniel Veillardc0826a72004-08-10 14:17:33 +00001869static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001870xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1871 xmlParserErrors error,
1872 xmlNodePtr node,
1873 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001874 const char *message,
1875 int nbval,
1876 int nbneg,
1877 xmlChar **values)
1878{
1879 xmlChar *str = NULL, *msg = NULL;
1880 xmlChar *localName, *nsName;
1881 const xmlChar *cur, *end;
Daniel Veillard77005e62005-07-19 16:26:18 +00001882 int i, is_not;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001883
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001884 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001885 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001886 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001887 /*
1888 * Note that is does not make sense to report that we have a
1889 * wildcard here, since the wildcard might be unfolded into
1890 * multiple transitions.
1891 */
1892 if (nbval + nbneg > 0) {
1893 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001894 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001895 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001896 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001897 nsName = NULL;
1898
1899 for (i = 0; i < nbval + nbneg; i++) {
1900 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00001901 if (cur == NULL)
1902 continue;
1903 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
1904 (cur[3] == ' ')) {
1905 is_not = 1;
1906 cur += 4;
1907 str = xmlStrcat(str, BAD_CAST "not ");
1908 } else {
1909 is_not = 0;
1910 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001911 /*
1912 * Get the local name.
1913 */
1914 localName = NULL;
1915
1916 end = cur;
1917 if (*end == '*') {
1918 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001919 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001920 } else {
1921 while ((*end != 0) && (*end != '|'))
1922 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001923 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001924 }
1925 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001926 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001927 /*
1928 * Skip "*|*" if they come with negated expressions, since
1929 * they represent the same negated wildcard.
1930 */
1931 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1932 /*
1933 * Get the namespace name.
1934 */
1935 cur = end;
1936 if (*end == '*') {
1937 nsName = xmlStrdup(BAD_CAST "{*}");
1938 } else {
1939 while (*end != 0)
1940 end++;
1941
1942 if (i >= nbval)
1943 nsName = xmlStrdup(BAD_CAST "{##other:");
1944 else
1945 nsName = xmlStrdup(BAD_CAST "{");
1946
1947 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1948 nsName = xmlStrcat(nsName, BAD_CAST "}");
1949 }
1950 str = xmlStrcat(str, BAD_CAST nsName);
1951 FREE_AND_NULL(nsName)
1952 } else {
1953 FREE_AND_NULL(localName);
1954 continue;
1955 }
1956 }
1957 str = xmlStrcat(str, BAD_CAST localName);
1958 FREE_AND_NULL(localName);
1959
1960 if (i < nbval + nbneg -1)
1961 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001962 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001963 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001964 msg = xmlStrcat(msg, BAD_CAST str);
1965 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001966 } else
1967 msg = xmlStrcat(msg, BAD_CAST "\n");
1968 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001969 xmlFree(msg);
1970}
1971
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001972static void
1973xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
1974 xmlParserErrors error,
1975 xmlNodePtr node,
1976 const xmlChar *value,
1977 unsigned long length,
1978 xmlSchemaTypePtr type,
1979 xmlSchemaFacetPtr facet,
1980 const char *message,
1981 const xmlChar *str1,
1982 const xmlChar *str2)
1983{
1984 xmlChar *str = NULL, *msg = NULL;
1985 xmlSchemaTypeType facetType;
1986 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
1987
1988 xmlSchemaFormatNodeForError(&msg, actxt, node);
1989 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1990 facetType = XML_SCHEMA_FACET_ENUMERATION;
1991 /*
1992 * If enumerations are validated, one must not expect the
1993 * facet to be given.
1994 */
1995 } else
1996 facetType = facet->type;
1997 msg = xmlStrcat(msg, BAD_CAST "[");
1998 msg = xmlStrcat(msg, BAD_CAST "facet '");
1999 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2000 msg = xmlStrcat(msg, BAD_CAST "'] ");
2001 if (message == NULL) {
2002 /*
2003 * Use a default message.
2004 */
2005 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2006 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2007 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2008
2009 char len[25], actLen[25];
2010
2011 /* FIXME, TODO: What is the max expected string length of the
2012 * this value?
2013 */
2014 if (nodeType == XML_ATTRIBUTE_NODE)
2015 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2016 else
2017 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2018
2019 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2020 snprintf(actLen, 24, "%lu", length);
2021
2022 if (facetType == XML_SCHEMA_FACET_LENGTH)
2023 msg = xmlStrcat(msg,
2024 BAD_CAST "this differs from the allowed length of '%s'.\n");
2025 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2026 msg = xmlStrcat(msg,
2027 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2028 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2029 msg = xmlStrcat(msg,
2030 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2031
2032 if (nodeType == XML_ATTRIBUTE_NODE)
2033 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2034 value, (const xmlChar *) actLen, (const xmlChar *) len);
2035 else
2036 xmlSchemaErr(actxt, error, node, (const char *) msg,
2037 (const xmlChar *) actLen, (const xmlChar *) len);
2038
2039 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2040 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2041 "of the set {%s}.\n");
2042 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2043 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2044 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2045 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2046 "by the pattern '%s'.\n");
2047 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2048 facet->value);
2049 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2050 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2051 "minimum value allowed ('%s').\n");
2052 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2053 facet->value);
2054 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2055 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2056 "maximum value allowed ('%s').\n");
2057 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2058 facet->value);
2059 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2060 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2061 "'%s'.\n");
2062 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2063 facet->value);
2064 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2065 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2066 "'%s'.\n");
2067 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2068 facet->value);
2069 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2070 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2071 "digits than are allowed ('%s').\n");
2072 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2073 facet->value);
2074 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2075 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2076 "digits than are allowed ('%s').\n");
2077 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2078 facet->value);
2079 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2080 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2081 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2082 } else {
2083 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2084 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2085 }
2086 } else {
2087 msg = xmlStrcat(msg, (const xmlChar *) message);
2088 msg = xmlStrcat(msg, BAD_CAST ".\n");
2089 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2090 }
2091 FREE_AND_NULL(str)
2092 xmlFree(msg);
2093}
2094
2095#define VERROR(err, type, msg) \
2096 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
2097
2098#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
2099
2100#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
2101
2102#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2103
2104
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002105/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002106 * xmlSchemaPMissingAttrErr:
2107 * @ctxt: the schema validation context
2108 * @ownerDes: the designation of the owner
2109 * @ownerName: the name of the owner
2110 * @ownerItem: the owner as a schema object
2111 * @ownerElem: the owner as an element node
2112 * @node: the parent element node of the missing attribute node
2113 * @type: the corresponding type of the attribute node
2114 *
2115 * Reports an illegal attribute.
2116 */
2117static void
2118xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002119 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002120 xmlSchemaTypePtr ownerItem,
2121 xmlNodePtr ownerElem,
2122 const char *name,
2123 const char *message)
2124{
2125 xmlChar *des = NULL;
2126
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002127 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2128
Daniel Veillardc0826a72004-08-10 14:17:33 +00002129 if (message != NULL)
2130 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002131 else
2132 xmlSchemaPErr(ctxt, ownerElem, error,
2133 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002134 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002135 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002136}
2137
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002138
Daniel Veillardc0826a72004-08-10 14:17:33 +00002139/**
2140 * xmlSchemaPResCompAttrErr:
2141 * @ctxt: the schema validation context
2142 * @error: the error code
2143 * @ownerDes: the designation of the owner
2144 * @ownerItem: the owner as a schema object
2145 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002146 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002147 * @refName: the referenced local name
2148 * @refURI: the referenced namespace URI
2149 * @message: optional message
2150 *
2151 * Used to report QName attribute values that failed to resolve
2152 * to schema components.
2153 */
2154static void
2155xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002156 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002157 xmlSchemaTypePtr ownerItem,
2158 xmlNodePtr ownerElem,
2159 const char *name,
2160 const xmlChar *refName,
2161 const xmlChar *refURI,
2162 xmlSchemaTypeType refType,
2163 const char *refTypeStr)
2164{
2165 xmlChar *des = NULL, *strA = NULL;
2166
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002167 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002168 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002169 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2170 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002171 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002172 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2173 "%s.\n", BAD_CAST des, BAD_CAST name,
2174 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002175 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002176 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002177 FREE_AND_NULL(strA)
2178}
2179
William M. Brack2f2a6632004-08-20 23:09:47 +00002180/**
2181 * xmlSchemaPCustomAttrErr:
2182 * @ctxt: the schema parser context
2183 * @error: the error code
2184 * @ownerDes: the designation of the owner
2185 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002186 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002187 *
2188 * Reports an illegal attribute during the parse.
2189 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002190static void
2191xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002192 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002193 xmlChar **ownerDes,
2194 xmlSchemaTypePtr ownerItem,
2195 xmlAttrPtr attr,
2196 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002197{
2198 xmlChar *des = NULL;
2199
2200 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002201 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002202 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002203 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002204 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002205 } else
2206 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002207 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002208 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002209 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2210 if (ownerDes == NULL)
2211 FREE_AND_NULL(des);
2212}
2213
2214/**
2215 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002216 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002217 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002218 * @ownerDes: the designation of the attribute's owner
2219 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002220 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002221 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002222 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002223 */
2224static void
2225xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002226 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002227 xmlChar **ownerDes,
2228 xmlSchemaTypePtr ownerItem,
2229 xmlAttrPtr attr)
2230{
2231 xmlChar *des = NULL, *strA = NULL;
2232
2233 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002234 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002235 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002236 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002237 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002238 } else
2239 des = *ownerDes;
2240 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2241 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2242 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002243 if (ownerDes == NULL)
2244 FREE_AND_NULL(des);
2245 FREE_AND_NULL(strA);
2246}
2247
William M. Brack2f2a6632004-08-20 23:09:47 +00002248/**
2249 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002250 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002251 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002252 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002253 * @itemElem: the node of the schema item
2254 *
2255 * Creates a designation for an item.
2256 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002257static void
2258xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002259 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002260 xmlSchemaTypePtr item,
2261 xmlNodePtr itemElem)
2262{
2263 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002264 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002265 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002266 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002267 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002268 } else
2269 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002270}
2271
William M. Brack2f2a6632004-08-20 23:09:47 +00002272/**
2273 * xmlSchemaPCustomErr:
2274 * @ctxt: the schema parser context
2275 * @error: the error code
2276 * @itemDes: the designation of the schema item
2277 * @item: the schema item
2278 * @itemElem: the node of the schema item
2279 * @message: the error message
2280 * @str1: an optional param for the error message
2281 * @str2: an optional param for the error message
2282 * @str3: an optional param for the error message
2283 *
2284 * Reports an error during parsing.
2285 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002286static void
2287xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002288 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002289 xmlChar **itemDes,
2290 xmlSchemaTypePtr item,
2291 xmlNodePtr itemElem,
2292 const char *message,
2293 const xmlChar *str1,
2294 const xmlChar *str2,
2295 const xmlChar *str3)
2296{
2297 xmlChar *des = NULL, *msg = NULL;
2298
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002299 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002300 msg = xmlStrdup(BAD_CAST "%s: ");
2301 msg = xmlStrcat(msg, (const xmlChar *) message);
2302 msg = xmlStrcat(msg, BAD_CAST ".\n");
2303 if ((itemElem == NULL) && (item != NULL))
2304 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002305 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002306 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2307 if (itemDes == NULL)
2308 FREE_AND_NULL(des);
2309 FREE_AND_NULL(msg);
2310}
2311
William M. Brack2f2a6632004-08-20 23:09:47 +00002312/**
2313 * xmlSchemaPCustomErr:
2314 * @ctxt: the schema parser context
2315 * @error: the error code
2316 * @itemDes: the designation of the schema item
2317 * @item: the schema item
2318 * @itemElem: the node of the schema item
2319 * @message: the error message
2320 * @str1: the optional param for the error message
2321 *
2322 * Reports an error during parsing.
2323 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002324static void
2325xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002326 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002327 xmlChar **itemDes,
2328 xmlSchemaTypePtr item,
2329 xmlNodePtr itemElem,
2330 const char *message,
2331 const xmlChar *str1)
2332{
2333 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2334 str1, NULL, NULL);
2335}
2336
William M. Brack2f2a6632004-08-20 23:09:47 +00002337/**
2338 * xmlSchemaPAttrUseErr:
2339 * @ctxt: the schema parser context
2340 * @error: the error code
2341 * @itemDes: the designation of the schema type
2342 * @item: the schema type
2343 * @itemElem: the node of the schema type
2344 * @attr: the invalid schema attribute
2345 * @message: the error message
2346 * @str1: the optional param for the error message
2347 *
2348 * Reports an attribute use error during parsing.
2349 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002350static void
2351xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002352 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002353 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002354 const xmlSchemaAttributePtr attr,
2355 const char *message,
2356 const xmlChar *str1)
2357{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002358 xmlChar *str = NULL, *msg = NULL;
2359 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2360 msg = xmlStrcat(msg, BAD_CAST ", ");
2361 msg = xmlStrcat(msg,
2362 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2363 (xmlSchemaTypePtr) attr, NULL));
2364 FREE_AND_NULL(str);
2365 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002366 msg = xmlStrcat(msg, (const xmlChar *) message);
2367 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002368 xmlSchemaPErr(ctxt, attr->node, error,
2369 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002370 xmlFree(msg);
2371}
2372
William M. Brack2f2a6632004-08-20 23:09:47 +00002373/**
2374 * xmlSchemaPIllegalFacetAtomicErr:
2375 * @ctxt: the schema parser context
2376 * @error: the error code
2377 * @itemDes: the designation of the type
2378 * @item: the schema type
2379 * @baseItem: the base type of type
2380 * @facet: the illegal facet
2381 *
2382 * Reports an illegal facet for atomic simple types.
2383 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002384static void
2385xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002386 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002387 xmlChar **itemDes,
2388 xmlSchemaTypePtr item,
2389 xmlSchemaTypePtr baseItem,
2390 xmlSchemaFacetPtr facet)
2391{
2392 xmlChar *des = NULL, *strT = NULL;
2393
2394 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2395 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2396 "%s: The facet '%s' is not allowed on types derived from the "
2397 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002398 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002399 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002400 NULL, NULL);
2401 if (itemDes == NULL)
2402 FREE_AND_NULL(des);
2403 FREE_AND_NULL(strT);
2404}
2405
William M. Brack2f2a6632004-08-20 23:09:47 +00002406/**
2407 * xmlSchemaPIllegalFacetListUnionErr:
2408 * @ctxt: the schema parser context
2409 * @error: the error code
2410 * @itemDes: the designation of the schema item involved
2411 * @item: the schema item involved
2412 * @facet: the illegal facet
2413 *
2414 * Reports an illegal facet for <list> and <union>.
2415 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002416static void
2417xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002418 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002419 xmlChar **itemDes,
2420 xmlSchemaTypePtr item,
2421 xmlSchemaFacetPtr facet)
2422{
2423 xmlChar *des = NULL, *strT = NULL;
2424
2425 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002426 xmlSchemaPErr(ctxt, item->node, error,
2427 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002428 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002429 if (itemDes == NULL)
2430 FREE_AND_NULL(des);
2431 FREE_AND_NULL(strT);
2432}
2433
2434/**
2435 * xmlSchemaPMutualExclAttrErr:
2436 * @ctxt: the schema validation context
2437 * @error: the error code
2438 * @elemDes: the designation of the parent element node
2439 * @attr: the bad attribute node
2440 * @type: the corresponding type of the attribute node
2441 *
2442 * Reports an illegal attribute.
2443 */
2444static void
2445xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2446 xmlParserErrors error,
2447 xmlChar **ownerDes,
2448 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002449 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002450 const char *name1,
2451 const char *name2)
2452{
2453 xmlChar *des = NULL;
2454
2455 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002456 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002457 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002458 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002459 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002460 } else
2461 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002462 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002463 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002464 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2465 if (ownerDes == NULL)
2466 FREE_AND_NULL(des)
2467}
2468
2469/**
2470 * xmlSchemaPSimpleTypeErr:
2471 * @ctxt: the schema validation context
2472 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002473 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002474 * @ownerDes: the designation of the owner
2475 * @ownerItem: the schema object if existent
2476 * @node: the validated node
2477 * @value: the validated value
2478 *
2479 * Reports a simple type validation error.
2480 * TODO: Should this report the value of an element as well?
2481 */
2482static void
2483xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2484 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002485 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002486 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002487 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002488 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002489 const xmlChar *value,
2490 const char *message,
2491 const xmlChar *str1,
2492 const xmlChar *str2)
2493{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002494 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002495
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002496 xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002497 if (message == NULL) {
2498 /*
2499 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002500 */
2501 if (type != NULL) {
2502 if (node->type == XML_ATTRIBUTE_NODE)
2503 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2504 else
2505 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2506 "valid value of ");
2507 if (! xmlSchemaIsGlobalItem(type))
2508 msg = xmlStrcat(msg, BAD_CAST "the local ");
2509 else
2510 msg = xmlStrcat(msg, BAD_CAST "the ");
2511
2512 if (VARIETY_ATOMIC(type))
2513 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2514 else if (VARIETY_LIST(type))
2515 msg = xmlStrcat(msg, BAD_CAST "list type");
2516 else if (VARIETY_UNION(type))
2517 msg = xmlStrcat(msg, BAD_CAST "union type");
2518
2519 if (xmlSchemaIsGlobalItem(type)) {
2520 xmlChar *str = NULL;
2521 msg = xmlStrcat(msg, BAD_CAST " '");
2522 if (type->builtInType != 0) {
2523 msg = xmlStrcat(msg, BAD_CAST "xs:");
2524 msg = xmlStrcat(msg, type->name);
2525 } else
2526 msg = xmlStrcat(msg,
2527 xmlSchemaFormatQName(&str,
2528 type->targetNamespace, type->name));
2529 msg = xmlStrcat(msg, BAD_CAST "'.");
2530 FREE_AND_NULL(str);
2531 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002532 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002533 if (node->type == XML_ATTRIBUTE_NODE)
2534 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2535 else
2536 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2537 "valid.");
2538 }
2539 if (expected) {
2540 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2541 msg = xmlStrcat(msg, BAD_CAST expected);
2542 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2543 } else
2544 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002545 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002546 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2547 else
2548 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2549 } else {
2550 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2551 "%s%s.\n", msg, BAD_CAST message, str1, str2, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002552 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002553 /* Cleanup. */
2554 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002555}
2556
William M. Brack2f2a6632004-08-20 23:09:47 +00002557/**
2558 * xmlSchemaPContentErr:
2559 * @ctxt: the schema parser context
2560 * @error: the error code
2561 * @onwerDes: the designation of the holder of the content
2562 * @ownerItem: the owner item of the holder of the content
2563 * @ownerElem: the node of the holder of the content
2564 * @child: the invalid child node
2565 * @message: the optional error message
2566 * @content: the optional string describing the correct content
2567 *
2568 * Reports an error concerning the content of a schema element.
2569 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002570static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002571xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002572 xmlParserErrors error,
2573 xmlChar **ownerDes,
2574 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002575 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002576 xmlNodePtr child,
2577 const char *message,
2578 const char *content)
2579{
2580 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002581
Daniel Veillardc0826a72004-08-10 14:17:33 +00002582 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002583 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002584 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002585 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002586 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002587 } else
2588 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002589 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002590 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2591 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002592 BAD_CAST des, BAD_CAST message);
2593 else {
2594 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002595 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2596 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002597 BAD_CAST des, BAD_CAST content);
2598 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002599 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2600 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002601 BAD_CAST des, NULL);
2602 }
2603 }
2604 if (ownerDes == NULL)
2605 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002606}
2607
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002608/************************************************************************
2609 * *
2610 * Streamable error functions *
2611 * *
2612 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002613
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002614
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002615
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002616
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002617/************************************************************************
2618 * *
2619 * Validation helper functions *
2620 * *
2621 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002622
Daniel Veillardc0826a72004-08-10 14:17:33 +00002623
Daniel Veillard4255d502002-04-16 15:50:10 +00002624/************************************************************************
2625 * *
2626 * Allocation functions *
2627 * *
2628 ************************************************************************/
2629
2630/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002631 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002632 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002633 *
2634 * Allocate a new Schema structure.
2635 *
2636 * Returns the newly allocated structure or NULL in case or error
2637 */
2638static xmlSchemaPtr
2639xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2640{
2641 xmlSchemaPtr ret;
2642
2643 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2644 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002645 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002646 return (NULL);
2647 }
2648 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002649 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002650 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002651
2652 return (ret);
2653}
2654
2655/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002656 * xmlSchemaNewSchema:
2657 * @ctxt: a schema validation context
2658 *
2659 * Allocate a new Schema structure.
2660 *
2661 * Returns the newly allocated structure or NULL in case or error
2662 */
2663static xmlSchemaAssemblePtr
2664xmlSchemaNewAssemble(void)
2665{
2666 xmlSchemaAssemblePtr ret;
2667
2668 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2669 if (ret == NULL) {
2670 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2671 return (NULL);
2672 }
2673 memset(ret, 0, sizeof(xmlSchemaAssemble));
2674 ret->items = NULL;
2675 return (ret);
2676}
2677
2678/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002679 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002680 *
2681 * Allocate a new Facet structure.
2682 *
2683 * Returns the newly allocated structure or NULL in case or error
2684 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002685xmlSchemaFacetPtr
2686xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002687{
2688 xmlSchemaFacetPtr ret;
2689
2690 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2691 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002692 return (NULL);
2693 }
2694 memset(ret, 0, sizeof(xmlSchemaFacet));
2695
2696 return (ret);
2697}
2698
2699/**
2700 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002701 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002702 * @node: a node
2703 *
2704 * Allocate a new annotation structure.
2705 *
2706 * Returns the newly allocated structure or NULL in case or error
2707 */
2708static xmlSchemaAnnotPtr
2709xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2710{
2711 xmlSchemaAnnotPtr ret;
2712
2713 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2714 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002715 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002716 return (NULL);
2717 }
2718 memset(ret, 0, sizeof(xmlSchemaAnnot));
2719 ret->content = node;
2720 return (ret);
2721}
2722
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002723static xmlSchemaItemListPtr
2724xmlSchemaNewItemList(void)
2725{
2726 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002727
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002728 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2729 if (ret == NULL) {
2730 xmlSchemaPErrMemory(NULL,
2731 "allocating an item list structure", NULL);
2732 return (NULL);
2733 }
2734 memset(ret, 0, sizeof(xmlSchemaItemList));
2735 return (ret);
2736}
2737
2738/**
2739 * xmlSchemaAddElementSubstitutionMember:
2740 * @pctxt: a schema parser context
2741 * @head: the head of the substitution group
2742 * @member: the new member of the substitution group
2743 *
2744 * Allocate a new annotation structure.
2745 *
2746 * Returns the newly allocated structure or NULL in case or error
2747 */
2748static int
2749xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2750 xmlSchemaElementPtr head,
2751 xmlSchemaElementPtr member)
2752{
2753 xmlSchemaSubstGroupPtr substGroup;
2754
2755 if (pctxt == NULL)
2756 return (-1);
2757
2758 if (pctxt->substGroups == NULL) {
2759 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2760 if (pctxt->substGroups == NULL)
2761 return (-1);
2762 }
2763 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2764 head->targetNamespace);
2765 if (substGroup == NULL) {
2766 int res;
2767
2768 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2769 if (substGroup == NULL) {
2770 xmlSchemaPErrMemory(NULL,
2771 "xmlSchemaAddElementSubstitution, allocating a substitution "
2772 "group container",
2773 NULL);
2774 return (-1);
2775 }
2776 substGroup->members = xmlSchemaNewItemList();
2777 if (substGroup->members == NULL) {
2778 xmlFree(substGroup);
2779 return (-1);
2780 }
2781 substGroup->head = head;
2782
2783 res = xmlHashAddEntry2(pctxt->substGroups,
2784 head->name, head->targetNamespace, substGroup);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002785 if (res != 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002786 xmlFree(substGroup->members);
2787 xmlFree(substGroup);
2788 xmlSchemaPErr(pctxt, member->node,
2789 XML_SCHEMAP_INTERNAL,
2790 "Internal error: xmlSchemaAddElementSubstitution, "
2791 "failed to add a new substitution group container for "
2792 "'%s'.\n", head->name, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002793 return (-1);
2794 }
2795 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002796 if (substGroup->members->items == NULL) {
2797 substGroup->members->items = (void **) xmlMalloc(
2798 5 * sizeof(xmlSchemaElementPtr));
2799 if (substGroup->members->items == NULL) {
2800 xmlSchemaPErrMemory(NULL,
2801 "allocating list of substitution group members", NULL);
2802 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002803 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002804 substGroup->members->sizeItems = 5;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002805 } else if (substGroup->members->sizeItems <=
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002806 substGroup->members->nbItems) {
2807 substGroup->members->sizeItems *= 2;
2808 substGroup->members->items = (void **) xmlRealloc(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002809 substGroup->members->items,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002810 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2811 if (substGroup->members->items == NULL) {
2812 xmlSchemaPErrMemory(NULL,
2813 "re-allocating list of substitution group members", NULL);
2814 substGroup->members->sizeItems = 0;
2815 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002816 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002817 }
2818 ((xmlSchemaElementPtr *) substGroup->members->items)
2819 [substGroup->members->nbItems++] = (void *) member;
2820 return (0);
2821}
2822
2823/**
2824 * xmlSchemaGetElementSubstitutionGroup:
2825 * @pctxt: a schema parser context
2826 * @head: the head of the substitution group
2827 * @member: the new member of the substitution group
2828 *
2829 * Allocate a new annotation structure.
2830 *
2831 * Returns the newly allocated structure or NULL in case or error
2832 */
2833static xmlSchemaSubstGroupPtr
2834xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2835 xmlSchemaElementPtr head)
2836{
2837 if (pctxt == NULL)
2838 return (NULL);
2839
2840 if (pctxt->substGroups == NULL)
2841 return (NULL);
2842
2843 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2844 head->name, head->targetNamespace));
2845}
2846
2847/**
2848 * xmlSchemaFreeItemList:
2849 * @annot: a schema type structure
2850 *
2851 * Deallocate a annotation structure
2852 */
2853static void
2854xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2855{
2856 if (list == NULL)
2857 return;
2858 if (list->items != NULL)
2859 xmlFree(list->items);
2860 xmlFree(list);
2861}
2862
Daniel Veillard4255d502002-04-16 15:50:10 +00002863/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002864 * xmlSchemaFreeAnnot:
2865 * @annot: a schema type structure
2866 *
2867 * Deallocate a annotation structure
2868 */
2869static void
2870xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2871{
2872 if (annot == NULL)
2873 return;
2874 xmlFree(annot);
2875}
2876
2877/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002878 * xmlSchemaFreeImport:
2879 * @import: a schema import structure
2880 *
2881 * Deallocate an import structure
2882 */
2883static void
2884xmlSchemaFreeImport(xmlSchemaImportPtr import)
2885{
2886 if (import == NULL)
2887 return;
2888
2889 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002890 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002891 xmlFree(import);
2892}
2893
2894/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002895 * xmlSchemaFreeInclude:
2896 * @include: a schema include structure
2897 *
2898 * Deallocate an include structure
2899 */
2900static void
2901xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2902{
2903 if (include == NULL)
2904 return;
2905
2906 xmlFreeDoc(include->doc);
2907 xmlFree(include);
2908}
2909
2910/**
2911 * xmlSchemaFreeIncludeList:
2912 * @includes: a schema include list
2913 *
2914 * Deallocate an include structure
2915 */
2916static void
2917xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2918{
2919 xmlSchemaIncludePtr next;
2920
2921 while (includes != NULL) {
2922 next = includes->next;
2923 xmlSchemaFreeInclude(includes);
2924 includes = next;
2925 }
2926}
2927
2928/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002929 * xmlSchemaFreeNotation:
2930 * @schema: a schema notation structure
2931 *
2932 * Deallocate a Schema Notation structure.
2933 */
2934static void
2935xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2936{
2937 if (nota == NULL)
2938 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002939 xmlFree(nota);
2940}
2941
2942/**
2943 * xmlSchemaFreeAttribute:
2944 * @schema: a schema attribute structure
2945 *
2946 * Deallocate a Schema Attribute structure.
2947 */
2948static void
2949xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2950{
2951 if (attr == NULL)
2952 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002953 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002954 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002955 if (attr->defVal != NULL)
2956 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002957 xmlFree(attr);
2958}
2959
2960/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002961 * xmlSchemaFreeWildcardNsSet:
2962 * set: a schema wildcard namespace
2963 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002964 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002965 */
2966static void
2967xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2968{
2969 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002970
Daniel Veillard3646d642004-06-02 19:19:14 +00002971 while (set != NULL) {
2972 next = set->next;
2973 xmlFree(set);
2974 set = next;
2975 }
2976}
2977
2978/**
2979 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002980 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002981 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002982 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002983 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002984void
Daniel Veillard3646d642004-06-02 19:19:14 +00002985xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2986{
2987 if (wildcard == NULL)
2988 return;
2989 if (wildcard->annot != NULL)
2990 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002991 if (wildcard->nsSet != NULL)
2992 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2993 if (wildcard->negNsSet != NULL)
2994 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00002995 xmlFree(wildcard);
2996}
2997
2998/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002999 * xmlSchemaFreeAttributeGroup:
3000 * @schema: a schema attribute group structure
3001 *
3002 * Deallocate a Schema Attribute Group structure.
3003 */
3004static void
3005xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
3006{
3007 if (attr == NULL)
3008 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00003009 if (attr->annot != NULL)
3010 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003011 xmlFree(attr);
3012}
3013
3014/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003015 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003016 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00003017 *
3018 * Deallocate a list of schema attribute uses.
3019 */
3020static void
3021xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3022{
3023 xmlSchemaAttributeLinkPtr next;
3024
3025 while (attrUse != NULL) {
3026 next = attrUse->next;
3027 xmlFree(attrUse);
3028 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003029 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003030}
3031
3032/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003033 * xmlSchemaFreeQNameRef:
3034 * @item: a QName reference structure
3035 *
3036 * Deallocatea a QName reference structure.
3037 */
3038static void
3039xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3040{
3041 xmlFree(item);
3042}
3043
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003044/**
3045 * xmlSchemaFreeQNameRef:
3046 * @item: a QName reference structure
3047 *
3048 * Deallocatea a QName reference structure.
3049 */
3050static void
3051xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3052{
3053 if (item == NULL)
3054 return;
3055 if (item->members != NULL)
3056 xmlSchemaFreeItemList(item->members);
3057 xmlFree(item);
3058}
3059
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003060static int
3061xmlSchemaAddVolatile(xmlSchemaPtr schema,
3062 xmlSchemaBasicItemPtr item)
3063{
3064 xmlSchemaItemListPtr list;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003065
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003066 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003067 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003068 if (schema->volatiles == NULL) {
3069 xmlSchemaPErrMemory(NULL,
3070 "allocating list of volatiles", NULL);
3071 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003072 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003073 }
3074 list = (xmlSchemaItemListPtr) schema->volatiles;
3075 if (list->items == NULL) {
3076 list->items = (void **) xmlMalloc(
3077 20 * sizeof(xmlSchemaBasicItemPtr));
3078 if (list->items == NULL) {
3079 xmlSchemaPErrMemory(NULL,
3080 "allocating new volatile item buffer", NULL);
3081 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003082 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003083 list->sizeItems = 20;
3084 } else if (list->sizeItems <= list->nbItems) {
3085 list->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003086 list->items = (void **) xmlRealloc(list->items,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003087 list->sizeItems * sizeof(xmlSchemaTypePtr));
3088 if (list->items == NULL) {
3089 xmlSchemaPErrMemory(NULL,
3090 "growing volatile item buffer", NULL);
3091 list->sizeItems = 0;
3092 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003093 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003094 }
3095 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3096 return (0);
3097}
3098
3099/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003100 * xmlSchemaFreeTypeLinkList:
3101 * @alink: a type link
3102 *
3103 * Deallocate a list of types.
3104 */
3105static void
3106xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3107{
3108 xmlSchemaTypeLinkPtr next;
3109
3110 while (link != NULL) {
3111 next = link->next;
3112 xmlFree(link);
3113 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003114 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003115}
3116
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003117static void
3118xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3119{
3120 xmlSchemaIDCStateObjPtr next;
3121 while (sto != NULL) {
3122 next = sto->next;
3123 if (sto->history != NULL)
3124 xmlFree(sto->history);
3125 if (sto->xpathCtxt != NULL)
3126 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3127 xmlFree(sto);
3128 sto = next;
3129 }
3130}
3131
3132/**
3133 * xmlSchemaFreeIDC:
3134 * @idc: a identity-constraint definition
3135 *
3136 * Deallocates an identity-constraint definition.
3137 */
3138static void
3139xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3140{
3141 xmlSchemaIDCSelectPtr cur, prev;
3142
3143 if (idcDef == NULL)
3144 return;
3145 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003146 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003147 /* Selector */
3148 if (idcDef->selector != NULL) {
3149 if (idcDef->selector->xpathComp != NULL)
3150 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3151 xmlFree(idcDef->selector);
3152 }
3153 /* Fields */
3154 if (idcDef->fields != NULL) {
3155 cur = idcDef->fields;
3156 do {
3157 prev = cur;
3158 cur = cur->next;
3159 if (prev->xpathComp != NULL)
3160 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003161 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003162 } while (cur != NULL);
3163 }
3164 xmlFree(idcDef);
3165}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003166
Daniel Veillard01fa6152004-06-29 17:04:39 +00003167/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003168 * xmlSchemaFreeElement:
3169 * @schema: a schema element structure
3170 *
3171 * Deallocate a Schema Element structure.
3172 */
3173static void
3174xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3175{
3176 if (elem == NULL)
3177 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003178 if (elem->annot != NULL)
3179 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003180 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003181 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003182 if (elem->defVal != NULL)
3183 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003184 xmlFree(elem);
3185}
3186
3187/**
3188 * xmlSchemaFreeFacet:
3189 * @facet: a schema facet structure
3190 *
3191 * Deallocate a Schema Facet structure.
3192 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003193void
Daniel Veillard4255d502002-04-16 15:50:10 +00003194xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3195{
3196 if (facet == NULL)
3197 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003198 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003199 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003200 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003201 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003202 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003203 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003204 xmlFree(facet);
3205}
3206
3207/**
3208 * xmlSchemaFreeType:
3209 * @type: a schema type structure
3210 *
3211 * Deallocate a Schema Type structure.
3212 */
3213void
3214xmlSchemaFreeType(xmlSchemaTypePtr type)
3215{
3216 if (type == NULL)
3217 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003218 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003219 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003220 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003221 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003222
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003223 facet = type->facets;
3224 while (facet != NULL) {
3225 next = facet->next;
3226 xmlSchemaFreeFacet(facet);
3227 facet = next;
3228 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003229 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003230 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3231 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003232 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003233 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003234 if (type->memberTypes != NULL)
3235 xmlSchemaFreeTypeLinkList(type->memberTypes);
3236 if (type->facetSet != NULL) {
3237 xmlSchemaFacetLinkPtr next, link;
3238
3239 link = type->facetSet;
3240 do {
3241 next = link->next;
3242 xmlFree(link);
3243 link = next;
3244 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003245 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003246 if (type->contModel != NULL)
3247 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003248 xmlFree(type);
3249}
3250
3251/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003252 * xmlSchemaFreeModelGroupDef:
3253 * @item: a schema model group definition
3254 *
3255 * Deallocates a schema model group definition.
3256 */
3257static void
3258xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3259{
3260 if (item->annot != NULL)
3261 xmlSchemaFreeAnnot(item->annot);
3262 xmlFree(item);
3263}
3264
3265/**
3266 * xmlSchemaFreeModelGroup:
3267 * @item: a schema model group
3268 *
3269 * Deallocates a schema model group structure.
3270 */
3271static void
3272xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3273{
3274 if (item->annot != NULL)
3275 xmlSchemaFreeAnnot(item->annot);
3276 xmlFree(item);
3277}
3278
3279/**
3280 * xmlSchemaFreeParticle:
3281 * @type: a schema type structure
3282 *
3283 * Deallocate a Schema Type structure.
3284 */
3285static void
3286xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3287{
3288 if (item->annot != NULL)
3289 xmlSchemaFreeAnnot(item->annot);
3290 xmlFree(item);
3291}
3292
3293/**
3294 * xmlSchemaFreeMiscComponents:
3295 * @item: a schema component
3296 *
3297 * Deallocates misc. schema component structures.
3298 */
3299static void
3300xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3301{
3302 if (item == NULL)
3303 return;
3304 switch (item->type) {
3305 case XML_SCHEMA_TYPE_PARTICLE:
3306 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3307 return;
3308 case XML_SCHEMA_TYPE_SEQUENCE:
3309 case XML_SCHEMA_TYPE_CHOICE:
3310 case XML_SCHEMA_TYPE_ALL:
3311 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3312 return;
3313 case XML_SCHEMA_TYPE_ANY:
3314 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3315 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3316 break;
3317 default:
3318 /* TODO: This should never be hit. */
3319 TODO
3320 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003321 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003322}
3323
3324static void
3325xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3326{
3327 if (schema->volatiles == NULL)
3328 return;
3329 {
3330 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3331 xmlSchemaTreeItemPtr item;
3332 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003333
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003334 for (i = 0; i < list->nbItems; i++) {
3335 if (list->items[i] != NULL) {
3336 item = (xmlSchemaTreeItemPtr) list->items[i];
3337 switch (item->type) {
3338 case XML_SCHEMA_EXTRA_QNAMEREF:
3339 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3340 break;
3341 default:
3342 xmlSchemaFreeMiscComponents(item);
3343 }
3344 }
3345 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003346 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003347 }
3348}
3349/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003350 * xmlSchemaFreeTypeList:
3351 * @type: a schema type structure
3352 *
3353 * Deallocate a Schema Type structure.
3354 */
3355static void
3356xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3357{
3358 xmlSchemaTypePtr next;
3359
3360 while (type != NULL) {
3361 next = type->redef;
3362 xmlSchemaFreeType(type);
3363 type = next;
3364 }
3365}
3366
3367/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003368 * xmlSchemaFree:
3369 * @schema: a schema structure
3370 *
3371 * Deallocate a Schema structure.
3372 */
3373void
3374xmlSchemaFree(xmlSchemaPtr schema)
3375{
3376 if (schema == NULL)
3377 return;
3378
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003379 if (schema->volatiles != NULL)
3380 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003381 if (schema->notaDecl != NULL)
3382 xmlHashFree(schema->notaDecl,
3383 (xmlHashDeallocator) xmlSchemaFreeNotation);
3384 if (schema->attrDecl != NULL)
3385 xmlHashFree(schema->attrDecl,
3386 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3387 if (schema->attrgrpDecl != NULL)
3388 xmlHashFree(schema->attrgrpDecl,
3389 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3390 if (schema->elemDecl != NULL)
3391 xmlHashFree(schema->elemDecl,
3392 (xmlHashDeallocator) xmlSchemaFreeElement);
3393 if (schema->typeDecl != NULL)
3394 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003395 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003396 if (schema->groupDecl != NULL)
3397 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003398 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003399 if (schema->idcDef != NULL)
3400 xmlHashFree(schema->idcDef,
3401 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003402 if (schema->schemasImports != NULL)
3403 xmlHashFree(schema->schemasImports,
3404 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003405 if (schema->includes != NULL) {
3406 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3407 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003408 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003409 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003410 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003411 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003412 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003413 xmlFree(schema);
3414}
3415
3416/************************************************************************
3417 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003418 * Debug functions *
3419 * *
3420 ************************************************************************/
3421
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003422#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003423
Daniel Veillard4255d502002-04-16 15:50:10 +00003424/**
3425 * xmlSchemaElementDump:
3426 * @elem: an element
3427 * @output: the file output
3428 *
3429 * Dump the element
3430 */
3431static void
3432xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003433 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003434 const xmlChar * namespace ATTRIBUTE_UNUSED,
3435 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003436{
3437 if (elem == NULL)
3438 return;
3439
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003440 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3441 fprintf(output, "Particle: %s", name);
3442 fprintf(output, ", term element: %s", elem->ref);
3443 if (elem->refNs != NULL)
3444 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003445 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003446 fprintf(output, "Element");
3447 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3448 fprintf(output, " (global)");
3449 fprintf(output, ": %s ", elem->name);
3450 if (namespace != NULL)
3451 fprintf(output, "ns %s", namespace);
3452 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003453 fprintf(output, "\n");
3454 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003455 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003456 if (elem->maxOccurs >= UNBOUNDED)
3457 fprintf(output, "max: unbounded\n");
3458 else if (elem->maxOccurs != 1)
3459 fprintf(output, "max: %d\n", elem->maxOccurs);
3460 else
3461 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003462 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003463 /*
3464 * Misc other properties.
3465 */
3466 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3467 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3468 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3469 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3470 (elem->id != NULL)) {
3471 fprintf(output, " props: ");
3472 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3473 fprintf(output, "[fixed] ");
3474 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3475 fprintf(output, "[default] ");
3476 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3477 fprintf(output, "[abstract] ");
3478 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3479 fprintf(output, "[nillable] ");
3480 if (elem->id != NULL)
3481 fprintf(output, "[id: '%s'] ", elem->id);
3482 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003483 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003484 /*
3485 * Default/fixed value.
3486 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003487 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003488 fprintf(output, " value: '%s'\n", elem->value);
3489 /*
3490 * Type.
3491 */
3492 if (elem->namedType != NULL) {
3493 fprintf(output, " type: %s ", elem->namedType);
3494 if (elem->namedTypeNs != NULL)
3495 fprintf(output, "ns %s\n", elem->namedTypeNs);
3496 else
3497 fprintf(output, "\n");
3498 }
3499 /*
3500 * Substitution group.
3501 */
3502 if (elem->substGroup != NULL) {
3503 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3504 if (elem->substGroupNs != NULL)
3505 fprintf(output, "ns %s\n", elem->substGroupNs);
3506 else
3507 fprintf(output, "\n");
3508 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003509}
3510
3511/**
3512 * xmlSchemaAnnotDump:
3513 * @output: the file output
3514 * @annot: a annotation
3515 *
3516 * Dump the annotation
3517 */
3518static void
3519xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3520{
3521 xmlChar *content;
3522
3523 if (annot == NULL)
3524 return;
3525
3526 content = xmlNodeGetContent(annot->content);
3527 if (content != NULL) {
3528 fprintf(output, " Annot: %s\n", content);
3529 xmlFree(content);
3530 } else
3531 fprintf(output, " Annot: empty\n");
3532}
3533
3534/**
3535 * xmlSchemaTypeDump:
3536 * @output: the file output
3537 * @type: a type structure
3538 *
3539 * Dump a SchemaType structure
3540 */
3541static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003542xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3543{
3544 xmlChar *str = NULL;
3545 xmlSchemaTreeItemPtr term;
3546 char shift[100];
3547 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003548
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003549 if (particle == NULL)
3550 return;
3551 for (i = 0;((i < depth) && (i < 25));i++)
3552 shift[2 * i] = shift[2 * i + 1] = ' ';
3553 shift[2 * i] = shift[2 * i + 1] = 0;
3554 fprintf(output, shift);
3555 if (particle->children == NULL) {
3556 fprintf(output, "MISSING particle term\n");
3557 return;
3558 }
3559 term = particle->children;
3560 switch (term->type) {
3561 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003562 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003563 ((xmlSchemaElementPtr)term)->targetNamespace,
3564 ((xmlSchemaElementPtr)term)->name));
3565 break;
3566 case XML_SCHEMA_TYPE_SEQUENCE:
3567 fprintf(output, "SEQUENCE");
3568 break;
3569 case XML_SCHEMA_TYPE_CHOICE:
3570 fprintf(output, "CHOICE");
3571 break;
3572 case XML_SCHEMA_TYPE_ALL:
3573 fprintf(output, "ALL");
3574 break;
3575 case XML_SCHEMA_TYPE_ANY:
3576 fprintf(output, "ANY");
3577 break;
3578 default:
3579 fprintf(output, "UNKNOWN\n");
3580 return;
3581 }
3582 if (particle->minOccurs != 1)
3583 fprintf(output, " min: %d", particle->minOccurs);
3584 if (particle->maxOccurs >= UNBOUNDED)
3585 fprintf(output, " max: unbounded");
3586 else if (particle->maxOccurs != 1)
3587 fprintf(output, " max: %d", particle->maxOccurs);
3588 fprintf(output, "\n");
3589 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3590 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3591 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3592 (term->children != NULL)) {
3593 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3594 output, depth +1);
3595 }
3596 if (particle->next != NULL)
3597 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3598 output, depth);
3599}
3600/**
3601 * xmlSchemaTypeDump:
3602 * @output: the file output
3603 * @type: a type structure
3604 *
3605 * Dump a SchemaType structure
3606 */
3607static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003608xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3609{
3610 if (type == NULL) {
3611 fprintf(output, "Type: NULL\n");
3612 return;
3613 }
3614 fprintf(output, "Type: ");
3615 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003616 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003617 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003618 fprintf(output, "no name ");
3619 if (type->targetNamespace != NULL)
3620 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003621 switch (type->type) {
3622 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003623 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003624 break;
3625 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003626 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003627 break;
3628 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003629 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003630 break;
3631 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003632 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003633 break;
3634 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003635 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003636 break;
3637 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003638 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003639 break;
3640 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003641 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003642 break;
3643 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003644 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003645 break;
3646 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003647 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003648 break;
3649 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003650 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003651 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003652 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003653 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003654 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003655 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003656 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003657 break;
3658 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003659 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003660 break;
3661 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003662 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003663 break;
3664 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003665 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003666 break;
3667 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003668 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003669 break;
3670 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003671 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003672 break;
3673 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003674 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003675 break;
3676 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003677 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003678 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003679 }
3680 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003681 if (type->base != NULL) {
3682 fprintf(output, " base type: %s", type->base);
3683 if (type->baseNs != NULL)
3684 fprintf(output, " ns %s\n", type->baseNs);
3685 else
3686 fprintf(output, "\n");
3687 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003688 if (type->annot != NULL)
3689 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003690#ifdef DUMP_CONTENT_MODEL
3691 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3692 (type->subtypes != NULL)) {
3693 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3694 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003695 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003696#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003697}
3698
3699/**
3700 * xmlSchemaDump:
3701 * @output: the file output
3702 * @schema: a schema structure
3703 *
3704 * Dump a Schema structure.
3705 */
3706void
3707xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3708{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003709 if (output == NULL)
3710 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003711 if (schema == NULL) {
3712 fprintf(output, "Schemas: NULL\n");
3713 return;
3714 }
3715 fprintf(output, "Schemas: ");
3716 if (schema->name != NULL)
3717 fprintf(output, "%s, ", schema->name);
3718 else
3719 fprintf(output, "no name, ");
3720 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003721 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003722 else
3723 fprintf(output, "no target namespace");
3724 fprintf(output, "\n");
3725 if (schema->annot != NULL)
3726 xmlSchemaAnnotDump(output, schema->annot);
3727
3728 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3729 output);
3730 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003731 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003732}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003733
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003734#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003735/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003736 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003737 * @vctxt: the WXS validation context
3738 *
3739 * Displays the current IDC table for debug purposes.
3740 */
3741static void
3742xmlSchemaDebugDumpIDCTable(FILE * output,
3743 const xmlChar *namespaceName,
3744 const xmlChar *localName,
3745 xmlSchemaPSVIIDCBindingPtr bind)
3746{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003747 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003748 xmlSchemaPSVIIDCNodePtr tab;
3749 xmlSchemaPSVIIDCKeyPtr key;
3750 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003751
3752 fprintf(output, "IDC: TABLES on %s\n",
3753 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003754 FREE_AND_NULL(str)
3755
3756 if (bind == NULL)
3757 return;
3758 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003759 fprintf(output, "IDC: BINDING %s\n",
3760 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003761 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003762 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003763 for (i = 0; i < bind->nbNodes; i++) {
3764 tab = bind->nodeTable[i];
3765 fprintf(output, " ( ");
3766 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003767 key = tab->keys[j];
3768 if ((key != NULL) && (key->val != NULL)) {
3769 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003770 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003771 fprintf(output, "\"%s\" ", value);
3772 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003773 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003774 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003775 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003776 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003777 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003778 else
3779 fprintf(output, "(key missing), ");
3780 }
3781 fprintf(output, ")\n");
3782 }
3783 bind = bind->next;
3784 } while (bind != NULL);
3785}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003786#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003787#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003788
3789/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003790 * *
3791 * Utilities *
3792 * *
3793 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003794
Daniel Veillardc0826a72004-08-10 14:17:33 +00003795/**
3796 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003797 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003798 * @name: the name of the attribute
3799 *
3800 * Seeks an attribute with a name of @name in
3801 * no namespace.
3802 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003803 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003804 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003805static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003806xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003807{
3808 xmlAttrPtr prop;
3809
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003810 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003811 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003812 prop = node->properties;
3813 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003814 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003815 return(prop);
3816 prop = prop->next;
3817 }
3818 return (NULL);
3819}
3820
3821/**
3822 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003823 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003824 * @uri: the uri
3825 * @name: the name of the attribute
3826 *
3827 * Seeks an attribute with a local name of @name and
3828 * a namespace URI of @uri.
3829 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003830 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003831 */
3832static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003833xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003834{
3835 xmlAttrPtr prop;
3836
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003837 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003838 return(NULL);
3839 prop = node->properties;
3840 while (prop != NULL) {
3841 if ((prop->ns != NULL) &&
3842 xmlStrEqual(prop->name, BAD_CAST name) &&
3843 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003844 return(prop);
3845 prop = prop->next;
3846 }
3847 return (NULL);
3848}
3849
3850static const xmlChar *
3851xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3852{
3853 xmlChar *val;
3854 const xmlChar *ret;
3855
3856 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003857 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003858 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003859 ret = xmlDictLookup(ctxt->dict, val, -1);
3860 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003861 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003862}
3863
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003864/**
3865 * xmlSchemaGetProp:
3866 * @ctxt: the parser context
3867 * @node: the node
3868 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003869 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003870 * Read a attribute value and internalize the string
3871 *
3872 * Returns the string or NULL if not present.
3873 */
3874static const xmlChar *
3875xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3876 const char *name)
3877{
3878 xmlChar *val;
3879 const xmlChar *ret;
3880
3881 val = xmlGetProp(node, BAD_CAST name);
3882 if (val == NULL)
3883 return(NULL);
3884 ret = xmlDictLookup(ctxt->dict, val, -1);
3885 xmlFree(val);
3886 return(ret);
3887}
3888
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003889/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003890 * *
3891 * Parsing functions *
3892 * *
3893 ************************************************************************/
3894
3895/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003896 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003897 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003898 * @name: the element name
3899 * @ns: the element namespace
3900 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003901 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003902 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003903 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003904 */
3905static xmlSchemaElementPtr
3906xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003907 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003908{
3909 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003910
3911 if ((name == NULL) || (schema == NULL))
3912 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003913
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003914 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003915 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003916 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003917 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003918 } else
3919 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003920 /*
3921 * This one was removed, since top level element declarations have
3922 * the target namespace specified in targetNamespace of the <schema>
3923 * information element, even if elementFormDefault is "unqualified".
3924 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003925
William M. Bracke7091952004-05-11 15:09:58 +00003926 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003927 if (xmlStrEqual(namespace, schema->targetNamespace))
3928 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3929 else
3930 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003931 if ((ret != NULL) &&
3932 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003933 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003934 }
William M. Bracke7091952004-05-11 15:09:58 +00003935 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003936
William M. Brack2f2a6632004-08-20 23:09:47 +00003937 /*
3938 * Removed since imported components will be hold by the main schema only.
3939 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003940 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003941 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003942 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003943 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003944 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003945 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003946 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3947 return (ret);
3948 } else
3949 ret = NULL;
3950 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003951 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003952#ifdef DEBUG
3953 if (ret == NULL) {
3954 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003955 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003956 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003957 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003958 namespace);
3959 }
3960#endif
3961 return (ret);
3962}
3963
3964/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003965 * xmlSchemaGetType:
3966 * @schema: the schemas context
3967 * @name: the type name
3968 * @ns: the type namespace
3969 *
3970 * Lookup a type in the schemas or the predefined types
3971 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003972 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003973 */
3974static xmlSchemaTypePtr
3975xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003976 const xmlChar * namespace)
3977{
Daniel Veillard4255d502002-04-16 15:50:10 +00003978 xmlSchemaTypePtr ret;
3979
3980 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003981 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003982 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003983 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003984 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003985 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003986 }
3987 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003988 if (ret != NULL)
3989 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003990 /*
3991 * Removed, since the imported components will be grafted on the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003992 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003993 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003994 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003995 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003996 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003997 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003998 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003999 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
4000 return (ret);
4001 } else
4002 ret = NULL;
4003 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004004 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004005#ifdef DEBUG
4006 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004007 if (namespace == NULL)
4008 fprintf(stderr, "Unable to lookup type %s", name);
4009 else
4010 fprintf(stderr, "Unable to lookup type %s:%s", name,
4011 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004012 }
4013#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004014 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004015}
4016
Daniel Veillard3646d642004-06-02 19:19:14 +00004017/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004018 * xmlSchemaGetAttributeDecl:
4019 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004020 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004021 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004022 *
4023 * Lookup a an attribute in the schema or imported schemas
4024 *
4025 * Returns the attribute declaration or NULL if not found.
4026 */
4027static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004028xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillard3646d642004-06-02 19:19:14 +00004029 const xmlChar * namespace)
4030{
4031 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004032
4033 if ((name == NULL) || (schema == NULL))
4034 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004035
4036
Daniel Veillard3646d642004-06-02 19:19:14 +00004037 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4038 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004039 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004040 else
4041 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004042 /*
4043 * Removed, since imported components will be hold by the main schema only.
4044 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004045 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004046 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004047 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004048 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004049 if (import != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004050 ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004051 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4052 return (ret);
4053 } else
4054 ret = NULL;
4055 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004056 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004057#ifdef DEBUG
4058 if (ret == NULL) {
4059 if (namespace == NULL)
4060 fprintf(stderr, "Unable to lookup attribute %s", name);
4061 else
4062 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4063 namespace);
4064 }
4065#endif
4066 return (ret);
4067}
4068
4069/**
4070 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004071 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004072 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004073 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004074 *
4075 * Lookup a an attribute group in the schema or imported schemas
4076 *
4077 * Returns the attribute group definition or NULL if not found.
4078 */
4079static xmlSchemaAttributeGroupPtr
4080xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4081 const xmlChar * namespace)
4082{
4083 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004084
4085 if ((name == NULL) || (schema == NULL))
4086 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004087
4088
Daniel Veillard3646d642004-06-02 19:19:14 +00004089 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4090 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004091 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004092 else
4093 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004094 /*
4095 * Removed since imported components will be hold by the main schema only.
4096 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004097 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004098 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004099 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004100 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004101 if (import != NULL) {
4102 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4103 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4104 return (ret);
4105 else
4106 ret = NULL;
4107 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004108 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004109#ifdef DEBUG
4110 if (ret == NULL) {
4111 if (namespace == NULL)
4112 fprintf(stderr, "Unable to lookup attribute group %s", name);
4113 else
4114 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4115 namespace);
4116 }
4117#endif
4118 return (ret);
4119}
4120
4121/**
4122 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004123 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004124 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004125 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004126 *
4127 * Lookup a group in the schema or imported schemas
4128 *
4129 * Returns the group definition or NULL if not found.
4130 */
4131static xmlSchemaTypePtr
4132xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4133 const xmlChar * namespace)
4134{
4135 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004136
4137 if ((name == NULL) || (schema == NULL))
4138 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004139
Daniel Veillard3646d642004-06-02 19:19:14 +00004140 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004141 /*
4142 * Removed since imported components will be hold by the main schema only.
4143 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004144 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004145 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004146 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004147 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004148 if (import != NULL) {
4149 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4150 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4151 return (ret);
4152 else
4153 ret = NULL;
4154 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004155 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004156#ifdef DEBUG
4157 if (ret == NULL) {
4158 if (namespace == NULL)
4159 fprintf(stderr, "Unable to lookup group %s", name);
4160 else
4161 fprintf(stderr, "Unable to lookup group %s:%s", name,
4162 namespace);
4163 }
4164#endif
4165 return (ret);
4166}
4167
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004168/**
4169 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004170 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004171 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004172 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004173 *
4174 * Lookup a group in the schema or imported schemas
4175 *
4176 * Returns the group definition or NULL if not found.
4177 */
4178static xmlSchemaTreeItemPtr
4179xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4180 xmlSchemaTypeType itemType,
4181 const xmlChar *name,
4182 const xmlChar *targetNs)
4183{
4184 switch (itemType) {
4185 case XML_SCHEMA_TYPE_GROUP:
4186 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4187 name, targetNs));
4188 case XML_SCHEMA_TYPE_ELEMENT:
4189 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4190 name, targetNs));
4191 default:
4192 return (NULL);
4193 }
4194}
4195
Daniel Veillard4255d502002-04-16 15:50:10 +00004196/************************************************************************
4197 * *
4198 * Parsing functions *
4199 * *
4200 ************************************************************************/
4201
4202#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004203 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004204
4205/**
4206 * xmlSchemaIsBlank:
4207 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004208 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004209 *
4210 * Check if a string is ignorable
4211 *
4212 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4213 */
4214static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004215xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004216{
Daniel Veillard4255d502002-04-16 15:50:10 +00004217 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004218 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004219 if (len < 0) {
4220 while (*str != 0) {
4221 if (!(IS_BLANK_CH(*str)))
4222 return (0);
4223 str++;
4224 }
4225 } else while ((*str != 0) && (len != 0)) {
4226 if (!(IS_BLANK_CH(*str)))
4227 return (0);
4228 str++;
4229 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004230 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004231
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004232 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004233}
4234
4235/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004236 * xmlSchemaAddAssembledItem:
4237 * @ctxt: a schema parser context
4238 * @schema: the schema being built
4239 * @item: the item
4240 *
4241 * Add a item to the schema's list of current items.
4242 * This is used if the schema was already constructed and
4243 * new schemata need to be added to it.
4244 * *WARNING* this interface is highly subject to change.
4245 *
4246 * Returns 0 if suceeds and -1 if an internal error occurs.
4247 */
4248static int
4249xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4250 xmlSchemaTypePtr item)
4251{
4252 static int growSize = 100;
4253 xmlSchemaAssemblePtr ass;
4254
4255 ass = ctxt->assemble;
4256 if (ass->sizeItems < 0) {
4257 /* If disabled. */
4258 return (0);
4259 }
4260 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004261 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004262 if (ass->items == NULL) {
4263 xmlSchemaPErrMemory(ctxt,
4264 "allocating new item buffer", NULL);
4265 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004266 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004267 ass->sizeItems = growSize;
4268 } else if (ass->sizeItems <= ass->nbItems) {
4269 ass->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004270 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004271 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4272 if (ass->items == NULL) {
4273 xmlSchemaPErrMemory(ctxt,
4274 "growing item buffer", NULL);
4275 ass->sizeItems = 0;
4276 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004277 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004278 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004279 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004280 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4281 return (0);
4282}
4283
4284/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004285 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004286 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004287 * @schema: the schema being built
4288 * @name: the item name
4289 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004290 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004291 * *WARNING* this interface is highly subject to change
4292 *
4293 * Returns the new struture or NULL in case of error
4294 */
4295static xmlSchemaNotationPtr
4296xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004297 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004298{
4299 xmlSchemaNotationPtr ret = NULL;
4300 int val;
4301
4302 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4303 return (NULL);
4304
4305 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004306 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004307 if (schema->notaDecl == NULL)
4308 return (NULL);
4309
4310 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4311 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004312 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004313 return (NULL);
4314 }
4315 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004316 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004317 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4318 ret);
4319 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004320 /*
4321 * TODO: This should never happen, since a unique name will be computed.
4322 * If it fails, then an other internal error must have occured.
4323 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004324 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4325 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004326 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004327 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004328 xmlFree(ret);
4329 return (NULL);
4330 }
4331 return (ret);
4332}
4333
4334
4335/**
4336 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004337 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004338 * @schema: the schema being built
4339 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004340 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004341 *
4342 * Add an XML schema Attrribute declaration
4343 * *WARNING* this interface is highly subject to change
4344 *
4345 * Returns the new struture or NULL in case of error
4346 */
4347static xmlSchemaAttributePtr
4348xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004349 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004350 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004351{
4352 xmlSchemaAttributePtr ret = NULL;
4353 int val;
4354
4355 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4356 return (NULL);
4357
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004358#ifdef DEBUG
4359 fprintf(stderr, "Adding attribute %s\n", name);
4360 if (namespace != NULL)
4361 fprintf(stderr, " target namespace %s\n", namespace);
4362#endif
4363
Daniel Veillard4255d502002-04-16 15:50:10 +00004364 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004365 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004366 if (schema->attrDecl == NULL)
4367 return (NULL);
4368
4369 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4370 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004371 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004372 return (NULL);
4373 }
4374 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004375 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004376 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004377 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004378 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004379 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004380 if (topLevel) {
4381 xmlSchemaPCustomErr(ctxt,
4382 XML_SCHEMAP_REDEFINED_ATTR,
4383 NULL, NULL, node,
4384 "A global attribute declaration with the name '%s' does "
4385 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004386 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004387 return (NULL);
4388 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004389 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004390 /*
4391 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4392 * in the scenario:
4393 * 1. multiple top-level complex types have different target
4394 * namespaces but have the SAME NAME; this can happen if
4395 * schemata are imported
4396 * 2. those complex types contain attributes with an equal name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004397 * 3. those attributes are in no namespace
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004398 * We will compute a new context string.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004399 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004400 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004401 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004402 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004403
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004404 if (val != 0) {
4405 xmlSchemaPCustomErr(ctxt,
4406 XML_SCHEMAP_INTERNAL,
4407 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004408 "Internal error: xmlSchemaAddAttribute, "
4409 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004410 "could not be added to the hash.", name);
4411 xmlFree(ret);
4412 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004413 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004414 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004415 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004416 if (ctxt->assemble != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004417 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004418 return (ret);
4419}
4420
4421/**
4422 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004423 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004424 * @schema: the schema being built
4425 * @name: the item name
4426 *
4427 * Add an XML schema Attrribute Group declaration
4428 *
4429 * Returns the new struture or NULL in case of error
4430 */
4431static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004432xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004433 xmlSchemaPtr schema, const xmlChar * name,
4434 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004435{
4436 xmlSchemaAttributeGroupPtr ret = NULL;
4437 int val;
4438
4439 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4440 return (NULL);
4441
4442 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004443 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004444 if (schema->attrgrpDecl == NULL)
4445 return (NULL);
4446
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004447 ret =
4448 (xmlSchemaAttributeGroupPtr)
4449 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004450 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004451 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004452 return (NULL);
4453 }
4454 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004455 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004456 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004457 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004458 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004459 xmlSchemaPCustomErr(ctxt,
4460 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4461 NULL, NULL, node,
4462 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004463 xmlFree(ret);
4464 return (NULL);
4465 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004466 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004467 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004468 return (ret);
4469}
4470
4471/**
4472 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004473 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004474 * @schema: the schema being built
4475 * @name: the type name
4476 * @namespace: the type namespace
4477 *
4478 * Add an XML schema Element declaration
4479 * *WARNING* this interface is highly subject to change
4480 *
4481 * Returns the new struture or NULL in case of error
4482 */
4483static xmlSchemaElementPtr
4484xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004485 const xmlChar * name, const xmlChar * namespace,
4486 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004487{
4488 xmlSchemaElementPtr ret = NULL;
4489 int val;
4490
4491 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4492 return (NULL);
4493
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004494#ifdef DEBUG
4495 fprintf(stderr, "Adding element %s\n", name);
4496 if (namespace != NULL)
4497 fprintf(stderr, " target namespace %s\n", namespace);
4498#endif
4499
Daniel Veillard4255d502002-04-16 15:50:10 +00004500 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004501 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004502 if (schema->elemDecl == NULL)
4503 return (NULL);
4504
4505 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4506 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004507 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004508 return (NULL);
4509 }
4510 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004511 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004512 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004513 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004514 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004515 if (topLevel) {
4516 xmlSchemaPCustomErr(ctxt,
4517 XML_SCHEMAP_REDEFINED_ELEMENT,
4518 NULL, NULL, node,
4519 "A global element declaration with the name '%s' does "
4520 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004521 xmlFree(ret);
4522 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004523 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004524 char buf[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00004525
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004526 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004527 val = xmlHashAddEntry3(schema->elemDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004528 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004529 if (val != 0) {
4530 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004531 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004532 NULL, NULL, node,
4533 "Internal error: xmlSchemaAddElement, "
4534 "a dublicate element declaration with the name '%s' "
4535 "could not be added to the hash.", name);
4536 xmlFree(ret);
4537 return (NULL);
4538 }
4539 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004540
Daniel Veillard4255d502002-04-16 15:50:10 +00004541 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004542 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004543 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004544 return (ret);
4545}
4546
4547/**
4548 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004549 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004550 * @schema: the schema being built
4551 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004552 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004553 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004554 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004555 * *WARNING* this interface is highly subject to change
4556 *
4557 * Returns the new struture or NULL in case of error
4558 */
4559static xmlSchemaTypePtr
4560xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004561 const xmlChar * name, const xmlChar * namespace,
4562 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004563{
4564 xmlSchemaTypePtr ret = NULL;
4565 int val;
4566
4567 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4568 return (NULL);
4569
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004570#ifdef DEBUG
4571 fprintf(stderr, "Adding type %s\n", name);
4572 if (namespace != NULL)
4573 fprintf(stderr, " target namespace %s\n", namespace);
4574#endif
4575
Daniel Veillard4255d502002-04-16 15:50:10 +00004576 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004577 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004578 if (schema->typeDecl == NULL)
4579 return (NULL);
4580
4581 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4582 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004583 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004584 return (NULL);
4585 }
4586 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004587 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004588 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004589 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004590 if (val != 0) {
4591 if (ctxt->includes == 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004592 xmlSchemaPCustomErr(ctxt,
4593 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004594 NULL, NULL, node,
4595 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004596 xmlFree(ret);
4597 return (NULL);
4598 } else {
4599 xmlSchemaTypePtr prev;
4600
4601 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4602 if (prev == NULL) {
4603 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004604 XML_ERR_INTERNAL_ERROR,
4605 "Internal error: xmlSchemaAddType, on type "
4606 "'%s'.\n",
4607 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004608 xmlFree(ret);
4609 return (NULL);
4610 }
4611 ret->redef = prev->redef;
4612 prev->redef = ret;
4613 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004614 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004615 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004616 ret->minOccurs = 1;
4617 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004618 ret->attributeUses = NULL;
4619 ret->attributeWildcard = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004620 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004621 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004622 return (ret);
4623}
4624
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004625static xmlSchemaQNameRefPtr
4626xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4627 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004628 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004629 const xmlChar *refNs)
4630{
4631 xmlSchemaQNameRefPtr ret;
4632
4633 ret = (xmlSchemaQNameRefPtr)
4634 xmlMalloc(sizeof(xmlSchemaQNameRef));
4635 if (ret == NULL) {
4636 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4637 NULL);
4638 return (NULL);
4639 }
4640 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4641 ret->name = refName;
4642 ret->targetNamespace = refNs;
4643 ret->item = NULL;
4644 ret->itemType = refType;
4645 /*
4646 * Store the reference item in the schema.
4647 */
4648 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4649 return (ret);
4650}
4651
4652/**
4653 * xmlSchemaAddModelGroup:
4654 * @ctxt: a schema parser context
4655 * @schema: the schema being built
4656 * @type: the "compositor" type of the model group
4657 * @container: the internal component name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004658 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004659 *
4660 * Adds a schema model group
4661 * *WARNING* this interface is highly subject to change
4662 *
4663 * Returns the new struture or NULL in case of error
4664 */
4665static xmlSchemaModelGroupPtr
4666xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4667 xmlSchemaTypeType type, const xmlChar **container,
4668 xmlNodePtr node)
4669{
4670 xmlSchemaModelGroupPtr ret = NULL;
4671 xmlChar buf[30];
4672
4673 if ((ctxt == NULL) || (schema == NULL))
4674 return (NULL);
4675
4676#ifdef DEBUG
4677 fprintf(stderr, "Adding model group component\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004678#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004679 ret = (xmlSchemaModelGroupPtr)
4680 xmlMalloc(sizeof(xmlSchemaModelGroup));
4681 if (ret == NULL) {
4682 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4683 NULL);
4684 return (NULL);
4685 }
4686 ret->type = type;
4687 ret->annot = NULL;
4688 ret->node = node;
4689 ret->children = NULL;
4690 ret->next = NULL;
4691 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4692 if (container != NULL)
4693 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4694 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004695 if (container != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004696 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4697 } else {
4698 if (container != NULL)
4699 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4700 }
4701 if (container != NULL)
4702 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4703 /*
4704 * Add to volatile items.
4705 * TODO: this should be changed someday.
4706 */
4707 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4708 xmlFree(ret);
4709 return (NULL);
4710 }
4711 return (ret);
4712}
4713
4714
4715/**
4716 * xmlSchemaAddParticle:
4717 * @ctxt: a schema parser context
4718 * @schema: the schema being built
4719 * @node: the corresponding node in the schema doc
4720 * @min: the minOccurs
4721 * @max: the maxOccurs
4722 *
4723 * Adds an XML schema particle component.
4724 * *WARNING* this interface is highly subject to change
4725 *
4726 * Returns the new struture or NULL in case of error
4727 */
4728static xmlSchemaParticlePtr
4729xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4730 xmlNodePtr node, int min, int max)
4731{
4732 xmlSchemaParticlePtr ret = NULL;
4733 if ((ctxt == NULL) || (schema == NULL))
4734 return (NULL);
4735
4736#ifdef DEBUG
4737 fprintf(stderr, "Adding particle component\n");
4738#endif
4739 ret = (xmlSchemaParticlePtr)
4740 xmlMalloc(sizeof(xmlSchemaParticle));
4741 if (ret == NULL) {
4742 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4743 NULL);
4744 return (NULL);
4745 }
4746 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4747 ret->annot = NULL;
4748 ret->node = node;
4749 ret->minOccurs = min;
4750 ret->maxOccurs = max;
4751 ret->next = NULL;
4752 ret->children = NULL;
4753
4754 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4755 xmlFree(ret);
4756 return (NULL);
4757 }
4758 return (ret);
4759}
4760
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004761/**
4762 * xmlSchemaAddGroup:
4763 * @ctxt: a schema validation context
4764 * @schema: the schema being built
4765 * @name: the group name
4766 *
4767 * Add an XML schema Group definition
4768 *
4769 * Returns the new struture or NULL in case of error
4770 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004771static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004772xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004773 const xmlChar *name, const xmlChar *namespaceName,
4774 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004775{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004776 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004777 int val;
4778
4779 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4780 return (NULL);
4781
4782 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004783 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004784 if (schema->groupDecl == NULL)
4785 return (NULL);
4786
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004787 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004788 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004789 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004790 return (NULL);
4791 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004792 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004793 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004794 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004795 ret->node = node;
4796 ret->targetNamespace = namespaceName;
4797 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004798 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004799 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004800 XML_SCHEMAP_REDEFINED_GROUP,
4801 NULL, NULL, node,
4802 "A global model group definition with the name '%s' does already "
4803 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004804 xmlFree(ret);
4805 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004806 }
4807 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004808 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004809 return (ret);
4810}
4811
Daniel Veillard3646d642004-06-02 19:19:14 +00004812/**
4813 * xmlSchemaNewWildcardNs:
4814 * @ctxt: a schema validation context
4815 *
4816 * Creates a new wildcard namespace constraint.
4817 *
4818 * Returns the new struture or NULL in case of error
4819 */
4820static xmlSchemaWildcardNsPtr
4821xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4822{
4823 xmlSchemaWildcardNsPtr ret;
4824
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004825 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004826 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4827 if (ret == NULL) {
4828 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004829 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00004830 }
4831 ret->value = NULL;
4832 ret->next = NULL;
4833 return (ret);
4834}
4835
4836/**
4837 * xmlSchemaAddWildcard:
4838 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004839 * @schema: a schema
4840 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004841 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004842 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004843 *
4844 * Returns the new struture or NULL in case of error
4845 */
4846static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004847xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4848 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004849{
4850 xmlSchemaWildcardPtr ret = NULL;
4851
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004852 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004853 return (NULL);
4854
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004855#ifdef DEBUG
4856 fprintf(stderr, "Adding wildcard component\n");
4857#endif
4858
Daniel Veillard3646d642004-06-02 19:19:14 +00004859 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4860 if (ret == NULL) {
4861 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4862 return (NULL);
4863 }
4864 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004865 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004866 ret->minOccurs = 1;
4867 ret->maxOccurs = 1;
4868
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004869 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4870 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4871 "Failed to add a wildcard component to the list", NULL);
4872 xmlFree(ret);
4873 return (NULL);
4874 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004875 return (ret);
4876}
4877
Daniel Veillard4255d502002-04-16 15:50:10 +00004878/************************************************************************
4879 * *
4880 * Utilities for parsing *
4881 * *
4882 ************************************************************************/
4883
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004884#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004885/**
4886 * xmlGetQNameProp:
4887 * @ctxt: a schema validation context
4888 * @node: a subtree containing XML Schema informations
4889 * @name: the attribute name
4890 * @namespace: the result namespace if any
4891 *
4892 * Extract a QName Attribute value
4893 *
4894 * Returns the NCName or NULL if not found, and also update @namespace
4895 * with the namespace URI
4896 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004897static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004898xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004899 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004900{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004901 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004902 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004903 const xmlChar *ret, *prefix;
4904 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004905 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004906
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004907 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004908 attr = xmlSchemaGetPropNode(node, name);
4909 if (attr == NULL)
4910 return (NULL);
4911 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004912
Daniel Veillard4255d502002-04-16 15:50:10 +00004913 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004914 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004915
Daniel Veillardba0153a2004-04-01 10:42:31 +00004916 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004917 ns = xmlSearchNs(node->doc, node, 0);
4918 if (ns) {
4919 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4920 return (val);
4921 }
4922 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004923 ret = xmlSplitQName3(val, &len);
4924 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004925 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004926 }
4927 ret = xmlDictLookup(ctxt->dict, ret, -1);
4928 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004929
4930 ns = xmlSearchNs(node->doc, node, prefix);
4931 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004932 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4933 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004934 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004935 "The QName value '%s' has no corresponding namespace "
4936 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004937 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004938 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004939 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004940 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004941}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004942#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004943
4944/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004945 * xmlSchemaPValAttrNodeQNameValue:
4946 * @ctxt: a schema parser context
4947 * @schema: the schema context
4948 * @ownerDes: the designation of the parent element
4949 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004950 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00004951 * @local: the resulting local part if found, the attribute value otherwise
4952 * @uri: the resulting namespace URI if found
4953 *
4954 * Extracts the local name and the URI of a QName value and validates it.
4955 * This one is intended to be used on attribute values that
4956 * should resolve to schema components.
4957 *
4958 * Returns 0, in case the QName is valid, a positive error code
4959 * if not valid and -1 if an internal error occurs.
4960 */
4961static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004962xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004963 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004964 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004965 xmlSchemaTypePtr ownerItem,
4966 xmlAttrPtr attr,
4967 const xmlChar *value,
4968 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004969 const xmlChar **local)
4970{
4971 const xmlChar *pref;
4972 xmlNsPtr ns;
4973 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004974
Daniel Veillardc0826a72004-08-10 14:17:33 +00004975 *uri = NULL;
4976 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004977 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004978 if (ret > 0) {
4979 xmlSchemaPSimpleTypeErr(ctxt,
4980 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4981 ownerItem, (xmlNodePtr) attr,
4982 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4983 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004984 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004985 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004986 } else if (ret < 0)
4987 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004988
4989 if (!strchr((char *) value, ':')) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004990 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4991 if (ns)
4992 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4993 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4994 /*
4995 * This one takes care of included schemas with no
4996 * target namespace.
4997 */
4998 *uri = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004999 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005000 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005001 return (0);
5002 }
5003 /*
5004 * At this point xmlSplitQName3 has to return a local name.
5005 */
5006 *local = xmlSplitQName3(value, &len);
5007 *local = xmlDictLookup(ctxt->dict, *local, -1);
5008 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005009 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5010 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005011 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005012 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005013 ownerItem, (xmlNodePtr) attr,
5014 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5015 "The value '%s' of simple type 'xs:QName' has no "
5016 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005017 return (ctxt->err);
5018 } else {
5019 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005020 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005021 return (0);
5022}
5023
5024/**
5025 * xmlSchemaPValAttrNodeQName:
5026 * @ctxt: a schema parser context
5027 * @schema: the schema context
5028 * @ownerDes: the designation of the owner element
5029 * @ownerItem: the owner as a schema object
5030 * @attr: the attribute node
5031 * @local: the resulting local part if found, the attribute value otherwise
5032 * @uri: the resulting namespace URI if found
5033 *
5034 * Extracts and validates the QName of an attribute value.
5035 * This one is intended to be used on attribute values that
5036 * should resolve to schema components.
5037 *
5038 * Returns 0, in case the QName is valid, a positive error code
5039 * if not valid and -1 if an internal error occurs.
5040 */
5041static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005042xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005043 xmlSchemaPtr schema,
5044 xmlChar **ownerDes,
5045 xmlSchemaTypePtr ownerItem,
5046 xmlAttrPtr attr,
5047 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005048 const xmlChar **local)
5049{
5050 const xmlChar *value;
5051
5052 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005053 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5054 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005055}
5056
5057/**
5058 * xmlSchemaPValAttrQName:
5059 * @ctxt: a schema parser context
5060 * @schema: the schema context
5061 * @ownerDes: the designation of the parent element
5062 * @ownerItem: the owner as a schema object
5063 * @ownerElem: the parent node of the attribute
5064 * @name: the name of the attribute
5065 * @local: the resulting local part if found, the attribute value otherwise
5066 * @uri: the resulting namespace URI if found
5067 *
5068 * Extracts and validates the QName of an attribute value.
5069 *
5070 * Returns 0, in case the QName is valid, a positive error code
5071 * if not valid and -1 if an internal error occurs.
5072 */
5073static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005074xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5075 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005076 xmlChar **ownerDes,
5077 xmlSchemaTypePtr ownerItem,
5078 xmlNodePtr ownerElem,
5079 const char *name,
5080 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005081 const xmlChar **local)
5082{
5083 xmlAttrPtr attr;
5084
5085 attr = xmlSchemaGetPropNode(ownerElem, name);
5086 if (attr == NULL) {
5087 *local = NULL;
5088 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005089 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005090 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005091 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5092 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005093}
5094
5095/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005096 * xmlSchemaPValAttrID:
5097 * @ctxt: a schema parser context
5098 * @schema: the schema context
5099 * @ownerDes: the designation of the parent element
5100 * @ownerItem: the owner as a schema object
5101 * @ownerElem: the parent node of the attribute
5102 * @name: the name of the attribute
5103 *
5104 * Extracts and validates the ID of an attribute value.
5105 *
5106 * Returns 0, in case the ID is valid, a positive error code
5107 * if not valid and -1 if an internal error occurs.
5108 */
5109static int
5110xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005111 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005112 xmlSchemaTypePtr ownerItem,
5113 xmlNodePtr ownerElem,
5114 const xmlChar *name)
5115{
5116 int ret;
5117 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005118 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005119
5120 value = xmlGetNoNsProp(ownerElem, name);
5121 if (value == NULL)
5122 return (0);
5123
5124 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5125 if (attr == NULL)
5126 return (-1);
5127
5128 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005129 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005130 /*
5131 * NOTE: the IDness might have already be declared in the DTD
5132 */
5133 if (attr->atype != XML_ATTRIBUTE_ID) {
5134 xmlIDPtr res;
5135 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005136
5137 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005138 * TODO: Use xmlSchemaStrip here; it's not exported at this
5139 * moment.
5140 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005141 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005142 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005143 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005144 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5145 if (res == NULL) {
5146 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005147 xmlSchemaPSimpleTypeErr(ctxt,
5148 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5149 ownerItem, (xmlNodePtr) attr,
5150 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5151 NULL, NULL, "Duplicate value '%s' of simple "
5152 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005153 } else
5154 attr->atype = XML_ATTRIBUTE_ID;
5155 if (strip != NULL)
5156 xmlFree(strip);
5157 }
5158 } else if (ret > 0) {
5159 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005160 xmlSchemaPSimpleTypeErr(ctxt,
5161 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5162 ownerItem, (xmlNodePtr) attr,
5163 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5164 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5165 "not a valid 'xs:NCName'",
5166 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005167 }
5168 xmlFree(value);
5169
5170 return (ret);
5171}
5172
5173/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005174 * xmlGetMaxOccurs:
5175 * @ctxt: a schema validation context
5176 * @node: a subtree containing XML Schema informations
5177 *
5178 * Get the maxOccurs property
5179 *
5180 * Returns the default if not found, or the value
5181 */
5182static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005183xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5184 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005185{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005186 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005187 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005188 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005189
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005190 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5191 if (attr == NULL)
5192 return (def);
5193 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005194
5195 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005196 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005197 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005198 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5199 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005200 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005201 val, NULL, NULL, NULL);
5202 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005203 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005204 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005205 }
5206
5207 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005208 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005209 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005210 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005211 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005212 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5213 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005214 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005215 val, NULL, NULL, NULL);
5216 return (def);
5217 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005218 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005219 ret = ret * 10 + (*cur - '0');
5220 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005221 }
William M. Brack76e95df2003-10-18 16:20:14 +00005222 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005223 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005224 /*
5225 * TODO: Restrict the maximal value to Integer.
5226 */
5227 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005228 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005229 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5230 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005231 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005232 val, NULL, NULL, NULL);
5233 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005234 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005235 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005236}
5237
5238/**
5239 * xmlGetMinOccurs:
5240 * @ctxt: a schema validation context
5241 * @node: a subtree containing XML Schema informations
5242 *
5243 * Get the minOccurs property
5244 *
5245 * Returns the default if not found, or the value
5246 */
5247static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005248xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005249 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005250{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005251 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005252 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005253 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005254
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005255 attr = xmlSchemaGetPropNode(node, "minOccurs");
5256 if (attr == NULL)
5257 return (def);
5258 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005259 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005260 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005261 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005262 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005263 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005264 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5265 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005266 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005267 val, NULL, NULL, NULL);
5268 return (def);
5269 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005270 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005271 ret = ret * 10 + (*cur - '0');
5272 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005273 }
William M. Brack76e95df2003-10-18 16:20:14 +00005274 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005275 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005276 /*
5277 * TODO: Restrict the maximal value to Integer.
5278 */
5279 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005280 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005281 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5282 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005283 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005284 val, NULL, NULL, NULL);
5285 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005286 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005287 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005288}
5289
5290/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005291 * xmlSchemaPGetBoolNodeValue:
5292 * @ctxt: a schema validation context
5293 * @ownerDes: owner designation
5294 * @ownerItem: the owner as a schema item
5295 * @node: the node holding the value
5296 *
5297 * Converts a boolean string value into 1 or 0.
5298 *
5299 * Returns 0 or 1.
5300 */
5301static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005302xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5303 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005304 xmlSchemaTypePtr ownerItem,
5305 xmlNodePtr node)
5306{
5307 xmlChar *value = NULL;
5308 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005309
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005310 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005311 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005312 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005313 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005314 * can have the following legal literals {true, false, 1, 0}.
5315 */
5316 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5317 res = 1;
5318 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5319 res = 0;
5320 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5321 res = 1;
5322 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005323 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005324 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005325 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005326 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005327 ownerItem, node,
5328 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5329 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005330 NULL, NULL, NULL);
5331 }
5332 if (value != NULL)
5333 xmlFree(value);
5334 return (res);
5335}
5336
5337/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005338 * xmlGetBooleanProp:
5339 * @ctxt: a schema validation context
5340 * @node: a subtree containing XML Schema informations
5341 * @name: the attribute name
5342 * @def: the default value
5343 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005344 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005345 *
5346 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005347 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005348 */
5349static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005350xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5351 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005352 xmlSchemaTypePtr ownerItem,
5353 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005354 const char *name, int def)
5355{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005356 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005357
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005358 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005359 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005360 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005361 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005362 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005363 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005364 * can have the following legal literals {true, false, 1, 0}.
5365 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005366 if (xmlStrEqual(val, BAD_CAST "true"))
5367 def = 1;
5368 else if (xmlStrEqual(val, BAD_CAST "false"))
5369 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005370 else if (xmlStrEqual(val, BAD_CAST "1"))
5371 def = 1;
5372 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005373 def = 0;
5374 else {
5375 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005376 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005377 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005378 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005379 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5380 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005381 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005382 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005383}
5384
5385/************************************************************************
5386 * *
5387 * Shema extraction from an Infoset *
5388 * *
5389 ************************************************************************/
5390static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5391 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005392 xmlNodePtr node,
5393 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005394static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5395 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005396 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005397 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005398 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005399static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5400 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005401 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005402 xmlNodePtr node,
5403 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005404static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5405 ctxt,
5406 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005407 xmlNodePtr node,
5408 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005409static xmlSchemaAttributeGroupPtr
5410xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005411 xmlSchemaPtr schema, xmlNodePtr node,
5412 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005413static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5414 xmlSchemaPtr schema,
5415 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005416static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005417xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5418 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005419
5420/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005421 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005422 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005423 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005424 * @ownerDes: the designation of the parent element
5425 * @ownerItem: the schema object owner if existent
5426 * @attr: the schema attribute node being validated
5427 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005428 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005429 *
5430 * Validates a value against the given built-in type.
5431 * This one is intended to be used internally for validation
5432 * of schema attribute values during parsing of the schema.
5433 *
5434 * Returns 0 if the value is valid, a positive error code
5435 * number otherwise and -1 in case of an internal or API error.
5436 */
5437static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005438xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5439 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5440 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005441 xmlAttrPtr attr,
5442 const xmlChar *value,
5443 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005444{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005445
5446 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005447
5448 /*
5449 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5450 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005451 */
5452 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005453 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005454 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5455 PERROR_INT("xmlSchemaPValAttrNodeValue",
5456 "the given type is not a built-in type");
5457 return (-1);
5458 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005459 switch (type->builtInType) {
5460 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005461 case XML_SCHEMAS_QNAME:
5462 case XML_SCHEMAS_ANYURI:
5463 case XML_SCHEMAS_TOKEN:
5464 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005465 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5466 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005467 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005468 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005469 PERROR_INT("xmlSchemaPValAttrNodeValue",
5470 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005471 return (-1);
5472 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005473 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005474 /*
5475 * TODO: Should we use the S4S error codes instead?
5476 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005477 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005478 PERROR_INT("xmlSchemaPValAttrNodeValue",
5479 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005480 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005481 } else if (ret > 0) {
5482 if (VARIETY_LIST(type))
5483 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5484 else
5485 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5486 xmlSchemaPSimpleTypeErr(pctxt,
5487 ret, ownerItem, (xmlNodePtr) attr,
5488 type, NULL, value, NULL, NULL, NULL);
5489 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005490 return (ret);
5491}
5492
5493/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005494 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005495 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005496 * @ctxt: a schema parser context
5497 * @ownerDes: the designation of the parent element
5498 * @ownerItem: the schema object owner if existent
5499 * @attr: the schema attribute node being validated
5500 * @type: the built-in type to be validated against
5501 * @value: the resulting value if any
5502 *
5503 * Extracts and validates a value against the given built-in type.
5504 * This one is intended to be used internally for validation
5505 * of schema attribute values during parsing of the schema.
5506 *
5507 * Returns 0 if the value is valid, a positive error code
5508 * number otherwise and -1 in case of an internal or API error.
5509 */
5510static int
5511xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5512 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005513 xmlSchemaTypePtr ownerItem,
5514 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005515 xmlSchemaTypePtr type,
5516 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005517{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005518 const xmlChar *val;
5519
5520 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005521 return (-1);
5522
Daniel Veillardc0826a72004-08-10 14:17:33 +00005523 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5524 if (value != NULL)
5525 *value = val;
5526
5527 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005528 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005529}
5530
5531/**
5532 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005533 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005534 * @ctxt: a schema parser context
5535 * @node: the element node of the attribute
5536 * @ownerDes: the designation of the parent element
5537 * @ownerItem: the schema object owner if existent
5538 * @ownerElem: the owner element node
5539 * @name: the name of the schema attribute node
5540 * @type: the built-in type to be validated against
5541 * @value: the resulting value if any
5542 *
5543 * Extracts and validates a value against the given built-in type.
5544 * This one is intended to be used internally for validation
5545 * of schema attribute values during parsing of the schema.
5546 *
5547 * Returns 0 if the value is valid, a positive error code
5548 * number otherwise and -1 in case of an internal or API error.
5549 */
5550static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005551xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005552 xmlChar **ownerDes,
5553 xmlSchemaTypePtr ownerItem,
5554 xmlNodePtr ownerElem,
5555 const char *name,
5556 xmlSchemaTypePtr type,
5557 const xmlChar **value)
5558{
5559 xmlAttrPtr attr;
5560
5561 if ((ctxt == NULL) || (type == NULL)) {
5562 if (value != NULL)
5563 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005564 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005565 }
5566 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5567 if (value != NULL)
5568 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005569 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005570 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005571 "Internal error: xmlSchemaPValAttr, the given "
5572 "type '%s' is not a built-in type.\n",
5573 type->name, NULL);
5574 return (-1);
5575 }
5576 attr = xmlSchemaGetPropNode(ownerElem, name);
5577 if (attr == NULL) {
5578 if (value != NULL)
5579 *value = NULL;
5580 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005581 }
5582 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005583 type, value));
5584}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005585
5586static int
5587xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5588 xmlSchemaPtr schema,
5589 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005590 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005591 const xmlChar *namespaceName)
5592{
5593 if (xmlStrEqual(schema->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005594 return (1);
5595 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5596 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005597 if (pctxt->localImports != NULL) {
5598 int i;
5599 for (i = 0; i < pctxt->nbLocalImports; i++)
5600 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5601 return (1);
5602 }
5603 if (namespaceName == NULL)
5604 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005605 NULL, (xmlSchemaTypePtr) item, node,
5606 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005607 "namespace are not valid, since not indicated by an import "
5608 "statement", NULL);
5609 else
5610 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005611 NULL, (xmlSchemaTypePtr) item, node,
5612 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005613 "namespace '%s' are not valid, since not indicated by an import "
5614 "statement", namespaceName);
5615 return (0);
5616}
5617
Daniel Veillardc0826a72004-08-10 14:17:33 +00005618/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005619 * xmlSchemaParseAttrDecls:
5620 * @ctxt: a schema validation context
5621 * @schema: the schema being built
5622 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005623 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005624 *
5625 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005626 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005627 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5628 */
5629static xmlNodePtr
5630xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5631 xmlNodePtr child, xmlSchemaTypePtr type)
5632{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005633 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005634
Daniel Veillard4255d502002-04-16 15:50:10 +00005635 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005636 (IS_SCHEMA(child, "attributeGroup"))) {
5637 attr = NULL;
5638 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005639 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005640 } else if (IS_SCHEMA(child, "attributeGroup")) {
5641 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005642 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005643 }
5644 if (attr != NULL) {
5645 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005646 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5647 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5648 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005649 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005650 lastattr = attr;
5651 } else {
5652 lastattr->next = attr;
5653 lastattr = attr;
5654 }
5655 }
5656 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005657 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005658 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005659}
5660
5661/**
5662 * xmlSchemaParseAnnotation:
5663 * @ctxt: a schema validation context
5664 * @schema: the schema being built
5665 * @node: a subtree containing XML Schema informations
5666 *
5667 * parse a XML schema Attrribute declaration
5668 * *WARNING* this interface is highly subject to change
5669 *
William M. Bracke7091952004-05-11 15:09:58 +00005670 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005671 * 1 in case of success.
5672 */
5673static xmlSchemaAnnotPtr
5674xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5675 xmlNodePtr node)
5676{
5677 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005678 xmlNodePtr child = NULL;
5679 xmlAttrPtr attr;
5680 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005681
Daniel Veillardc0826a72004-08-10 14:17:33 +00005682 /*
5683 * INFO: S4S completed.
5684 */
5685 /*
5686 * id = ID
5687 * {any attributes with non-schema namespace . . .}>
5688 * Content: (appinfo | documentation)*
5689 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005690 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5691 return (NULL);
5692 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005693 attr = node->properties;
5694 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005695 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005696 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005697 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005698 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005699
5700 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005701 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5702 NULL, NULL, attr);
5703 }
5704 attr = attr->next;
5705 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005706 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005707 /*
5708 * And now for the children...
5709 */
5710 child = node->children;
5711 while (child != NULL) {
5712 if (IS_SCHEMA(child, "appinfo")) {
5713 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005714 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005715 * source = anyURI
5716 * {any attributes with non-schema namespace . . .}>
5717 * Content: ({any})*
5718 */
5719 attr = child->properties;
5720 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005721 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005722 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005723 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005724 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005725
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005726 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005727 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5728 NULL, NULL, attr);
5729 }
5730 attr = attr->next;
5731 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005732 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5733 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005734 child = child->next;
5735 } else if (IS_SCHEMA(child, "documentation")) {
5736 /* TODO: make available the content of "documentation". */
5737 /*
5738 * source = anyURI
5739 * {any attributes with non-schema namespace . . .}>
5740 * Content: ({any})*
5741 */
5742 attr = child->properties;
5743 while (attr != NULL) {
5744 if (attr->ns == NULL) {
5745 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005746 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005747 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5748 NULL, NULL, attr);
5749 }
5750 } else {
5751 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5752 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5753 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005754
5755 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005756 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5757 NULL, NULL, attr);
5758 }
5759 }
5760 attr = attr->next;
5761 }
5762 /*
5763 * Attribute "xml:lang".
5764 */
5765 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5766 if (attr != NULL)
5767 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005768 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005769 child = child->next;
5770 } else {
5771 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005772 xmlSchemaPContentErr(ctxt,
5773 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005774 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5775 barked = 1;
5776 child = child->next;
5777 }
5778 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005779
Daniel Veillard4255d502002-04-16 15:50:10 +00005780 return (ret);
5781}
5782
5783/**
5784 * xmlSchemaParseFacet:
5785 * @ctxt: a schema validation context
5786 * @schema: the schema being built
5787 * @node: a subtree containing XML Schema informations
5788 *
5789 * parse a XML schema Facet declaration
5790 * *WARNING* this interface is highly subject to change
5791 *
5792 * Returns the new type structure or NULL in case of error
5793 */
5794static xmlSchemaFacetPtr
5795xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005796 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005797{
5798 xmlSchemaFacetPtr facet;
5799 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005800 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005801
5802 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5803 return (NULL);
5804
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005805 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005806 if (facet == NULL) {
5807 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5808 return (NULL);
5809 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005810 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005811 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005812 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005813 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5814 "Facet %s has no value\n", node->name, NULL);
5815 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005816 return (NULL);
5817 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005818 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005819 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005820 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005821 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005822 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005823 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005824 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005825 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005826 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005827 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005828 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005829 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005830 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005831 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005832 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005833 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005834 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005835 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005836 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005837 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005838 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005839 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5840 } else if (IS_SCHEMA(node, "minLength")) {
5841 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5842 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005843 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5844 "Unknown facet type %s\n", node->name, NULL);
5845 xmlSchemaFreeFacet(facet);
5846 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005847 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005848 xmlSchemaPValAttrID(ctxt, NULL,
5849 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005850 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005851 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5852 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5853 const xmlChar *fixed;
5854
5855 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5856 if (fixed != NULL) {
5857 if (xmlStrEqual(fixed, BAD_CAST "true"))
5858 facet->fixed = 1;
5859 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005860 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005861 child = node->children;
5862
5863 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005864 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5865 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005866 }
5867 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005868 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5869 "Facet %s has unexpected child content\n",
5870 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005871 }
5872 return (facet);
5873}
5874
5875/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005876 * xmlSchemaParseWildcardNs:
5877 * @ctxt: a schema parser context
5878 * @wildc: the wildcard, already created
5879 * @node: a subtree containing XML Schema informations
5880 *
5881 * Parses the attribute "processContents" and "namespace"
5882 * of a xsd:anyAttribute and xsd:any.
5883 * *WARNING* this interface is highly subject to change
5884 *
5885 * Returns 0 if everything goes fine, a positive error code
5886 * if something is not valid and -1 if an internal error occurs.
5887 */
5888static int
5889xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5890 xmlSchemaPtr schema,
5891 xmlSchemaWildcardPtr wildc,
5892 xmlNodePtr node)
5893{
5894 const xmlChar *pc, *ns, *dictnsItem;
5895 int ret = 0;
5896 xmlChar *nsItem;
5897 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5898 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005899
Daniel Veillardc0826a72004-08-10 14:17:33 +00005900 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5901 if ((pc == NULL)
5902 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5903 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5904 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5905 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5906 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5907 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5908 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005909 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005910 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005911 NULL, node,
5912 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005913 NULL, NULL, NULL);
5914 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005915 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005916 }
5917 /*
5918 * Build the namespace constraints.
5919 */
5920 attr = xmlSchemaGetPropNode(node, "namespace");
5921 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00005922 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005923 wildc->any = 1;
5924 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5925 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005926 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005927 return (-1);
5928 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005929 wildc->negNsSet->value = schema->targetNamespace;
5930 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005931 const xmlChar *end, *cur;
5932
5933 cur = ns;
5934 do {
5935 while (IS_BLANK_CH(*cur))
5936 cur++;
5937 end = cur;
5938 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5939 end++;
5940 if (end == cur)
5941 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005942 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005943 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5944 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005945 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005946 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005947 NULL, (xmlNodePtr) attr,
5948 NULL,
5949 "((##any | ##other) | List of (xs:anyURI | "
5950 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005951 nsItem, NULL, NULL, NULL);
5952 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5953 } else {
5954 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5955 dictnsItem = schema->targetNamespace;
5956 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5957 dictnsItem = NULL;
5958 } else {
5959 /*
5960 * Validate the item (anyURI).
5961 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005962 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005963 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5964 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5965 }
5966 /*
5967 * Avoid dublicate namespaces.
5968 */
5969 tmp = wildc->nsSet;
5970 while (tmp != NULL) {
5971 if (dictnsItem == tmp->value)
5972 break;
5973 tmp = tmp->next;
5974 }
5975 if (tmp == NULL) {
5976 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5977 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005978 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005979 return (-1);
5980 }
5981 tmp->value = dictnsItem;
5982 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005983 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00005984 wildc->nsSet = tmp;
5985 else
5986 lastNs->next = tmp;
5987 lastNs = tmp;
5988 }
5989
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005990 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005991 xmlFree(nsItem);
5992 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005993 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005994 }
5995 return (ret);
5996}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005997
5998static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005999xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6000 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006001 xmlNodePtr node,
6002 int minOccurs,
6003 int maxOccurs) {
6004
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006005 if ((maxOccurs == 0) && ( minOccurs == 0))
6006 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006007 if (maxOccurs != UNBOUNDED) {
6008 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006009 * TODO: Maybe we should better not create the particle,
6010 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006011 * content model.
6012 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006013 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006014 * 3.9.6 Schema Component Constraint: Particle Correct
6015 *
6016 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006017 if (maxOccurs < 1) {
6018 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006019 * 2.2 {max occurs} must be greater than or equal to 1.
6020 */
6021 xmlSchemaPCustomAttrErr(ctxt,
6022 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006023 NULL, NULL,
6024 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006025 "The value must be greater than or equal to 1");
6026 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6027 } else if (minOccurs > maxOccurs) {
6028 /*
6029 * 2.1 {min occurs} must not be greater than {max occurs}.
6030 */
6031 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006032 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006033 NULL, NULL,
6034 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006035 "The value must not be greater than the value of 'maxOccurs'");
6036 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6037 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006038 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006039 return (0);
6040}
6041
Daniel Veillardc0826a72004-08-10 14:17:33 +00006042/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006043 * xmlSchemaParseAny:
6044 * @ctxt: a schema validation context
6045 * @schema: the schema being built
6046 * @node: a subtree containing XML Schema informations
6047 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006048 * Parsea a XML schema <any> element. A particle and wildcard
6049 * will be created (except if minOccurs==maxOccurs==0, in this case
6050 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006051 * *WARNING* this interface is highly subject to change
6052 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006053 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006054 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006055static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006056xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6057 xmlNodePtr node)
6058{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006059 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006060 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006061 xmlSchemaWildcardPtr wild;
6062 int min, max;
6063 xmlAttrPtr attr;
6064 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006065
6066 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6067 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006068 /*
6069 * Check for illegal attributes.
6070 */
6071 attr = node->properties;
6072 while (attr != NULL) {
6073 if (attr->ns == NULL) {
6074 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6075 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6076 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6077 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6078 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006079 xmlSchemaPIllegalAttrErr(ctxt,
6080 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6081 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006082 }
6083 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006084 xmlSchemaPIllegalAttrErr(ctxt,
6085 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6086 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006087 }
6088 attr = attr->next;
6089 }
6090 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6091 /*
6092 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006093 */
6094 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6095 "(xs:nonNegativeInteger | unbounded)");
6096 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6097 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006098 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6099 /*
6100 * Create & parse the wildcard.
6101 */
6102 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6103 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006104 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006105 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006106 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006107 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006108 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006109 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006110 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006111 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006112 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006113 }
6114 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006115 xmlSchemaPContentErr(ctxt,
6116 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006117 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006118 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006119 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006120 /*
6121 * No component if minOccurs==maxOccurs==0.
6122 */
6123 if ((min == 0) && (max == 0)) {
6124 /* Don't free the wildcard, since it's already on the list. */
6125 return (NULL);
6126 }
6127 /*
6128 * Create the particle.
6129 */
6130 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6131 if (particle == NULL)
6132 return (NULL);
6133 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006134 wild->minOccurs = min;
6135 wild->maxOccurs = max;
6136 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006137
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006138 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006139}
6140
6141/**
6142 * xmlSchemaParseNotation:
6143 * @ctxt: a schema validation context
6144 * @schema: the schema being built
6145 * @node: a subtree containing XML Schema informations
6146 *
6147 * parse a XML schema Notation declaration
6148 *
6149 * Returns the new structure or NULL in case of error
6150 */
6151static xmlSchemaNotationPtr
6152xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006153 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006154{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006155 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006156 xmlSchemaNotationPtr ret;
6157 xmlNodePtr child = NULL;
6158
6159 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6160 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006161 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006162 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006163 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6164 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006165 return (NULL);
6166 }
6167 ret = xmlSchemaAddNotation(ctxt, schema, name);
6168 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006169 return (NULL);
6170 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006171 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006172
6173 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6174 node, BAD_CAST "id");
6175
6176 if (IS_SCHEMA(child, "annotation")) {
6177 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6178 child = child->next;
6179 }
6180
Daniel Veillard4255d502002-04-16 15:50:10 +00006181 child = node->children;
6182 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006183 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6184 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006185 }
6186 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006187 xmlSchemaPContentErr(ctxt,
6188 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006189 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006190 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006191 }
6192
6193 return (ret);
6194}
6195
6196/**
6197 * xmlSchemaParseAnyAttribute:
6198 * @ctxt: a schema validation context
6199 * @schema: the schema being built
6200 * @node: a subtree containing XML Schema informations
6201 *
6202 * parse a XML schema AnyAttrribute declaration
6203 * *WARNING* this interface is highly subject to change
6204 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006205 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006206 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006207static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006208xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6209 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006210{
Daniel Veillard3646d642004-06-02 19:19:14 +00006211 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006212 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006213 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006214
6215 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6216 return (NULL);
6217
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006218 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6219 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006220 if (ret == NULL) {
6221 return (NULL);
6222 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006223 /*
6224 * Check for illegal attributes.
6225 */
6226 attr = node->properties;
6227 while (attr != NULL) {
6228 if (attr->ns == NULL) {
6229 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6230 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6231 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006232 xmlSchemaPIllegalAttrErr(ctxt,
6233 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6234 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006235 }
6236 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006237 xmlSchemaPIllegalAttrErr(ctxt,
6238 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6239 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006240 }
6241 attr = attr->next;
6242 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006243 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6244 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006245 /*
6246 * Parse the namespace list.
6247 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006248 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006249 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006250 /*
6251 * And now for the children...
6252 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006253 child = node->children;
6254 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006255 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6256 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006257 }
6258 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006259 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006260 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006261 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006262 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006263 }
6264
6265 return (ret);
6266}
6267
6268
6269/**
6270 * xmlSchemaParseAttribute:
6271 * @ctxt: a schema validation context
6272 * @schema: the schema being built
6273 * @node: a subtree containing XML Schema informations
6274 *
6275 * parse a XML schema Attrribute declaration
6276 * *WARNING* this interface is highly subject to change
6277 *
William M. Bracke7091952004-05-11 15:09:58 +00006278 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006279 */
6280static xmlSchemaAttributePtr
6281xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006282 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006283{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006284 const xmlChar *name, *attrValue;
6285 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006286 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006287 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006288 xmlAttrPtr attr, nameAttr;
6289 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006290
6291 /*
6292 * Note that the w3c spec assumes the schema to be validated with schema
6293 * for schemas beforehand.
6294 *
6295 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006296 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006297
6298 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6299 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006300 attr = xmlSchemaGetPropNode(node, "ref");
6301 nameAttr = xmlSchemaGetPropNode(node, "name");
6302
6303 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006304 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006305 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006306 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006307 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006308 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6309 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006310 "One of the attributes 'ref' or 'name' must be present");
6311 return (NULL);
6312 }
6313 if ((topLevel) || (attr == NULL)) {
6314 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006315 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6316 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006317 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006318 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006319 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006320 isRef = 1;
6321
Daniel Veillardc0826a72004-08-10 14:17:33 +00006322 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006323 char buf[50];
6324 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006325
6326 /*
6327 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006328 */
6329 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6330 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6331 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006332 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006333 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006334 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006335 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006336 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006337 if (ret == NULL) {
6338 if (repName != NULL)
6339 xmlFree(repName);
6340 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006341 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006342 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6343 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006344 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006345 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006346 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6347 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006348 /*
6349 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6350 */
6351 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006352 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6353 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006354 "ref", "name");
6355 /*
6356 * Check for illegal attributes.
6357 */
6358 attr = node->properties;
6359 while (attr != NULL) {
6360 if (attr->ns == NULL) {
6361 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6362 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006363 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006364 * 3.2.3 : 3.2
6365 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006366 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006367 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006368 xmlSchemaPIllegalAttrErr(ctxt,
6369 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006370 (xmlSchemaTypePtr) ret, attr);
6371 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6372 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6373 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006374 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6375 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006376 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006377 xmlSchemaPIllegalAttrErr(ctxt,
6378 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6379 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006380 }
6381 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006382 xmlSchemaPIllegalAttrErr(ctxt,
6383 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6384 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006385 }
6386 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006387 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006388 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006389 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006390
Daniel Veillardc0826a72004-08-10 14:17:33 +00006391 /*
6392 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006393 */
6394 if (xmlSchemaPValAttrNode(ctxt,
6395 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006396 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6397 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006398 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006399 /*
6400 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6401 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006402 /*
6403 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6404 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006405 */
6406 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006407 xmlSchemaPSimpleTypeErr(ctxt,
6408 XML_SCHEMAP_NO_XMLNS,
6409 NULL, (xmlNodePtr) nameAttr,
6410 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6411 "The value of type 'xs:NCName' must not match 'xmlns'",
6412 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006413 if (repName != NULL)
6414 xmlFree(repName);
6415 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006416 }
6417 /*
6418 * Evaluate the target namespace
6419 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006420 if (topLevel) {
6421 ns = schema->targetNamespace;
6422 } else {
6423 attr = xmlSchemaGetPropNode(node, "form");
6424 if (attr != NULL) {
6425 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6426 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6427 ns = schema->targetNamespace;
6428 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006429 xmlSchemaPSimpleTypeErr(ctxt,
6430 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6431 NULL, (xmlNodePtr) attr,
6432 NULL, "(qualified | unqualified)",
6433 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006434 }
6435 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006436 ns = schema->targetNamespace;
6437 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006438 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006439 if (ret == NULL) {
6440 if (repName != NULL)
6441 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006442 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006443 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006444 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006445 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006446 if (topLevel)
6447 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006448 /*
6449 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6450 * TODO: Move this to the component layer.
6451 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006452 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006453 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006454 XML_SCHEMAP_NO_XSI,
6455 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006456 "The target namespace must not match '%s'",
6457 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006458 }
6459 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006460 * Check for illegal attributes.
6461 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006462 attr = node->properties;
6463 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006464 if (attr->ns == NULL) {
6465 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6466 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6467 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006468 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6469 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006470 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006471 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6472 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006473 xmlSchemaPIllegalAttrErr(ctxt,
6474 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6475 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006476 }
6477 }
6478 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006479 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6480 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006481 }
6482 attr = attr->next;
6483 }
6484 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006485 node, "type", &ret->typeNs, &ret->typeName);
6486 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006487 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6488 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006489 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006490 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006491 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006492 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6493 if (ret->defValue != NULL)
6494 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006495 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006496 * Attribute "default".
6497 */
6498 attr = xmlSchemaGetPropNode(node, "default");
6499 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006500 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006501 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006502 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006503 */
6504 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6505 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6506 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6507 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006508 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6509 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006510 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006511 /*
6512 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006513 */
6514 attr = xmlSchemaGetPropNode(node, "use");
6515 if (attr != NULL) {
6516 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6517 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6518 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6519 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6520 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6521 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6522 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6523 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006524 xmlSchemaPSimpleTypeErr(ctxt,
6525 XML_SCHEMAP_INVALID_ATTR_USE,
6526 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6527 NULL, "(optional | prohibited | required)",
6528 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006529 } else
6530 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006531 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006532 * 3.2.3 : 2
6533 * If default and use are both present, use must have
6534 * the actual value optional.
6535 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006536 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6537 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006538 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006539 xmlSchemaPSimpleTypeErr(ctxt,
6540 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6541 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6542 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006543 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006544 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006545 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006546 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006547 /*
6548 * And now for the children...
6549 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006550 child = node->children;
6551 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006552 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6553 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006554 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006555 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006556 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006557 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006558 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006559 * 3.2.3 : 3.2
6560 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006561 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006562 */
6563 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6564 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6565 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006566 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006567 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6568 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006569 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006570 }
6571 } else {
6572 if (IS_SCHEMA(child, "simpleType")) {
6573 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006574 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006575 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006576 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006577 */
6578 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6579 &repName, (xmlSchemaTypePtr) ret, node, child,
6580 "The attribute 'type' and the <simpleType> child "
6581 "are mutually exclusive", NULL);
6582 } else
6583 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6584 child = child->next;
6585 }
6586 if (child != NULL)
6587 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6588 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6589 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006590 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006591 /*
6592 * Cleanup.
6593 */
6594 if (repName != NULL)
6595 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006596 return (ret);
6597}
6598
6599/**
6600 * xmlSchemaParseAttributeGroup:
6601 * @ctxt: a schema validation context
6602 * @schema: the schema being built
6603 * @node: a subtree containing XML Schema informations
6604 *
6605 * parse a XML schema Attribute Group declaration
6606 * *WARNING* this interface is highly subject to change
6607 *
6608 * Returns the attribute group or NULL in case of error.
6609 */
6610static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006611xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006612 xmlSchemaPtr schema, xmlNodePtr node,
6613 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006614{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006615 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006616 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006617 xmlNodePtr child = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006618 const xmlChar *oldcontainer;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006619 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006620
6621 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6622 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006623
6624 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006625 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006626 if ((topLevel) || (attr == NULL)) {
6627 /*
6628 * Parse as an attribute group definition.
6629 * Note that those are allowed at top level only.
6630 */
6631 if (nameAttr == NULL) {
6632 xmlSchemaPMissingAttrErr(ctxt,
6633 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006634 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006635 return (NULL);
6636 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006637 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006638 * (xmlNodePtr) nameAttr);
6639 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006640 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006641 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006642 */
6643 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006644 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006645 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6646 return (NULL);
6647 }
6648 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6649 if (ret == NULL)
6650 return (NULL);
6651 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6652 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6653 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006654 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006655 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006656 char buf[50];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006657 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006658
6659 /*
6660 * Parse as an attribute group definition reference.
6661 */
6662 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006663 xmlSchemaPMissingAttrErr(ctxt,
6664 XML_SCHEMAP_S4S_ATTR_MISSING,
6665 NULL, node, "ref", NULL);
6666 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006667 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006668 NULL, NULL, attr, &refNs,&ref);
6669
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006670 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006671 name = (const xmlChar *) buf;
6672 if (name == NULL) {
6673 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6674 "attribute group definition reference", node);
6675 return (NULL);
6676 }
6677 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6678 if (ret == NULL)
6679 return (NULL);
6680 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6681 ret->ref = ref;
6682 ret->refNs = refNs;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006683 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006684 xmlSchemaCheckReference(ctxt, schema, node,
6685 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006686 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006687 /*
6688 * Check for illegal attributes.
6689 */
6690 attr = node->properties;
6691 while (attr != NULL) {
6692 if (attr->ns == NULL) {
6693 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6694 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006695 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006696 {
6697 xmlSchemaPIllegalAttrErr(ctxt,
6698 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6699 NULL, NULL, attr);
6700 }
6701 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6702 xmlSchemaPIllegalAttrErr(ctxt,
6703 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6704 NULL, NULL, attr);
6705 }
6706 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006707 }
6708 /* TODO: Validate "id" ? */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006709 /*
6710 * And now for the children...
6711 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006712 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006713 ctxt->container = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006714 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006715 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006716 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6717 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006718 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006719 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006720 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006721 if (IS_SCHEMA(child, "anyAttribute")) {
6722 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6723 child = child->next;
6724 }
6725 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006726 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006727 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006728 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6729 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006730 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006731 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006732 ctxt->container = oldcontainer;
6733 return (ret);
6734}
6735
6736/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006737 * xmlSchemaPValAttrFormDefault:
6738 * @value: the value
6739 * @flags: the flags to be modified
6740 * @flagQualified: the specific flag for "qualified"
6741 *
6742 * Returns 0 if the value is valid, 1 otherwise.
6743 */
6744static int
6745xmlSchemaPValAttrFormDefault(const xmlChar *value,
6746 int *flags,
6747 int flagQualified)
6748{
6749 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6750 if ((*flags & flagQualified) == 0)
6751 *flags |= flagQualified;
6752 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006753 return (1);
6754
William M. Brack2f2a6632004-08-20 23:09:47 +00006755 return (0);
6756}
6757
6758/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006759 * xmlSchemaPValAttrBlockFinal:
6760 * @value: the value
6761 * @flags: the flags to be modified
6762 * @flagAll: the specific flag for "#all"
6763 * @flagExtension: the specific flag for "extension"
6764 * @flagRestriction: the specific flag for "restriction"
6765 * @flagSubstitution: the specific flag for "substitution"
6766 * @flagList: the specific flag for "list"
6767 * @flagUnion: the specific flag for "union"
6768 *
6769 * Validates the value of the attribute "final" and "block". The value
6770 * is converted into the specified flag values and returned in @flags.
6771 *
6772 * Returns 0 if the value is valid, 1 otherwise.
6773 */
6774
6775static int
6776xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006777 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006778 int flagAll,
6779 int flagExtension,
6780 int flagRestriction,
6781 int flagSubstitution,
6782 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006783 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006784{
6785 int ret = 0;
6786
6787 /*
6788 * TODO: This does not check for dublicate entries.
6789 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006790 if ((flags == NULL) || (value == NULL))
6791 return (-1);
6792 if (value[0] == 0)
6793 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006794 if (xmlStrEqual(value, BAD_CAST "#all")) {
6795 if (flagAll != -1)
6796 *flags |= flagAll;
6797 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006798 if (flagExtension != -1)
6799 *flags |= flagExtension;
6800 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006801 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006802 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006803 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006804 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006805 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006806 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006807 *flags |= flagUnion;
6808 }
6809 } else {
6810 const xmlChar *end, *cur = value;
6811 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006812
Daniel Veillardc0826a72004-08-10 14:17:33 +00006813 do {
6814 while (IS_BLANK_CH(*cur))
6815 cur++;
6816 end = cur;
6817 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6818 end++;
6819 if (end == cur)
6820 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006821 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006822 if (xmlStrEqual(item, BAD_CAST "extension")) {
6823 if (flagExtension != -1) {
6824 if ((*flags & flagExtension) == 0)
6825 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006826 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006827 ret = 1;
6828 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6829 if (flagRestriction != -1) {
6830 if ((*flags & flagRestriction) == 0)
6831 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006832 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006833 ret = 1;
6834 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6835 if (flagSubstitution != -1) {
6836 if ((*flags & flagSubstitution) == 0)
6837 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006838 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006839 ret = 1;
6840 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6841 if (flagList != -1) {
6842 if ((*flags & flagList) == 0)
6843 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006844 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006845 ret = 1;
6846 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6847 if (flagUnion != -1) {
6848 if ((*flags & flagUnion) == 0)
6849 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006850 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006851 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006852 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006853 ret = 1;
6854 if (item != NULL)
6855 xmlFree(item);
6856 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006857 } while ((ret == 0) && (*cur != 0));
6858 }
6859
Daniel Veillardc0826a72004-08-10 14:17:33 +00006860 return (ret);
6861}
6862
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006863static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006864xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006865 xmlSchemaIDCPtr idc,
6866 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006867 xmlAttrPtr attr,
6868 int isField)
6869{
6870 xmlNodePtr node;
6871
6872 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006873 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006874 * Schema Component Constraint: Selector Value OK
6875 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006876 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006877 * in [XPath].
6878 */
6879 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006880 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006881 XML_SCHEMAP_INTERNAL,
6882 "Internal error: xmlSchemaCheckCSelectorXPath, "
6883 "the selector is not specified.\n", NULL, NULL);
6884 return (-1);
6885 }
6886 if (attr == NULL)
6887 node = idc->node;
6888 else
6889 node = (xmlNodePtr) attr;
6890 if (selector->xpath == NULL) {
6891 xmlSchemaPCustomErr(ctxt,
6892 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006893 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6894 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006895 "The XPath expression of the selector is not valid", NULL);
6896 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6897 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006898 const xmlChar **nsArray = NULL;
6899 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006900 /*
6901 * Compile the XPath expression.
6902 */
6903 /*
6904 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006905 * TODO: Call xmlPatterncompile with different options for selector/
6906 * field.
6907 */
6908 nsList = xmlGetNsList(attr->doc, attr->parent);
6909 /*
6910 * Build an array of prefixes and namespaces.
6911 */
6912 if (nsList != NULL) {
6913 int i, count = 0;
6914 xmlNsPtr ns;
6915
6916 for (i = 0; nsList[i] != NULL; i++)
6917 count++;
6918
6919 nsArray = (const xmlChar **) xmlMalloc(
6920 (count * 2 + 1) * sizeof(const xmlChar *));
6921 if (nsArray == NULL) {
6922 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6923 NULL);
6924 return (-1);
6925 }
6926 for (i = 0; i < count; i++) {
6927 ns = nsList[i];
6928 nsArray[2 * i] = nsList[i]->href;
6929 nsArray[2 * i + 1] = nsList[i]->prefix;
6930 }
6931 nsArray[count * 2] = NULL;
6932 xmlFree(nsList);
6933 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006934 /*
6935 * TODO: Differentiate between "selector" and "field".
6936 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006937 if (isField)
6938 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006939 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006940 else
6941 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006942 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006943 if (nsArray != NULL)
6944 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006945
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006946 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006947 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006948 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006949 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6950 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006951 "The XPath expression '%s' could not be "
6952 "compiled", selector->xpath);
6953 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006954 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006955 }
6956 return (0);
6957}
6958
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006959#define ADD_ANNOTATION(annot) \
6960 xmlSchemaAnnotPtr cur = item->annot; \
6961 if (item->annot == NULL) { \
6962 item->annot = annot; \
6963 return (annot); \
6964 } \
6965 cur = item->annot; \
6966 if (cur->next != NULL) { \
6967 cur = cur->next; \
6968 } \
6969 cur->next = annot;
6970
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006971/**
6972 * xmlSchemaAssignAnnotation:
6973 * @item: the schema component
6974 * @annot: the annotation
6975 *
6976 * Adds the annotation to the given schema component.
6977 *
6978 * Returns the given annotaion.
6979 */
6980static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006981xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
6982 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006983{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006984 if ((annItem == NULL) || (annot == NULL))
6985 return (NULL);
6986 switch (annItem->type) {
6987 case XML_SCHEMA_TYPE_ELEMENT: {
6988 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
6989 ADD_ANNOTATION(annot)
6990 }
6991 break;
6992 case XML_SCHEMA_TYPE_ATTRIBUTE: {
6993 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
6994 ADD_ANNOTATION(annot)
6995 }
6996 break;
6997 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
6998 case XML_SCHEMA_TYPE_ANY: {
6999 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
7000 ADD_ANNOTATION(annot)
7001 }
7002 break;
7003 case XML_SCHEMA_TYPE_PARTICLE:
7004 case XML_SCHEMA_TYPE_IDC_KEY:
7005 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007006 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007007 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
7008 ADD_ANNOTATION(annot)
7009 }
7010 break;
7011 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
7012 xmlSchemaAttributeGroupPtr item =
7013 (xmlSchemaAttributeGroupPtr) annItem;
7014 ADD_ANNOTATION(annot)
7015 }
7016 break;
7017 case XML_SCHEMA_TYPE_NOTATION: {
7018 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7019 ADD_ANNOTATION(annot)
7020 }
7021 break;
7022 case XML_SCHEMA_FACET_MININCLUSIVE:
7023 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7024 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7025 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7026 case XML_SCHEMA_FACET_TOTALDIGITS:
7027 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7028 case XML_SCHEMA_FACET_PATTERN:
7029 case XML_SCHEMA_FACET_ENUMERATION:
7030 case XML_SCHEMA_FACET_WHITESPACE:
7031 case XML_SCHEMA_FACET_LENGTH:
7032 case XML_SCHEMA_FACET_MAXLENGTH:
7033 case XML_SCHEMA_FACET_MINLENGTH: {
7034 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7035 ADD_ANNOTATION(annot)
7036 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007037 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007038 case XML_SCHEMA_TYPE_SIMPLE:
7039 case XML_SCHEMA_TYPE_COMPLEX: {
7040 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7041 ADD_ANNOTATION(annot)
7042 }
7043 break;
7044 case XML_SCHEMA_TYPE_GROUP: {
7045 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7046 ADD_ANNOTATION(annot)
7047 }
7048 break;
7049 case XML_SCHEMA_TYPE_SEQUENCE:
7050 case XML_SCHEMA_TYPE_CHOICE:
7051 case XML_SCHEMA_TYPE_ALL: {
7052 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7053 ADD_ANNOTATION(annot)
7054 }
7055 break;
7056 default:
7057 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007058 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007059 NULL, NULL, NULL,
7060 "Internal error: xmlSchemaAddAnnotation, "
7061 "The item is not a annotated schema component", NULL);
7062 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007063 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007064 return (annot);
7065}
7066
7067/**
7068 * xmlSchemaParseIDCSelectorAndField:
7069 * @ctxt: a schema validation context
7070 * @schema: the schema being built
7071 * @node: a subtree containing XML Schema informations
7072 *
7073 * Parses a XML Schema identity-contraint definition's
7074 * <selector> and <field> elements.
7075 *
7076 * Returns the parsed identity-constraint definition.
7077 */
7078static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007079xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007080 xmlSchemaPtr schema,
7081 xmlSchemaIDCPtr idc,
7082 xmlNodePtr node,
7083 int isField)
7084{
7085 xmlSchemaIDCSelectPtr item;
7086 xmlNodePtr child = NULL;
7087 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007088
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007089 /*
7090 * Check for illegal attributes.
7091 */
7092 attr = node->properties;
7093 while (attr != NULL) {
7094 if (attr->ns == NULL) {
7095 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7096 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007097 xmlSchemaPIllegalAttrErr(ctxt,
7098 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7099 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007100 }
7101 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007102 xmlSchemaPIllegalAttrErr(ctxt,
7103 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7104 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007105 }
7106 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007107 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007108 /*
7109 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007110 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007111 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7112 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007113 xmlSchemaPErrMemory(ctxt,
7114 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007115 NULL);
7116 return (NULL);
7117 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007118 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007119 /*
7120 * Attribute "xpath" (mandatory).
7121 */
7122 attr = xmlSchemaGetPropNode(node, "xpath");
7123 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007124 xmlSchemaPMissingAttrErr(ctxt,
7125 XML_SCHEMAP_S4S_ATTR_MISSING,
7126 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007127 "name", NULL);
7128 } else {
7129 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7130 /*
7131 * URGENT TODO: "field"s have an other syntax than "selector"s.
7132 */
7133
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007134 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7135 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007136 xmlSchemaPErr(ctxt,
7137 (xmlNodePtr) attr,
7138 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007139 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007140 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007141 NULL, NULL);
7142 }
7143
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007144 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007145 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007146 /*
7147 * And now for the children...
7148 */
7149 child = node->children;
7150 if (IS_SCHEMA(child, "annotation")) {
7151 /*
7152 * Add the annotation to the parent IDC.
7153 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007154 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007155 xmlSchemaParseAnnotation(ctxt, schema, child));
7156 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007157 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007158 if (child != NULL) {
7159 xmlSchemaPContentErr(ctxt,
7160 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007161 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007162 NULL, "(annotation?)");
7163 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007164
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007165 return (item);
7166}
7167
7168/**
7169 * xmlSchemaParseIDC:
7170 * @ctxt: a schema validation context
7171 * @schema: the schema being built
7172 * @node: a subtree containing XML Schema informations
7173 *
7174 * Parses a XML Schema identity-contraint definition.
7175 *
7176 * Returns the parsed identity-constraint definition.
7177 */
7178static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007179xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007180 xmlSchemaPtr schema,
7181 xmlNodePtr node,
7182 xmlSchemaTypeType idcCategory,
7183 const xmlChar *targetNamespace)
7184{
7185 xmlSchemaIDCPtr item = NULL;
7186 xmlNodePtr child = NULL;
7187 xmlAttrPtr attr;
7188 const xmlChar *name = NULL;
7189 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7190 int resAdd;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007191
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007192 /*
7193 * Check for illegal attributes.
7194 */
7195 attr = node->properties;
7196 while (attr != NULL) {
7197 if (attr->ns == NULL) {
7198 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7199 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7200 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7201 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007202 xmlSchemaPIllegalAttrErr(ctxt,
7203 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7204 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007205 }
7206 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007207 xmlSchemaPIllegalAttrErr(ctxt,
7208 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7209 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007210 }
7211 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007212 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007213 /*
7214 * Attribute "name" (mandatory).
7215 */
7216 attr = xmlSchemaGetPropNode(node, "name");
7217 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007218 xmlSchemaPMissingAttrErr(ctxt,
7219 XML_SCHEMAP_S4S_ATTR_MISSING,
7220 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007221 "name", NULL);
7222 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007223 } else if (xmlSchemaPValAttrNode(ctxt,
7224 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007225 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7226 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007227 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007228 /*
7229 * Create the component.
7230 */
7231 if (schema->idcDef == NULL)
7232 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007233 if (schema->idcDef == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007234 return (NULL);
7235
7236 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7237 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007238 xmlSchemaPErrMemory(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007239 "allocating an identity-constraint definition", NULL);
7240 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007241 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007242 /*
7243 * Add the IDC to the list of IDCs on the schema component.
7244 */
7245 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007246 if (resAdd != 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007247 xmlSchemaPCustomErrExt(ctxt,
7248 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007249 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007250 "An identity-constraint definition with the name '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007251 "and targetNamespace '%s' does already exist",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007252 name, targetNamespace, NULL);
7253 xmlFree(item);
7254 return (NULL);
7255 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007256 memset(item, 0, sizeof(xmlSchemaIDC));
7257 item->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007258 item->type = idcCategory;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007259 item->node = node;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +00007260 if (ctxt->assemble != NULL)
7261 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007262 /*
7263 * The target namespace of the parent element declaration.
7264 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007265 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007266 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7267 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007268 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7269 /*
7270 * Attribute "refer" (mandatory).
7271 */
7272 attr = xmlSchemaGetPropNode(node, "refer");
7273 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007274 xmlSchemaPMissingAttrErr(ctxt,
7275 XML_SCHEMAP_S4S_ATTR_MISSING,
7276 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007277 "refer", NULL);
7278 } else {
7279 /*
7280 * Create a reference item.
7281 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007282 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007283 NULL, NULL);
7284 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007285 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007286 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007287 NULL, NULL, attr,
7288 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007289 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007290 xmlSchemaCheckReference(ctxt, schema, node,
7291 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007292 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007293 }
7294 }
7295 /*
7296 * And now for the children...
7297 */
7298 child = node->children;
7299 if (IS_SCHEMA(child, "annotation")) {
7300 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7301 child = child->next;
7302 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007303 if (child == NULL) {
7304 xmlSchemaPContentErr(ctxt,
7305 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007306 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007307 "A child element is missing",
7308 "(annotation?, (selector, field+))");
7309 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007310 /*
7311 * Child element <selector>.
7312 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007313 if (IS_SCHEMA(child, "selector")) {
7314 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007315 item, child, 0);
7316 child = child->next;
7317 /*
7318 * Child elements <field>.
7319 */
7320 if (IS_SCHEMA(child, "field")) {
7321 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007322 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007323 item, child, 1);
7324 if (field != NULL) {
7325 field->index = item->nbFields;
7326 item->nbFields++;
7327 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007328 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007329 else
7330 item->fields = field;
7331 lastField = field;
7332 }
7333 child = child->next;
7334 } while (IS_SCHEMA(child, "field"));
7335 } else {
7336 xmlSchemaPContentErr(ctxt,
7337 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007338 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007339 NULL, "(annotation?, (selector, field+))");
7340 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007341 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007342 if (child != NULL) {
7343 xmlSchemaPContentErr(ctxt,
7344 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007345 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007346 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007347 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007348
7349 return (item);
7350}
7351
Daniel Veillardc0826a72004-08-10 14:17:33 +00007352/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007353 * xmlSchemaParseElement:
7354 * @ctxt: a schema validation context
7355 * @schema: the schema being built
7356 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007357 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007358 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007359 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007360 * *WARNING* this interface is highly subject to change
7361 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007362 * Returns the element declaration or a particle; NULL in case
7363 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007364 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007365static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007366xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007367 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007368{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007369 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007370 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007371 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007372 xmlNodePtr child = NULL;
7373 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007374 int min, max, isRef = 0;
7375 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007376
7377 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7378 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007379
Daniel Veillard4255d502002-04-16 15:50:10 +00007380 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007381 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007382 /*
7383 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007384 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007385 * robust.
7386 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007387 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007388 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007389 if ((topLevel) || (attr == NULL)) {
7390 if (nameAttr == NULL) {
7391 xmlSchemaPMissingAttrErr(ctxt,
7392 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007393 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007394 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007395 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007396 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007397 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007398
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007399 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007400 child = node->children;
7401 if (IS_SCHEMA(child, "annotation")) {
7402 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7403 child = child->next;
7404 }
7405 /*
7406 * Skip particle part if a global declaration.
7407 */
7408 if (topLevel)
7409 goto declaration_part;
7410 /*
7411 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007412 */
7413 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7414 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7415 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007416 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7417 if (particle == NULL)
7418 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007419
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007420 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7421
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007422 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007423 const xmlChar *refNs = NULL, *ref = NULL;
7424 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007425 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007426 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007427 */
7428 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007429 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007430 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007431 /*
7432 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007433 */
7434 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007435 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007436 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007437 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007438 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007439 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007440 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007441 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007442 attr = node->properties;
7443 while (attr != NULL) {
7444 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007445 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7446 xmlStrEqual(attr->name, BAD_CAST "name") ||
7447 xmlStrEqual(attr->name, BAD_CAST "id") ||
7448 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7449 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7450 {
7451 attr = attr->next;
7452 continue;
7453 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007454 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007455 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007456 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007457 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007458 "Only the attributes 'minOccurs', 'maxOccurs' and "
7459 "'id' are allowed in addition to 'ref'");
7460 break;
7461 }
7462 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7463 xmlSchemaPIllegalAttrErr(ctxt,
7464 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007465 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007466 }
7467 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007468 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007469 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007470 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007471 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007472 if (child != NULL) {
7473 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7474 NULL, NULL, node, child, NULL, "(annotation?)");
7475 }
7476 if ((min == 0) && (max == 0))
7477 goto return_null;
7478 /*
7479 * Create the reference item.
7480 */
7481 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7482 ref, refNs);
7483 if (refer == NULL)
7484 goto return_null;
7485 particle->children = (xmlSchemaTreeItemPtr) refer;
7486 particle->annot = annot;
7487 /*
7488 * Add to assembled items; the reference need to be resolved.
7489 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007490 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007491 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7492
7493 return ((xmlSchemaBasicItemPtr) particle);
7494 }
7495 /*
7496 * The declaration part ===============================================
7497 */
7498declaration_part:
7499 {
7500 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7501 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7502
7503 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007504 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007505 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007506 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007507 * Evaluate the target namespace.
7508 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007509 if (topLevel) {
7510 ns = schema->targetNamespace;
7511 } else {
7512 attr = xmlSchemaGetPropNode(node, "form");
7513 if (attr != NULL) {
7514 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7515 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007516 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007517 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007518 xmlSchemaPSimpleTypeErr(ctxt,
7519 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7520 NULL, (xmlNodePtr) attr,
7521 NULL, "(qualified | unqualified)",
7522 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007523 }
7524 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007525 ns = schema->targetNamespace;
7526 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007527 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007528 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007529 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007530 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007531 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7532 decl->node = node;
7533 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007534 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007535 * Check for illegal attributes.
7536 */
William M. Bracke7091952004-05-11 15:09:58 +00007537 attr = node->properties;
7538 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007539 if (attr->ns == NULL) {
7540 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7541 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007542 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007543 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007544 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007545 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007546 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7547 {
7548 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007549 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007550 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007551 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007552 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007553 xmlSchemaPIllegalAttrErr(ctxt,
7554 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7555 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007556 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007557 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7558 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007559 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7560
7561 xmlSchemaPIllegalAttrErr(ctxt,
7562 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007563 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007564 }
7565 }
7566 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007567
Daniel Veillardc0826a72004-08-10 14:17:33 +00007568 xmlSchemaPIllegalAttrErr(ctxt,
7569 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007570 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007571 }
7572 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007573 }
William M. Bracke7091952004-05-11 15:09:58 +00007574 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007575 * Extract/validate attributes.
7576 */
7577 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007578 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007579 * Process top attributes of global element declarations here.
7580 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007581 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7582 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007583 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7584 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7585 &(decl->substGroupNs), &(decl->substGroup));
7586 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007587 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007588 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007589 /*
7590 * Attribute "final".
7591 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007592 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007593 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007594 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7595 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7596 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7597 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007598 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007599 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7600 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007601 -1,
7602 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7603 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007604 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007605 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007606 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7607 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007608 attrValue, NULL, NULL, NULL);
7609 }
7610 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007611 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007612 /*
7613 * Attribute "block".
7614 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007615 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007616 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007617 /*
7618 * Apply default "block" values.
7619 */
7620 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7621 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7622 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7623 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7624 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7625 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007626 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007627 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7628 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007629 -1,
7630 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007631 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007632 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7633 xmlSchemaPSimpleTypeErr(ctxt,
7634 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007635 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007636 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007637 "restriction | substitution))", attrValue,
7638 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007639 }
7640 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007641 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007642 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007643 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007644
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007645 attr = xmlSchemaGetPropNode(node, "type");
7646 if (attr != NULL) {
7647 xmlSchemaPValAttrNodeQName(ctxt, schema,
7648 NULL, (xmlSchemaTypePtr) decl, attr,
7649 &(decl->namedTypeNs), &(decl->namedType));
7650 xmlSchemaCheckReference(ctxt, schema, node,
7651 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7652 }
7653 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7654 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007655 if (attr != NULL) {
7656 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007657 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007658 /*
7659 * 3.3.3 : 1
7660 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007661 */
7662 xmlSchemaPMutualExclAttrErr(ctxt,
7663 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007664 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007665 "default", "fixed");
7666 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007667 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7668 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007669 }
William M. Bracke7091952004-05-11 15:09:58 +00007670 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007671 /*
7672 * And now for the children...
7673 */
7674 oldcontainer = ctxt->container;
7675 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007676 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007677 /*
7678 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007679 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007680 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007681 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007682 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007683 xmlSchemaPContentErr(ctxt,
7684 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007685 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007686 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007687 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007688 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007689 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007690 child = child->next;
7691 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007692 /*
7693 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007694 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007695 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007696 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007697 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007698 xmlSchemaPContentErr(ctxt,
7699 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007700 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007701 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007702 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007703 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007704 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007705 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007706 }
William M. Bracke7091952004-05-11 15:09:58 +00007707 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007708 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007709 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007710 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007711 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007712 } else if (IS_SCHEMA(child, "key")) {
7713 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007714 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007715 } else if (IS_SCHEMA(child, "keyref")) {
7716 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007717 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007718 }
7719 if (lastIDC != NULL)
7720 lastIDC->next = curIDC;
7721 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007722 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007723 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007724 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007725 }
7726 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007727 xmlSchemaPContentErr(ctxt,
7728 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007729 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007730 NULL, "(annotation?, ((simpleType | complexType)?, "
7731 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007732 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007733 ctxt->container = oldcontainer;
7734 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007735 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007736 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007737 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007738 * different layer.
7739 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007740 FREE_AND_NULL(des)
7741 if (topLevel)
7742 return ((xmlSchemaBasicItemPtr) decl);
7743 else {
7744 particle->children = (xmlSchemaTreeItemPtr) decl;
7745 return ((xmlSchemaBasicItemPtr) particle);
7746 }
7747
7748return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007749 FREE_AND_NULL(des);
7750 if (annot != NULL) {
7751 if (particle != NULL)
7752 particle->annot = NULL;
7753 if (decl != NULL)
7754 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007755 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007756 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007757 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007758}
7759
7760/**
7761 * xmlSchemaParseUnion:
7762 * @ctxt: a schema validation context
7763 * @schema: the schema being built
7764 * @node: a subtree containing XML Schema informations
7765 *
7766 * parse a XML schema Union definition
7767 * *WARNING* this interface is highly subject to change
7768 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007769 * Returns -1 in case of internal error, 0 in case of success and a positive
7770 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007771 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007772static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007773xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007774 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007775{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007776 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007777 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007778 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007779 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007780
7781 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007782 return (-1);
7783 /* Not a component, don't create it. */
7784 type = ctxt->ctxtType;
7785 /*
7786 * Mark the simple type as being of variety "union".
7787 */
7788 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007789 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007790 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7791 * then the ·simple ur-type definition·."
7792 */
7793 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007794 /*
7795 * Check for illegal attributes.
7796 */
7797 attr = node->properties;
7798 while (attr != NULL) {
7799 if (attr->ns == NULL) {
7800 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7801 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007802 xmlSchemaPIllegalAttrErr(ctxt,
7803 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7804 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007805 }
7806 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007807 xmlSchemaPIllegalAttrErr(ctxt,
7808 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7809 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007810 }
7811 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007812 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007813 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007814 /*
7815 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007816 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007817 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007818 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007819 if (attr != NULL) {
7820 const xmlChar *end;
7821 xmlChar *tmp;
7822 const xmlChar *localName, *nsName;
7823 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7824 xmlSchemaQNameRefPtr ref;
7825
7826 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007827 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007828 do {
7829 while (IS_BLANK_CH(*cur))
7830 cur++;
7831 end = cur;
7832 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7833 end++;
7834 if (end == cur)
7835 break;
7836 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007837 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7838 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007839 /*
7840 * Create the member type link.
7841 */
7842 link = (xmlSchemaTypeLinkPtr)
7843 xmlMalloc(sizeof(xmlSchemaTypeLink));
7844 if (link == NULL) {
7845 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7846 "allocating a type link", NULL);
7847 return (-1);
7848 }
7849 link->type = NULL;
7850 link->next = NULL;
7851 if (lastLink == NULL)
7852 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007853 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007854 lastLink->next = link;
7855 lastLink = link;
7856 /*
7857 * Create a reference item.
7858 */
7859 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
7860 localName, nsName);
7861 if (ref == NULL) {
7862 FREE_AND_NULL(tmp)
7863 return (-1);
7864 }
7865 /*
7866 * Assign the reference to the link, it will be resolved
7867 * later during fixup of the union simple type.
7868 */
7869 link->type = (xmlSchemaTypePtr) ref;
7870 }
7871 FREE_AND_NULL(tmp)
7872 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007873 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007874
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007875 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007876 /*
7877 * And now for the children...
7878 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007879 child = node->children;
7880 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007881 /*
7882 * Add the annotation to the simple type ancestor.
7883 */
7884 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7885 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007886 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007887 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007888 if (IS_SCHEMA(child, "simpleType")) {
7889 xmlSchemaTypePtr subtype, last = NULL;
7890
7891 /*
7892 * Anchor the member types in the "subtypes" field of the
7893 * simple type.
7894 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007895 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007896 subtype = (xmlSchemaTypePtr)
7897 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7898 if (subtype != NULL) {
7899 if (last == NULL) {
7900 type->subtypes = subtype;
7901 last = subtype;
7902 } else {
7903 last->next = subtype;
7904 last = subtype;
7905 }
7906 last->next = NULL;
7907 }
7908 child = child->next;
7909 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007910 }
7911 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007912 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007913 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007914 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007915 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007916 if ((attr == NULL) && (type->subtypes == NULL)) {
7917 /*
7918 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007919 * Either the memberTypes [attribute] of the <union> element must
7920 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007921 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007922 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007923 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
7924 NULL, NULL, node,
7925 "Either the attribute 'memberTypes' or "
7926 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007927 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007928 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007929}
7930
7931/**
7932 * xmlSchemaParseList:
7933 * @ctxt: a schema validation context
7934 * @schema: the schema being built
7935 * @node: a subtree containing XML Schema informations
7936 *
7937 * parse a XML schema List definition
7938 * *WARNING* this interface is highly subject to change
7939 *
William M. Bracke7091952004-05-11 15:09:58 +00007940 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007941 * 1 in case of success.
7942 */
7943static xmlSchemaTypePtr
7944xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007945 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007946{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007947 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007948 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007949 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007950
7951 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7952 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007953 /* Not a component, don't create it. */
7954 type = ctxt->ctxtType;
7955 /*
7956 * Mark the type as being of variety "list".
7957 */
7958 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007959 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007960 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7961 * then the ·simple ur-type definition·."
7962 */
7963 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007964 /*
7965 * Check for illegal attributes.
7966 */
7967 attr = node->properties;
7968 while (attr != NULL) {
7969 if (attr->ns == NULL) {
7970 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7971 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007972 xmlSchemaPIllegalAttrErr(ctxt,
7973 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7974 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007975 }
7976 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007977 xmlSchemaPIllegalAttrErr(ctxt,
7978 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7979 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007980 }
7981 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007982 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007983
7984 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7985
William M. Brack2f2a6632004-08-20 23:09:47 +00007986 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007987 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
7988 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00007989 */
7990 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007991 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00007992 /*
7993 * And now for the children...
7994 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007995 child = node->children;
7996 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007997 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7998 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007999 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008000 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008001 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008002 /*
8003 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008004 * Either the itemType [attribute] or the <simpleType> [child] of
8005 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008006 */
8007 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008008 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008009 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008010 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00008011 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008012 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008013 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008014 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008015 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008016 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008017 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008018 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008019 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008020 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008021 "Either the attribute 'itemType' or the <simpleType> child "
8022 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008023 }
8024 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008025 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008026 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008027 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008028 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008029 if ((type->ref == NULL) &&
8030 (type->subtypes == NULL) &&
8031 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008032 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008033 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008034 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008035 "Either the attribute 'itemType' or the <simpleType> child "
8036 "must be present", NULL);
8037 }
8038 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008039}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008040
Daniel Veillard4255d502002-04-16 15:50:10 +00008041/**
8042 * xmlSchemaParseSimpleType:
8043 * @ctxt: a schema validation context
8044 * @schema: the schema being built
8045 * @node: a subtree containing XML Schema informations
8046 *
8047 * parse a XML schema Simple Type definition
8048 * *WARNING* this interface is highly subject to change
8049 *
William M. Bracke7091952004-05-11 15:09:58 +00008050 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008051 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008052 */
8053static xmlSchemaTypePtr
8054xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008055 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008056{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008057 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008058 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008059 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008060 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008061
8062 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8063 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008064
Daniel Veillardc0826a72004-08-10 14:17:33 +00008065 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008066 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008067 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008068 xmlSchemaPMissingAttrErr(ctxt,
8069 XML_SCHEMAP_S4S_ATTR_MISSING,
8070 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008071 "name", NULL);
8072 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008073 } else {
8074 if (xmlSchemaPValAttrNode(ctxt,
8075 NULL, NULL, attr,
8076 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
8077 return (NULL);
8078 /*
8079 * Skip built-in types.
8080 */
8081 if (ctxt->isS4S) {
8082 xmlSchemaTypePtr biType;
8083
8084 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
8085 if (biType != NULL)
8086 return (biType);
8087 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008088 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008089 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008090
Daniel Veillardc0826a72004-08-10 14:17:33 +00008091 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008092 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008093
Daniel Veillard01fa6152004-06-29 17:04:39 +00008094 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008095 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008096 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008097 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008098 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008099 if (type == NULL)
8100 return (NULL);
8101 type->node = node;
8102 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008103 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008104 /*
8105 * Check for illegal attributes.
8106 */
8107 attr = node->properties;
8108 while (attr != NULL) {
8109 if (attr->ns == NULL) {
8110 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008111 xmlSchemaPIllegalAttrErr(ctxt,
8112 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8113 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008114 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008115 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008116 xmlSchemaPIllegalAttrErr(ctxt,
8117 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8118 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008119 }
8120 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008121 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008122 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008123 /*
8124 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008125 *
8126 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008127 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008128 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008129 if (type == NULL)
8130 return (NULL);
8131 type->node = node;
8132 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008133 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008134 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8135 /*
8136 * Check for illegal attributes.
8137 */
8138 attr = node->properties;
8139 while (attr != NULL) {
8140 if (attr->ns == NULL) {
8141 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8142 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008143 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008144 xmlSchemaPIllegalAttrErr(ctxt,
8145 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8146 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008147 }
8148 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008149 xmlSchemaPIllegalAttrErr(ctxt,
8150 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8151 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008152 }
8153 attr = attr->next;
8154 }
8155 /*
8156 * Attribute "final".
8157 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008158 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008159 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008160 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8161 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8162 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8163 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8164 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8165 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008166 } else {
8167 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008168 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8169 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008170 XML_SCHEMAS_TYPE_FINAL_LIST,
8171 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8172
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008173 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008174 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008175 type, (xmlNodePtr) attr,
8176 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008177 attrValue, NULL, NULL, NULL);
8178 }
8179 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008180 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008181 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008182 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008183 /*
8184 * And now for the children...
8185 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008186 oldCtxtType = ctxt->ctxtType;
8187 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008188 ctxt->ctxtType = type;
8189 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008190 child = node->children;
8191 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008192 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8193 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008194 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008195 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008196 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8197 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008198 "(annotation?, (restriction | list | union))");
8199 } else if (IS_SCHEMA(child, "restriction")) {
8200 xmlSchemaParseRestriction(ctxt, schema, child,
8201 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008202 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008203 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008204 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008205 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008206 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008207 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008208 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008209 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008210 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008211 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8212 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008213 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008214 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008215 ctxt->parentItem = oldParentItem;
8216 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008217
Daniel Veillard4255d502002-04-16 15:50:10 +00008218 return (type);
8219}
8220
Daniel Veillard4255d502002-04-16 15:50:10 +00008221/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008222 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008223 * @ctxt: a schema validation context
8224 * @schema: the schema being built
8225 * @node: a subtree containing XML Schema informations
8226 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008227 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008228 * *WARNING* this interface is highly subject to change
8229 *
William M. Bracke7091952004-05-11 15:09:58 +00008230 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008231 * 1 in case of success.
8232 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008233static xmlSchemaTreeItemPtr
8234xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8235 xmlSchemaPtr schema,
8236 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008237{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008238 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008239 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008240 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008241 const xmlChar *ref = NULL, *refNs = NULL;
8242 int min, max;
8243
8244 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008245 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008246
8247 attr = xmlSchemaGetPropNode(node, "ref");
8248 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008249 xmlSchemaPMissingAttrErr(ctxt,
8250 XML_SCHEMAP_S4S_ATTR_MISSING,
8251 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008252 "ref", NULL);
8253 return (NULL);
8254 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008255 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008256 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008257 }
8258 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008259 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008260 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008261 /*
8262 * Check for illegal attributes.
8263 */
8264 attr = node->properties;
8265 while (attr != NULL) {
8266 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008267 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008268 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8269 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8270 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008271 xmlSchemaPIllegalAttrErr(ctxt,
8272 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8273 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008274 }
8275 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008276 xmlSchemaPIllegalAttrErr(ctxt,
8277 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8278 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008279 }
8280 attr = attr->next;
8281 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008282 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008283 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8284 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008285 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008286 /*
8287 * Create a reference item as the term; it will be substituted for
8288 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008289 */
8290 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008291 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8292 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8293 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8294 /*
8295 * And now for the children...
8296 */
8297 child = node->children;
8298 /* TODO: Is annotation even allowed for a model group reference? */
8299 if (IS_SCHEMA(child, "annotation")) {
8300 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008301 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008302 */
8303 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8304 child = child->next;
8305 }
8306 if (child != NULL) {
8307 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008308 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008309 NULL, NULL, node, child, NULL,
8310 "(annotation?)");
8311 }
8312 /*
8313 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8314 */
8315 if ((min == 0) && (max == 0))
8316 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008317 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008318 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8319 return ((xmlSchemaTreeItemPtr) item);
8320}
8321
8322/**
8323 * xmlSchemaParseModelGroupDefinition:
8324 * @ctxt: a schema validation context
8325 * @schema: the schema being built
8326 * @node: a subtree containing XML Schema informations
8327 *
8328 * Parses a XML schema model group definition.
8329 * *WARNING* this interface is highly subject to change
8330 *
8331 * Returns -1 in case of error, 0 if the declaration is improper and
8332 * 1 in case of success.
8333 */
8334static xmlSchemaModelGroupDefPtr
8335xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8336 xmlSchemaPtr schema,
8337 xmlNodePtr node)
8338{
8339 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008340 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008341 xmlAttrPtr attr;
8342 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008343
8344 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008345 return (NULL);
8346
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008347 attr = xmlSchemaGetPropNode(node, "name");
8348 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008349 xmlSchemaPMissingAttrErr(ctxt,
8350 XML_SCHEMAP_S4S_ATTR_MISSING,
8351 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008352 "name", NULL);
8353 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008354 } else if (xmlSchemaPValAttrNode(ctxt,
8355 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008356 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8357 return (NULL);
8358 }
8359 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8360 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008361 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008362 /*
8363 * Check for illegal attributes.
8364 */
8365 attr = node->properties;
8366 while (attr != NULL) {
8367 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008368 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008369 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008370 xmlSchemaPIllegalAttrErr(ctxt,
8371 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8372 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008373 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008374 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008375 xmlSchemaPIllegalAttrErr(ctxt,
8376 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8377 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008378 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008379 attr = attr->next;
8380 }
8381 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8382 /*
8383 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008384 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008385 child = node->children;
8386 if (IS_SCHEMA(child, "annotation")) {
8387 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8388 child = child->next;
8389 }
8390 if (IS_SCHEMA(child, "all")) {
8391 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8392 XML_SCHEMA_TYPE_ALL, 0);
8393 child = child->next;
8394 } else if (IS_SCHEMA(child, "choice")) {
8395 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8396 XML_SCHEMA_TYPE_CHOICE, 0);
8397 child = child->next;
8398 } else if (IS_SCHEMA(child, "sequence")) {
8399 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8400 XML_SCHEMA_TYPE_SEQUENCE, 0);
8401 child = child->next;
8402 }
8403 if (child != NULL) {
8404 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008405 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8406 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008407 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008408 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008409
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008410 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008411}
8412
8413/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008414 * xmlSchemaCleanupDoc:
8415 * @ctxt: a schema validation context
8416 * @node: the root of the document.
8417 *
8418 * removes unwanted nodes in a schemas document tree
8419 */
8420static void
8421xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8422{
8423 xmlNodePtr delete, cur;
8424
8425 if ((ctxt == NULL) || (root == NULL)) return;
8426
8427 /*
8428 * Remove all the blank text nodes
8429 */
8430 delete = NULL;
8431 cur = root;
8432 while (cur != NULL) {
8433 if (delete != NULL) {
8434 xmlUnlinkNode(delete);
8435 xmlFreeNode(delete);
8436 delete = NULL;
8437 }
8438 if (cur->type == XML_TEXT_NODE) {
8439 if (IS_BLANK_NODE(cur)) {
8440 if (xmlNodeGetSpacePreserve(cur) != 1) {
8441 delete = cur;
8442 }
8443 }
8444 } else if ((cur->type != XML_ELEMENT_NODE) &&
8445 (cur->type != XML_CDATA_SECTION_NODE)) {
8446 delete = cur;
8447 goto skip_children;
8448 }
8449
8450 /*
8451 * Skip to next node
8452 */
8453 if (cur->children != NULL) {
8454 if ((cur->children->type != XML_ENTITY_DECL) &&
8455 (cur->children->type != XML_ENTITY_REF_NODE) &&
8456 (cur->children->type != XML_ENTITY_NODE)) {
8457 cur = cur->children;
8458 continue;
8459 }
8460 }
8461 skip_children:
8462 if (cur->next != NULL) {
8463 cur = cur->next;
8464 continue;
8465 }
8466
8467 do {
8468 cur = cur->parent;
8469 if (cur == NULL)
8470 break;
8471 if (cur == root) {
8472 cur = NULL;
8473 break;
8474 }
8475 if (cur->next != NULL) {
8476 cur = cur->next;
8477 break;
8478 }
8479 } while (cur != NULL);
8480 }
8481 if (delete != NULL) {
8482 xmlUnlinkNode(delete);
8483 xmlFreeNode(delete);
8484 delete = NULL;
8485 }
8486}
8487
William M. Brack2f2a6632004-08-20 23:09:47 +00008488
8489/**
8490 * xmlSchemaImportSchema
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008491 *
William M. Brack2f2a6632004-08-20 23:09:47 +00008492 * @ctxt: a schema validation context
8493 * @schemaLocation: an URI defining where to find the imported schema
8494 *
8495 * import a XML schema
8496 * *WARNING* this interface is highly subject to change
8497 *
8498 * Returns -1 in case of error and 1 in case of success.
8499 */
8500#if 0
8501static xmlSchemaImportPtr
8502xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8503 const xmlChar *schemaLocation)
8504{
8505 xmlSchemaImportPtr import;
8506 xmlSchemaParserCtxtPtr newctxt;
8507
8508 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8509 if (newctxt == NULL) {
8510 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8511 NULL);
8512 return (NULL);
8513 }
8514 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8515 /* Keep the same dictionnary for parsing, really */
8516 xmlDictReference(ctxt->dict);
8517 newctxt->dict = ctxt->dict;
8518 newctxt->includes = 0;
8519 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8520
8521 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8522 ctxt->userData);
8523
8524 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8525 if (import == NULL) {
8526 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8527 NULL);
8528 xmlSchemaFreeParserCtxt(newctxt);
8529 return (NULL);
8530 }
8531
8532 memset(import, 0, sizeof(xmlSchemaImport));
8533 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8534 import->schema = xmlSchemaParse(newctxt);
8535
8536 if (import->schema == NULL) {
8537 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008538 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008539 "Failed to import schema from location \"%s\".\n",
8540 schemaLocation, NULL);
8541
8542 xmlSchemaFreeParserCtxt(newctxt);
8543 /* The schemaLocation is held by the dictionary.
8544 if (import->schemaLocation != NULL)
8545 xmlFree((xmlChar *)import->schemaLocation);
8546 */
8547 xmlFree(import);
8548 return NULL;
8549 }
8550
8551 xmlSchemaFreeParserCtxt(newctxt);
8552 return import;
8553}
8554#endif
8555
8556static void
8557xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8558{
8559 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8560 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8561
8562 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8563 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8564
8565 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8566 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8567 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8568 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8569 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8570 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8571 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8572 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8573
8574 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8575 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8576 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8577 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8578 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8579 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8580}
8581
8582static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008583xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008584 xmlSchemaPtr schema,
8585 xmlNodePtr node)
8586{
8587 xmlAttrPtr attr;
8588 const xmlChar *val;
8589
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008590 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8591 if (schema->version == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008592 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008593 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8594 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008595 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008596 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8597
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008598 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008599 if (attr != NULL) {
8600 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008601 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008602 XML_SCHEMAS_QUALIF_ELEM) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008603 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008604 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008605 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008606 "(qualified | unqualified)", val, NULL, NULL, NULL);
8607 }
8608 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008609
8610 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008611 if (attr != NULL) {
8612 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008613 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008614 XML_SCHEMAS_QUALIF_ATTR) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008615 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008616 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008617 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008618 "(qualified | unqualified)", val, NULL, NULL, NULL);
8619 }
8620 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008621
8622 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008623 if (attr != NULL) {
8624 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8625 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8626 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8627 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8628 -1,
8629 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8630 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8631 xmlSchemaPSimpleTypeErr(ctxt,
8632 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008633 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008634 "(#all | List of (extension | restriction | list | union))",
8635 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008636 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008637 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008638
8639 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008640 if (attr != NULL) {
8641 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8642 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8643 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8644 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8645 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8646 xmlSchemaPSimpleTypeErr(ctxt,
8647 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008648 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008649 "(#all | List of (extension | restriction | substitution))",
8650 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008651 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008652 }
8653}
8654
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008655/**
8656 * xmlSchemaParseSchemaTopLevel:
8657 * @ctxt: a schema validation context
8658 * @schema: the schemas
8659 * @nodes: the list of top level nodes
8660 *
8661 * Returns the internal XML Schema structure built from the resource or
8662 * NULL in case of error
8663 */
8664static void
8665xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8666 xmlSchemaPtr schema, xmlNodePtr nodes)
8667{
8668 xmlNodePtr child;
8669 xmlSchemaAnnotPtr annot;
8670
8671 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8672 return;
8673
8674 child = nodes;
8675 while ((IS_SCHEMA(child, "include")) ||
8676 (IS_SCHEMA(child, "import")) ||
8677 (IS_SCHEMA(child, "redefine")) ||
8678 (IS_SCHEMA(child, "annotation"))) {
8679 if (IS_SCHEMA(child, "annotation")) {
8680 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8681 if (schema->annot == NULL)
8682 schema->annot = annot;
8683 else
8684 xmlSchemaFreeAnnot(annot);
8685 } else if (IS_SCHEMA(child, "import")) {
8686 xmlSchemaParseImport(ctxt, schema, child);
8687 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008688 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008689 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008690 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008691 } else if (IS_SCHEMA(child, "redefine")) {
8692 TODO
8693 }
8694 child = child->next;
8695 }
8696 while (child != NULL) {
8697 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008698 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008699 child = child->next;
8700 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008701 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008702 child = child->next;
8703 } else if (IS_SCHEMA(child, "element")) {
8704 xmlSchemaParseElement(ctxt, schema, child, 1);
8705 child = child->next;
8706 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008707 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008708 child = child->next;
8709 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008710 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008711 child = child->next;
8712 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008713 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008714 child = child->next;
8715 } else if (IS_SCHEMA(child, "notation")) {
8716 xmlSchemaParseNotation(ctxt, schema, child);
8717 child = child->next;
8718 } else {
8719 xmlSchemaPErr2(ctxt, NULL, child,
8720 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008721 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008722 child->name, NULL);
8723 child = child->next;
8724 }
8725 while (IS_SCHEMA(child, "annotation")) {
8726 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8727 if (schema->annot == NULL)
8728 schema->annot = annot;
8729 else
8730 xmlSchemaFreeAnnot(annot);
8731 child = child->next;
8732 }
8733 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008734 ctxt->parentItem = NULL;
8735 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008736}
8737
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008738static xmlSchemaImportPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008739xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008740 xmlHashTablePtr *imports,
8741 const xmlChar *nsName)
8742{
8743 xmlSchemaImportPtr ret;
8744
8745 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008746 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008747 if (*imports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008748 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008749 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8750 NULL, NULL, (xmlNodePtr) ctxt->doc,
8751 "Internal error: failed to build the import table",
8752 NULL);
8753 return (NULL);
8754 }
8755 }
8756 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8757 if (ret == NULL) {
8758 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8759 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008760 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008761 memset(ret, 0, sizeof(xmlSchemaImport));
8762 if (nsName == NULL)
8763 nsName = XML_SCHEMAS_NO_NAMESPACE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008764 xmlHashAddEntry(*imports, nsName, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008765
8766 return (ret);
8767}
8768
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008769/**
8770 * xmlSchemaNewParserCtxtUseDict:
8771 * @URL: the location of the schema
8772 * @dict: the dictionary to be used
8773 *
8774 * Create an XML Schemas parse context for that file/resource expected
8775 * to contain an XML Schemas file.
8776 *
8777 * Returns the parser context or NULL in case of error
8778 */
8779static xmlSchemaParserCtxtPtr
8780xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8781{
8782 xmlSchemaParserCtxtPtr ret;
8783 /*
8784 if (URL == NULL)
8785 return (NULL);
8786 */
8787
8788 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8789 if (ret == NULL) {
8790 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8791 NULL);
8792 return (NULL);
8793 }
8794 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8795 ret->dict = dict;
8796 xmlDictReference(dict);
8797 if (URL != NULL)
8798 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
8799 ret->includes = 0;
8800 return (ret);
8801}
8802
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008803static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008804xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
8805{
8806 if (vctxt->pctxt == NULL) {
8807 if (vctxt->schema != NULL)
8808 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
8809 else
8810 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
8811 if (vctxt->pctxt == NULL) {
8812 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
8813 "failed to create a temp. parser context");
8814 return (-1);
8815 }
8816 /* TODO: Pass user data. */
8817 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
8818 }
8819 return (0);
8820}
8821
8822static int
8823xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008824 xmlSchemaPtr schema,
8825 xmlNodePtr node,
8826 const xmlChar *nsName,
8827 const xmlChar *location,
8828 xmlDocPtr *doc,
8829 const xmlChar **targetNamespace,
8830 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008831{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008832 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008833 xmlParserCtxtPtr parserCtxt;
8834 xmlSchemaImportPtr import;
8835 const xmlChar *ns;
8836 xmlNodePtr root;
8837
8838 /*
8839 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8840 * <xsi:noNamespaceSchemaLocation>.
8841 */
8842 *doc = NULL;
8843 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008844 * Given that the schemaLocation [attribute] is only a hint, it is open
8845 * to applications to ignore all but the first <import> for a given
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008846 * namespace, regardless of the ·actual value· of schemaLocation, but
8847 * such a strategy risks missing useful information when new
8848 * schemaLocations are offered.
8849 *
8850 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8851 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8852 * valid or not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008853 * We will follow XSV here.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008854 */
8855 if (location == NULL) {
8856 /*
8857 * Schema Document Location Strategy:
8858 *
8859 * 3 Based on the namespace name, identify an existing schema document,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008860 * either as a resource which is an XML document or a <schema> element
8861 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008862 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008863 * 5 Attempt to resolve the namespace name to locate such a resource.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008864 *
8865 * NOTE: Those stategies are not supported, so we will skip.
8866 */
8867 return (0);
8868 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008869 if (nsName == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008870 ns = XML_SCHEMAS_NO_NAMESPACE;
8871 else
8872 ns = nsName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008873
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008874 import = xmlHashLookup(schema->schemasImports, ns);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008875 if (import != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008876 /*
8877 * There was a valid resource for the specified namespace already
8878 * defined, so skip.
8879 * TODO: This might be changed someday to allow import of
8880 * components from multiple documents for a single target namespace.
8881 */
8882 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008883 }
8884 if (actxt->type == XML_SCHEMA_CTXT_PARSER)
8885 pctxt = (xmlSchemaParserCtxtPtr) actxt;
8886 else {
8887 xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
8888 pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
8889 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008890 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008891 * Schema Document Location Strategy:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008892 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008893 * 2 Based on the location URI, identify an existing schema document,
8894 * either as a resource which is an XML document or a <schema> element
8895 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008896 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008897 * 4 Attempt to resolve the location URI, to locate a resource on the
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008898 * web which is or contains or references a <schema> element;
8899 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8900 *
8901 */
8902 if ((absolute == 0) && (node != NULL)) {
8903 xmlChar *base, *URI;
8904
8905 base = xmlNodeGetBase(node->doc, node);
8906 if (base == NULL) {
8907 URI = xmlBuildURI(location, node->doc->URL);
8908 } else {
8909 URI = xmlBuildURI(location, base);
8910 xmlFree(base);
8911 }
8912 if (URI != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008913 location = xmlDictLookup(pctxt->dict, URI, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008914 xmlFree(URI);
8915 }
8916 }
8917 parserCtxt = xmlNewParserCtxt();
8918 if (parserCtxt == NULL) {
8919 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8920 "allocating a parser context", NULL);
8921 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008922 }
8923 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008924 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008925 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008926 xmlDictReference(parserCtxt->dict);
8927 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008928 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008929 NULL, SCHEMAS_PARSE_OPTIONS);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008930 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008931 * 2.1 The referent is (a fragment of) a resource which is an
8932 * XML document (see clause 1.1), which in turn corresponds to
8933 * a <schema> element information item in a well-formed information
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008934 * set, which in turn corresponds to a valid schema.
8935 * TODO: What to do with the "fragment" stuff?
8936 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008937 * 2.2 The referent is a <schema> element information item in
8938 * a well-formed information set, which in turn corresponds
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008939 * to a valid schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008940 * NOTE: 2.2 won't apply, since only XML documents will be processed
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008941 * here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008942 */
8943 if (*doc == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008944 xmlErrorPtr lerr;
8945 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008946 * It is *not* an error for the application schema reference
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008947 * strategy to fail.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008948 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008949 * If the doc is NULL and the parser error is an IO error we
8950 * will assume that the resource could not be located or accessed.
8951 *
8952 * TODO: Try to find specific error codes to react only on
8953 * localisation failures.
8954 *
8955 * TODO, FIXME: Check the spec: is a namespace added to the imported
8956 * namespaces, even if the schemaLocation did not provide
8957 * a resource? I guess so, since omitting the "schemaLocation"
8958 * attribute, imports a namespace as well.
8959 */
8960 lerr = xmlGetLastError();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008961 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008962 xmlFreeParserCtxt(parserCtxt);
8963 return(0);
8964 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008965 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008966 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008967 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008968 "Failed to parse the resource '%s' for import",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008969 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008970 xmlFreeParserCtxt(parserCtxt);
8971 return(XML_SCHEMAP_SRC_IMPORT_2_1);
8972 }
8973 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008974
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008975 root = xmlDocGetRootElement(*doc);
8976 if (root == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008977 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008978 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008979 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008980 "The XML document '%s' to be imported has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008981 "element", location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008982 xmlFreeDoc(*doc);
8983 *doc = NULL;
8984 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008985 }
8986
8987 xmlSchemaCleanupDoc(pctxt, root);
8988
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008989 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008990 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008991 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008992 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008993 "The XML document '%s' to be imported is not a XML schema document",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008994 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008995 xmlFreeDoc(*doc);
8996 *doc = NULL;
8997 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008998 }
8999 *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009000 /*
9001 * Schema Representation Constraint: Import Constraints and Semantics
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009002 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009003 if (nsName == NULL) {
9004 if (*targetNamespace != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009005 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009006 XML_SCHEMAP_SRC_IMPORT_3_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009007 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009008 "The XML schema to be imported is not expected "
9009 "to have a target namespace; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009010 "its target namespace of '%s'", *targetNamespace, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009011 xmlFreeDoc(*doc);
9012 *doc = NULL;
9013 return (XML_SCHEMAP_SRC_IMPORT_3_2);
9014 }
9015 } else {
9016 if (*targetNamespace == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009017 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009018 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009019 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009020 "The XML schema to be imported is expected to have a target "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009021 "namespace of '%s'", nsName, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009022 xmlFreeDoc(*doc);
9023 *doc = NULL;
9024 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9025 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009026 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009027 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009028 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009029 "The XML schema to be imported is expected to have a "
9030 "target namespace of '%s'; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009031 "its target namespace of '%s'",
9032 nsName, *targetNamespace);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009033 xmlFreeDoc(*doc);
9034 *doc = NULL;
9035 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9036 }
9037 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009038 import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009039 if (import == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009040 AERROR_INT("xmlSchemaAcquireSchemaDoc",
9041 "failed to build import table");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009042 xmlFreeDoc(*doc);
9043 *doc = NULL;
9044 return (-1);
9045 }
9046 import->schemaLocation = location;
9047 import->doc = *doc;
9048 return (0);
9049}
William M. Brack2f2a6632004-08-20 23:09:47 +00009050
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009051static void
9052xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9053 xmlSchemaPtr schema,
9054 const xmlChar *targetNamespace,
9055 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009056{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009057 const xmlChar *oldURL, **oldLocImps, *oldTNS;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009058 int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009059
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009060 /*
9061 * Save and reset the context & schema.
9062 */
9063 oldURL = pctxt->URL;
9064 /* TODO: Is using the doc->URL here correct? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009065 pctxt->URL = node->doc->URL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009066 oldLocImps = pctxt->localImports;
9067 pctxt->localImports = NULL;
9068 oldNumLocImps = pctxt->nbLocalImports;
9069 pctxt->nbLocalImports = 0;
9070 oldSizeLocImps = pctxt->sizeLocalImports;
9071 pctxt->sizeLocalImports = 0;
9072 oldFlags = schema->flags;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009073 oldIsS4S = pctxt->isS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009074 xmlSchemaClearSchemaDefaults(schema);
9075 oldTNS = schema->targetNamespace;
9076 schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009077 if ((targetNamespace != NULL) &&
9078 xmlStrEqual(targetNamespace, xmlSchemaNs)) {
9079 /*
9080 * We are parsing the schema for schema!
9081 */
9082 pctxt->isS4S = 1;
9083 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009084 /*
9085 * Parse the schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009086 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009087 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9088 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9089 /*
9090 * Restore the context & schema.
9091 */
9092 schema->flags = oldFlags;
9093 schema->targetNamespace = oldTNS;
9094 if (pctxt->localImports != NULL)
9095 xmlFree((xmlChar *) pctxt->localImports);
9096 pctxt->localImports = oldLocImps;
9097 pctxt->nbLocalImports = oldNumLocImps;
9098 pctxt->sizeLocalImports = oldSizeLocImps;
9099 pctxt->URL = oldURL;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009100 pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009101}
9102
William M. Brack2f2a6632004-08-20 23:09:47 +00009103/**
9104 * xmlSchemaParseImport:
9105 * @ctxt: a schema validation context
9106 * @schema: the schema being built
9107 * @node: a subtree containing XML Schema informations
9108 *
9109 * parse a XML schema Import definition
9110 * *WARNING* this interface is highly subject to change
9111 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009112 * Returns 0 in case of success, a positive error code if
9113 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009114 */
9115static int
9116xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9117 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009118{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009119 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009120 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009121 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009122 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009123 xmlAttrPtr attr;
9124 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009125 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009126
9127 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9128 return (-1);
9129
9130 /*
9131 * Check for illegal attributes.
9132 */
9133 attr = node->properties;
9134 while (attr != NULL) {
9135 if (attr->ns == NULL) {
9136 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9137 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9138 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009139 xmlSchemaPIllegalAttrErr(ctxt,
9140 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9141 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009142 }
9143 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009144 xmlSchemaPIllegalAttrErr(ctxt,
9145 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9146 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009147 }
9148 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009149 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009150 /*
9151 * Extract and validate attributes.
9152 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009153 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9154 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009155 &namespaceName) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009156 xmlSchemaPSimpleTypeErr(ctxt,
9157 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9158 NULL, node,
9159 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009160 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009161 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9162 }
9163
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009164 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9165 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009166 &schemaLocation) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009167 xmlSchemaPSimpleTypeErr(ctxt,
9168 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9169 NULL, node,
9170 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009171 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009172 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009173 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009174 /*
9175 * And now for the children...
9176 */
9177 child = node->children;
9178 if (IS_SCHEMA(child, "annotation")) {
9179 /*
9180 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009181 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009182 */
9183 child = child->next;
9184 }
9185 if (child != NULL) {
9186 xmlSchemaPContentErr(ctxt,
9187 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9188 NULL, NULL, node, child, NULL,
9189 "(annotation?)");
9190 }
9191 /*
9192 * Apply additional constraints.
9193 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009194 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009195 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009196 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9197 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009198 * targetNamespace [attribute].
9199 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009200 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009201 xmlSchemaPCustomErr(ctxt,
9202 XML_SCHEMAP_SRC_IMPORT_1_1,
9203 NULL, NULL, node,
9204 "The value of the attribute 'namespace' must not match "
9205 "the target namespace '%s' of the importing schema",
9206 schema->targetNamespace);
9207 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9208 }
9209 } else {
9210 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009211 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009212 * <schema> must have a targetNamespace [attribute].
9213 */
9214 if (schema->targetNamespace == NULL) {
9215 xmlSchemaPCustomErr(ctxt,
9216 XML_SCHEMAP_SRC_IMPORT_1_2,
9217 NULL, NULL, node,
9218 "The attribute 'namespace' must be existent if "
9219 "the importing schema has no target namespace",
9220 NULL);
9221 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9222 }
9223 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009224 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009225 * Add the namespace to the list of locally imported namespace.
9226 */
9227 if (ctxt->localImports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009228 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009229 sizeof(const xmlChar*));
9230 ctxt->sizeLocalImports = 10;
9231 ctxt->nbLocalImports = 0;
9232 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9233 ctxt->sizeLocalImports *= 2;
9234 ctxt->localImports = (const xmlChar **) xmlRealloc(
9235 (xmlChar **) ctxt->localImports,
9236 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9237 }
9238 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9239 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009240 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009241 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009242 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) ctxt,
9243 schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009244 schemaLocation, &doc, &targetNamespace, 0);
9245 if (ret != 0) {
9246 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009247 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009248 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009249 } else if (doc != NULL) {
9250 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9251 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009252 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009253
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009254 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009255}
9256
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009257/**
9258 * xmlSchemaParseInclude:
9259 * @ctxt: a schema validation context
9260 * @schema: the schema being built
9261 * @node: a subtree containing XML Schema informations
9262 *
9263 * parse a XML schema Include definition
9264 *
William M. Bracke7091952004-05-11 15:09:58 +00009265 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009266 * 1 in case of success.
9267 */
9268static int
9269xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9270 xmlNodePtr node)
9271{
9272 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009273 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009274 xmlDocPtr doc = NULL;
9275 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009276 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009277 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009278 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009279 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009280
9281
9282 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9283 return (-1);
9284
9285 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009286 * Check for illegal attributes.
9287 */
9288 attr = node->properties;
9289 while (attr != NULL) {
9290 if (attr->ns == NULL) {
9291 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9292 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009293 xmlSchemaPIllegalAttrErr(ctxt,
9294 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9295 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009296 }
9297 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009298 xmlSchemaPIllegalAttrErr(ctxt,
9299 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9300 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009301 }
9302 attr = attr->next;
9303 }
9304 /*
9305 * Extract and validate attributes.
9306 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009307 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009308 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009309 * Preliminary step, extract the URI-Reference for the include and
9310 * make an URI from the base.
9311 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009312 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9313 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009314 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009315 xmlChar *uri = NULL;
9316
9317 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9318 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009319 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009320 base = xmlNodeGetBase(node->doc, node);
9321 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009322 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009323 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009324 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009325 xmlFree(base);
9326 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009327 if (uri == NULL) {
9328 xmlSchemaPErr(ctxt,
9329 node,
9330 XML_SCHEMAP_INTERNAL,
9331 "Internal error: xmlSchemaParseInclude, "
9332 "could not build an URI from the schemaLocation.\n",
9333 NULL, NULL);
9334 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009335 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009336 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9337 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009338 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009339 xmlSchemaPMissingAttrErr(ctxt,
9340 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9341 NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009342 goto exit_invalid;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009343 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009344 /*
9345 * And now for the children...
9346 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009347 child = node->children;
9348 while (IS_SCHEMA(child, "annotation")) {
9349 /*
9350 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009351 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009352 */
9353 child = child->next;
9354 }
9355 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009356 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009357 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9358 NULL, NULL, node, child, NULL,
9359 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009360 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009361 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009362 * Report self-inclusion.
9363 */
9364 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9365 xmlSchemaPCustomErr(ctxt,
9366 XML_SCHEMAP_SRC_INCLUDE,
9367 NULL, NULL, node,
9368 "The schema document '%s' cannot include itself.",
9369 schemaLocation);
9370 return (XML_SCHEMAP_SRC_INCLUDE);
9371 }
9372 /*
9373 * Check if this one was already processed to avoid incorrect
9374 * duplicate component errors and infinite circular inclusion.
9375 */
9376 include = schema->includes;
9377 while (include != NULL) {
9378 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9379 targetNamespace = include->origTargetNamespace;
9380 if (targetNamespace == NULL) {
9381 /*
9382 * Chameleon include: skip only if it was build for
9383 * the targetNamespace of the including schema.
9384 */
9385 if (xmlStrEqual(schema->targetNamespace,
9386 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009387 goto check_targetNamespace;
9388 }
9389 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009390 goto check_targetNamespace;
9391 }
9392 }
9393 include = include->next;
9394 }
9395 /*
9396 * First step is to parse the input document into an DOM/Infoset
9397 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009398 */
9399 parserCtxt = xmlNewParserCtxt();
9400 if (parserCtxt == NULL) {
9401 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9402 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009403 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009404 }
9405
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009406 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9407 xmlDictFree(parserCtxt->dict);
9408 parserCtxt->dict = ctxt->dict;
9409 xmlDictReference(parserCtxt->dict);
9410 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009411
9412 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009413 NULL, SCHEMAS_PARSE_OPTIONS);
9414 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009415 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009416 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009417 * TODO: It is not an error for the ·actual value· of the
9418 * schemaLocation [attribute] to fail to resolve it all, in which
9419 * case no corresponding inclusion is performed.
William M. Brack2f2a6632004-08-20 23:09:47 +00009420 * So do we need a warning report here?
9421 */
9422 xmlSchemaPCustomErr(ctxt,
9423 XML_SCHEMAP_FAILED_LOAD,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009424 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009425 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009426 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009427 }
9428
9429 /*
9430 * Then extract the root of the schema
9431 */
9432 root = xmlDocGetRootElement(doc);
9433 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009434 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009435 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009436 NULL, NULL, node,
9437 "The included document '%s' has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009438 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009439 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009440 }
9441
9442 /*
9443 * Remove all the blank text nodes
9444 */
9445 xmlSchemaCleanupDoc(ctxt, root);
9446
9447 /*
9448 * Check the schemas top level element
9449 */
9450 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009451 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009452 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009453 NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009454 "The document '%s' to be included is not a schema document",
William M. Brack2f2a6632004-08-20 23:09:47 +00009455 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009456 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009457 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009458
William M. Brack2f2a6632004-08-20 23:09:47 +00009459 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009460 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009461 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9462 * value· is identical to the ·actual value· of the targetNamespace
Daniel Veillardc0826a72004-08-10 14:17:33 +00009463 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9464 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009465check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009466 if (targetNamespace != NULL) {
9467 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009468 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009469 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009470 NULL, NULL, node,
9471 "The target namespace of the included schema "
9472 "'%s' has to be absent, since the including schema "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009473 "has no target namespace",
9474 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009475 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009476 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9477 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009478 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009479 NULL, NULL, node,
9480 "The target namespace '%s' of the included schema '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009481 "differs from '%s' of the including schema",
William M. Brack2f2a6632004-08-20 23:09:47 +00009482 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009483 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009484 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009485 } else if (schema->targetNamespace != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009486 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009487 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009488 } else
9489 wasConvertingNs = 1;
9490 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009491
9492 if (include != NULL)
9493 goto exit;
9494
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009495 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009496 * URGENT TODO: If the schema is a chameleon-include then copy the
9497 * components into the including schema and modify the targetNamespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009498 * of those components, do nothing otherwise.
9499 * NOTE: This is currently worked-around by compiling the chameleon
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009500 * for every destinct including targetNamespace; thus not performant at
9501 * the moment.
9502 * TODO: Check when the namespace in wildcards for chameleons needs
9503 * to be converted: before we built wildcard intersections or after.
9504 */
9505 /*
9506 * Register the include.
9507 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009508 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9509 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009510 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9511 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009512 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009513 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009514 include->next = schema->includes;
9515 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009516 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009517 * TODO: Use the resolved URI for the this location, since it might
9518 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009519 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009520 include->schemaLocation = schemaLocation;
9521 include->doc = doc;
9522 /*
9523 * In case of chameleons, the original target namespace will differ
9524 * from the resulting namespace.
9525 */
9526 include->origTargetNamespace = targetNamespace;
9527 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009528#ifdef DEBUG_INCLUDES
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009529 if (targetNamespace != schema->targetNamespace)
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009530 xmlGenericError(xmlGenericErrorContext,
9531 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9532 " into TNS '%s'\n", schemaLocation,
9533 targetNamespace, schema->targetNamespace);
9534 else
9535 xmlGenericError(xmlGenericErrorContext,
9536 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9537 targetNamespace);
9538#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009539 /*
9540 * Compile the included schema.
9541 */
9542 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9543
9544exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009545 /*
9546 * Remove the converting flag.
9547 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009548 if ((wasConvertingNs == 0) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00009549 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009550 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009551 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009552
9553exit_invalid:
9554 if (doc != NULL) {
9555 if (include != NULL)
9556 include->doc = NULL;
9557 xmlFreeDoc(doc);
9558 }
9559 return (ctxt->err);
9560
9561exit_failure:
9562 if (doc != NULL) {
9563 if (include != NULL)
9564 include->doc = NULL;
9565 xmlFreeDoc(doc);
9566 }
9567 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009568}
9569
9570/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009571 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009572 * @ctxt: a schema validation context
9573 * @schema: the schema being built
9574 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009575 * @type: the "compositor" type
9576 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009577 *
9578 * parse a XML schema Sequence definition
9579 * *WARNING* this interface is highly subject to change
9580 *
William M. Bracke7091952004-05-11 15:09:58 +00009581 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009582 * 1 in case of success.
9583 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009584static xmlSchemaTreeItemPtr
9585xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9586 xmlNodePtr node, xmlSchemaTypeType type,
9587 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009588{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009589 xmlSchemaModelGroupPtr item;
9590 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009591 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009592 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009593 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009594 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009595
9596 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009597 return (NULL);
9598 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009599 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009600 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009601 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9602 if (item == NULL)
9603 return (NULL);
9604
9605 if (withParticle) {
9606 if (type == XML_SCHEMA_TYPE_ALL) {
9607 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009608 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009609 } else {
9610 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009611 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9612 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9613 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009614 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009615 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
9616 /*
9617 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009618 */
9619 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9620 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009621 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009622 particle->children = (xmlSchemaTreeItemPtr) item;
9623 /*
9624 * Check for illegal attributes.
9625 */
9626 attr = node->properties;
9627 while (attr != NULL) {
9628 if (attr->ns == NULL) {
9629 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9630 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9631 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009632 xmlSchemaPIllegalAttrErr(ctxt,
9633 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9634 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009635 }
9636 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009637 xmlSchemaPIllegalAttrErr(ctxt,
9638 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9639 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009640 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009641 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009642 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009643 } else {
9644 /*
9645 * Check for illegal attributes.
9646 */
9647 attr = node->properties;
9648 while (attr != NULL) {
9649 if (attr->ns == NULL) {
9650 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009651 xmlSchemaPIllegalAttrErr(ctxt,
9652 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9653 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009654 }
9655 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009656 xmlSchemaPIllegalAttrErr(ctxt,
9657 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9658 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009659 }
9660 attr = attr->next;
9661 }
9662
William M. Brack2f2a6632004-08-20 23:09:47 +00009663 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009664
William M. Brack2f2a6632004-08-20 23:09:47 +00009665 /*
9666 * Extract and validate attributes.
9667 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009668 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009669 /*
9670 * And now for the children...
9671 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009672 child = node->children;
9673 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009674 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009675 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009676 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009677 oldcontainer = ctxt->container;
9678 ctxt->container = container;
9679 if (type == XML_SCHEMA_TYPE_ALL) {
9680 xmlSchemaParticlePtr part, last = NULL;
9681
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009682 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009683 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9684 schema, child, 0);
9685 if (part != NULL) {
9686 if (part->minOccurs > 1)
9687 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009688 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009689 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9690 if (part->maxOccurs > 1)
9691 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009692 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009693 "Invalid value for maxOccurs (must be 0 or 1)",
9694 NULL);
9695 if (last == NULL)
9696 item->children = (xmlSchemaTreeItemPtr) part;
9697 else
9698 last->next = (xmlSchemaTreeItemPtr) part;
9699 last = part;
9700 }
9701 child = child->next;
9702 }
9703 if (child != NULL) {
9704 xmlSchemaPContentErr(ctxt,
9705 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9706 NULL, NULL, node, child, NULL,
9707 "(annotation?, (annotation?, element*)");
9708 }
9709 } else {
9710 /* choice + sequence */
9711 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9712
9713 while ((IS_SCHEMA(child, "element")) ||
9714 (IS_SCHEMA(child, "group")) ||
9715 (IS_SCHEMA(child, "any")) ||
9716 (IS_SCHEMA(child, "choice")) ||
9717 (IS_SCHEMA(child, "sequence"))) {
9718
9719 if (IS_SCHEMA(child, "element")) {
9720 part = (xmlSchemaTreeItemPtr)
9721 xmlSchemaParseElement(ctxt, schema, child, 0);
9722 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009723 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009724 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9725 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009726 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009727 xmlSchemaParseAny(ctxt, schema, child);
9728 } else if (IS_SCHEMA(child, "choice")) {
9729 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9730 XML_SCHEMA_TYPE_CHOICE, 1);
9731 } else if (IS_SCHEMA(child, "sequence")) {
9732 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9733 XML_SCHEMA_TYPE_SEQUENCE, 1);
9734 }
9735 if (part != NULL) {
9736 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009737 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009738 else
9739 last->next = part;
9740 last = part;
9741 }
9742 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009743 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009744 if (child != NULL) {
9745 xmlSchemaPContentErr(ctxt,
9746 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9747 NULL, NULL, node, child, NULL,
9748 "(annotation?, (element | group | choice | sequence | any)*)");
9749 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009750 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009751 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009752 if (withParticle) {
9753 if ((min == 0) && (max == 0))
9754 return (NULL);
9755 else
9756 return ((xmlSchemaTreeItemPtr) particle);
9757 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009758 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009759}
9760
9761/**
9762 * xmlSchemaParseRestriction:
9763 * @ctxt: a schema validation context
9764 * @schema: the schema being built
9765 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009766 *
9767 * parse a XML schema Restriction definition
9768 * *WARNING* this interface is highly subject to change
9769 *
9770 * Returns the type definition or NULL in case of error
9771 */
9772static xmlSchemaTypePtr
9773xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009774 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009775{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009776 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009777 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009778 char buf[30];
9779 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009780 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009781
9782 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9783 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009784 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009785 type = ctxt->ctxtType;
9786 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009787
9788 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009789 * TODO: Is the container needed at all? the anonymous
9790 * items inside should generate unique names already.
9791 */
9792 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009793 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009794 /*
9795 * Check for illegal attributes.
9796 */
9797 attr = node->properties;
9798 while (attr != NULL) {
9799 if (attr->ns == NULL) {
9800 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9801 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009802 xmlSchemaPIllegalAttrErr(ctxt,
9803 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9804 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009805 }
9806 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009807 xmlSchemaPIllegalAttrErr(ctxt,
9808 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9809 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009810 }
9811 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009812 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009813 /*
9814 * Extract and validate attributes.
9815 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009816 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009817 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009818 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009819 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009820 /*
9821 * SPEC (1.2) "otherwise (<restriction> has no <simpleType> "
9822 * among its [children]), the simple type definition which is
9823 * the {content type} of the type definition ·resolved· to by
9824 * the ·actual value· of the base [attribute]"
9825 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009826 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009827 NULL, NULL, node, "base",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009828 &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009829 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009830 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009831 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009832 XML_SCHEMAP_S4S_ATTR_MISSING,
9833 type, node, "base", NULL);
9834 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009835 /*
9836 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009837 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009838 child = node->children;
9839 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009840 /*
9841 * Add the annotation to the simple type ancestor.
9842 */
9843 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9844 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009845 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009846 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009847 oldcontainer = ctxt->container;
9848 ctxt->container = container;
9849 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9850 /*
9851 * Corresponds to <simpleType><restriction><simpleType>.
9852 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009853 if (IS_SCHEMA(child, "simpleType")) {
9854 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009855 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009856 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009857 * Either the base [attribute] or the simpleType [child] of the
9858 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +00009859 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009860 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009861 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009862 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009863 "The attribute 'base' and the <simpleType> child are "
9864 "mutually exclusive", NULL);
9865 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009866 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009867 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009868 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009869 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009870 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009871 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009872 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9873 NULL, NULL, node, child,
9874 "Either the attribute 'base' or a <simpleType> child "
9875 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009876 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009877 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9878 /*
9879 * Corresponds to <complexType><complexContent><restriction>...
9880 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009881 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009882 * Model groups <all>, <choice> and <sequence>.
9883 */
9884 if (IS_SCHEMA(child, "all")) {
9885 type->subtypes = (xmlSchemaTypePtr)
9886 xmlSchemaParseModelGroup(ctxt, schema, child,
9887 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009888 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009889 } else if (IS_SCHEMA(child, "choice")) {
9890 type->subtypes = (xmlSchemaTypePtr)
9891 xmlSchemaParseModelGroup(ctxt,
9892 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9893 child = child->next;
9894 } else if (IS_SCHEMA(child, "sequence")) {
9895 type->subtypes = (xmlSchemaTypePtr)
9896 xmlSchemaParseModelGroup(ctxt, schema, child,
9897 XML_SCHEMA_TYPE_SEQUENCE, 1);
9898 child = child->next;
9899 /*
9900 * Model group reference <group>.
9901 */
9902 } else if (IS_SCHEMA(child, "group")) {
9903 type->subtypes = (xmlSchemaTypePtr)
9904 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9905 child = child->next;
9906 }
9907 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009908 /*
9909 * Corresponds to <complexType><simpleContent><restriction>...
9910 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009911 * "1.1 the simple type definition corresponding to the <simpleType>
9912 * among the [children] of <restriction> if there is one;"
9913 */
9914 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009915 /*
9916 * We will store the to-be-restricted simple type in
9917 * type->contentTypeDef *temporarily*.
9918 */
9919 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009920 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009921 if ( type->contentTypeDef == NULL)
9922 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009923 child = child->next;
9924 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009925 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009926
9927 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009928 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009929 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009930 /*
9931 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009932 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009933 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009934
Daniel Veillard01fa6152004-06-29 17:04:39 +00009935 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009936 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009937 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009938 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009939 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9940 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009941 * *Single Facet Value*
9942 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009943 while ((IS_SCHEMA(child, "minInclusive")) ||
9944 (IS_SCHEMA(child, "minExclusive")) ||
9945 (IS_SCHEMA(child, "maxInclusive")) ||
9946 (IS_SCHEMA(child, "maxExclusive")) ||
9947 (IS_SCHEMA(child, "totalDigits")) ||
9948 (IS_SCHEMA(child, "fractionDigits")) ||
9949 (IS_SCHEMA(child, "pattern")) ||
9950 (IS_SCHEMA(child, "enumeration")) ||
9951 (IS_SCHEMA(child, "whiteSpace")) ||
9952 (IS_SCHEMA(child, "length")) ||
9953 (IS_SCHEMA(child, "maxLength")) ||
9954 (IS_SCHEMA(child, "minLength"))) {
9955 facet = xmlSchemaParseFacet(ctxt, schema, child);
9956 if (facet != NULL) {
9957 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009958 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009959 else
9960 lastfacet->next = facet;
9961 lastfacet = facet;
9962 lastfacet->next = NULL;
9963 }
9964 child = child->next;
9965 }
9966 /*
9967 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009968 */
9969 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009970 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
9971
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009972 facet = type->facets;
9973 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009974 facetLink = (xmlSchemaFacetLinkPtr)
9975 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +00009976 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009977 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009978 xmlFree(facetLink);
9979 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009980 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009981 facetLink->facet = facet;
9982 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009983 if (lastFacetLink == NULL)
9984 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009985 else
9986 lastFacetLink->next = facetLink;
9987 lastFacetLink = facetLink;
9988 facet = facet->next;
9989 } while (facet != NULL);
9990 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009991 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009992 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
9993 /*
9994 * Attribute uses/declarations.
9995 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009996 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009997 /*
9998 * Attribute wildcard.
9999 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010000 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010001 type->attributeWildcard =
10002 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010003 child = child->next;
10004 }
10005 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010006 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010007 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10008 xmlSchemaPContentErr(ctxt,
10009 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010010 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010011 "annotation?, (group | all | choice | sequence)?, "
10012 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010013 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010014 xmlSchemaPContentErr(ctxt,
10015 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010016 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010017 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10018 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10019 "length | minLength | maxLength | enumeration | whiteSpace | "
10020 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10021 } else {
10022 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010023 xmlSchemaPContentErr(ctxt,
10024 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010025 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010026 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10027 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10028 "length | minLength | maxLength | enumeration | whiteSpace | "
10029 "pattern)*))");
10030 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010031 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010032 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010033 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010034}
10035
10036/**
10037 * xmlSchemaParseExtension:
10038 * @ctxt: a schema validation context
10039 * @schema: the schema being built
10040 * @node: a subtree containing XML Schema informations
10041 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010042 * Parses an <extension>, which is found inside a
10043 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010044 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010045 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010046 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010047 */
10048static xmlSchemaTypePtr
10049xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010050 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010051{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010052 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010053 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010054 char buf[30];
10055 const xmlChar *oldcontainer, *container;
10056 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010057
10058 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10059 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010060 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010061 type = ctxt->ctxtType;
10062 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010063
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010064 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10065 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10066 /*
10067 * Check for illegal attributes.
10068 */
10069 attr = node->properties;
10070 while (attr != NULL) {
10071 if (attr->ns == NULL) {
10072 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10073 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010074 xmlSchemaPIllegalAttrErr(ctxt,
10075 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10076 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010077 }
10078 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010079 xmlSchemaPIllegalAttrErr(ctxt,
10080 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10081 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010082 }
10083 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010084 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010085
10086 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010087
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010088 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010089 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010090 */
10091 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010092 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10093 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010094 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010095 XML_SCHEMAP_S4S_ATTR_MISSING,
10096 NULL, node, "base", NULL);
10097 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010098 /*
10099 * And now for the children...
10100 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010101 child = node->children;
10102 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010103 /*
10104 * Add the annotation to the type ancestor.
10105 */
10106 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10107 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010108 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010109 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010110 oldcontainer = ctxt->container;
10111 ctxt->container = container;
10112 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10113 /*
10114 * Corresponds to <complexType><complexContent><extension>... and:
10115 *
10116 * Model groups <all>, <choice>, <sequence> and <group>.
10117 */
10118 if (IS_SCHEMA(child, "all")) {
10119 type->subtypes = (xmlSchemaTypePtr)
10120 xmlSchemaParseModelGroup(ctxt, schema,
10121 child, XML_SCHEMA_TYPE_ALL, 1);
10122 child = child->next;
10123 } else if (IS_SCHEMA(child, "choice")) {
10124 type->subtypes = (xmlSchemaTypePtr)
10125 xmlSchemaParseModelGroup(ctxt, schema,
10126 child, XML_SCHEMA_TYPE_CHOICE, 1);
10127 child = child->next;
10128 } else if (IS_SCHEMA(child, "sequence")) {
10129 type->subtypes = (xmlSchemaTypePtr)
10130 xmlSchemaParseModelGroup(ctxt, schema,
10131 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10132 child = child->next;
10133 } else if (IS_SCHEMA(child, "group")) {
10134 type->subtypes = (xmlSchemaTypePtr)
10135 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10136 child = child->next;
10137 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010138 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010139 if (child != NULL) {
10140 /*
10141 * Attribute uses/declarations.
10142 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010143 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010144 /*
10145 * Attribute wildcard.
10146 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010147 if (IS_SCHEMA(child, "anyAttribute")) {
10148 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010149 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10150 child = child->next;
10151 }
10152 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010153 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010154 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10155 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010156 xmlSchemaPContentErr(ctxt,
10157 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010158 NULL, NULL, node, child, NULL,
10159 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010160 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010161 } else {
10162 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010163 xmlSchemaPContentErr(ctxt,
10164 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010165 NULL, NULL, node, child, NULL,
10166 "(annotation?, ((attribute | attributeGroup)*, "
10167 "anyAttribute?))");
10168 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010169 }
10170 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010171 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010172}
10173
10174/**
10175 * xmlSchemaParseSimpleContent:
10176 * @ctxt: a schema validation context
10177 * @schema: the schema being built
10178 * @node: a subtree containing XML Schema informations
10179 *
10180 * parse a XML schema SimpleContent definition
10181 * *WARNING* this interface is highly subject to change
10182 *
10183 * Returns the type definition or NULL in case of error
10184 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010185static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010186xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10187 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010188{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010189 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010190 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010191 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010192
10193 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010194 return (-1);
10195 /* Not a component, don't create it. */
10196 type = ctxt->ctxtType;
10197 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10198 /*
10199 * Check for illegal attributes.
10200 */
10201 attr = node->properties;
10202 while (attr != NULL) {
10203 if (attr->ns == NULL) {
10204 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010205 xmlSchemaPIllegalAttrErr(ctxt,
10206 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10207 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010208 }
10209 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010210 xmlSchemaPIllegalAttrErr(ctxt,
10211 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10212 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010213 }
10214 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010215 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010216
10217 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010218
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010219 /*
10220 * And now for the children...
10221 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010222 child = node->children;
10223 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010224 /*
10225 * Add the annotation to the complex type ancestor.
10226 */
10227 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10228 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010229 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010230 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010231 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010232 xmlSchemaParseRestriction(ctxt, schema, child,
10233 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010234 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010235 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010236 xmlSchemaParseExtension(ctxt, schema, child,
10237 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010238 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010239 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010240 if (child != NULL) {
10241 xmlSchemaPContentErr(ctxt,
10242 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010243 NULL, NULL, node, child, NULL,
10244 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010245 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010246 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010247}
10248
10249/**
10250 * xmlSchemaParseComplexContent:
10251 * @ctxt: a schema validation context
10252 * @schema: the schema being built
10253 * @node: a subtree containing XML Schema informations
10254 *
10255 * parse a XML schema ComplexContent definition
10256 * *WARNING* this interface is highly subject to change
10257 *
10258 * Returns the type definition or NULL in case of error
10259 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010260static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010261xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10262 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010263{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010264 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010265 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010266 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010267
10268 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010269 return (-1);
10270 /* Not a component, don't create it. */
10271 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010272 /*
10273 * Check for illegal attributes.
10274 */
10275 attr = node->properties;
10276 while (attr != NULL) {
10277 if (attr->ns == NULL) {
10278 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010279 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010280 {
10281 xmlSchemaPIllegalAttrErr(ctxt,
10282 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10283 NULL, NULL, attr);
10284 }
10285 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10286 xmlSchemaPIllegalAttrErr(ctxt,
10287 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10288 NULL, NULL, attr);
10289 }
10290 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010291 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010292
10293 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10294
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010295 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010296 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010297 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010298 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10299 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10300 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010301 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010302 child = node->children;
10303 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010304 /*
10305 * Add the annotation to the complex type ancestor.
10306 */
10307 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10308 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010309 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010310 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010311 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010312 xmlSchemaParseRestriction(ctxt, schema, child,
10313 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010314 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010315 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010316 xmlSchemaParseExtension(ctxt, schema, child,
10317 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010318 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010319 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010320 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010321 xmlSchemaPContentErr(ctxt,
10322 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10323 NULL, NULL, node, child,
10324 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010325 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010326 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010327}
10328
10329/**
10330 * xmlSchemaParseComplexType:
10331 * @ctxt: a schema validation context
10332 * @schema: the schema being built
10333 * @node: a subtree containing XML Schema informations
10334 *
10335 * parse a XML schema Complex Type definition
10336 * *WARNING* this interface is highly subject to change
10337 *
10338 * Returns the type definition or NULL in case of error
10339 */
10340static xmlSchemaTypePtr
10341xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010342 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010343{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010344 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010345 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010346 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010347 xmlAttrPtr attr;
10348 const xmlChar *attrValue;
10349 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010350 char buf[40];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010351 int final = 0, block = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010352
Daniel Veillard4255d502002-04-16 15:50:10 +000010353
10354 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10355 return (NULL);
10356
Daniel Veillard01fa6152004-06-29 17:04:39 +000010357 ctxtType = ctxt->ctxtType;
10358
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010359 if (topLevel) {
10360 attr = xmlSchemaGetPropNode(node, "name");
10361 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010362 xmlSchemaPMissingAttrErr(ctxt,
10363 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010364 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010365 } else if (xmlSchemaPValAttrNode(ctxt,
10366 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010367 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10368 return (NULL);
10369 }
10370 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010371
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010372 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010373 /*
10374 * Parse as local complex type definition.
10375 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010376 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010377 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10378 if (type == NULL)
10379 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010380 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010381 type->node = node;
10382 type->type = XML_SCHEMA_TYPE_COMPLEX;
10383 /*
10384 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010385 */
10386 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010387 /*
10388 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010389 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010390 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010391 if (type == NULL)
10392 return (NULL);
10393 type->node = node;
10394 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010395 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010396 }
10397 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010398 /*
10399 * Handle attributes.
10400 */
10401 attr = node->properties;
10402 while (attr != NULL) {
10403 if (attr->ns == NULL) {
10404 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10405 /*
10406 * Attribute "id".
10407 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010408 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10409 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010410 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10411 /*
10412 * Attribute "mixed".
10413 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010414 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010415 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010416 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10417 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010418 /*
10419 * Attributes of global complex type definitions.
10420 */
10421 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10422 /* Pass. */
10423 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10424 /*
10425 * Attribute "abstract".
10426 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010427 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10428 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010429 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10430 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10431 /*
10432 * Attribute "final".
10433 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010434 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010435 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010436 if (xmlSchemaPValAttrBlockFinal(attrValue,
10437 &(type->flags),
10438 -1,
10439 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10440 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10441 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010442 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010443 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010444 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010445 type, (xmlNodePtr) attr, NULL,
10446 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010447 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010448 } else
10449 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010450 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10451 /*
10452 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010453 */
10454 attrValue = xmlSchemaGetNodeContent(ctxt,
10455 (xmlNodePtr) attr);
10456 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010457 -1,
10458 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010459 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010460 -1, -1, -1) != 0) {
10461 xmlSchemaPSimpleTypeErr(ctxt,
10462 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010463 type, (xmlNodePtr) attr, NULL,
10464 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010465 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010466 } else
10467 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010468 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010469 xmlSchemaPIllegalAttrErr(ctxt,
10470 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010471 &des, type, attr);
10472 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010473 } else {
10474 xmlSchemaPIllegalAttrErr(ctxt,
10475 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010476 &des, type, attr);
10477 }
10478 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010479 xmlSchemaPIllegalAttrErr(ctxt,
10480 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10481 &des, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010482 }
10483 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010484 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010485 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010486 /*
10487 * Apply default "block" values.
10488 */
10489 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10490 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10491 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10492 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10493 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010494 if (! final) {
10495 /*
10496 * Apply default "block" values.
10497 */
10498 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
10499 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
10500 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
10501 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
10502 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010503 /*
10504 * And now for the children...
10505 */
10506 oldcontainer = ctxt->container;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010507 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010508 child = node->children;
10509 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010510 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10511 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010512 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010513 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010514 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010515 /*
10516 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010517 * Specifying mixed='true' when the <simpleContent>
10518 * alternative is chosen has no effect
10519 */
William M. Bracke7091952004-05-11 15:09:58 +000010520 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10521 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010522 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010523 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010524 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010525 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10526 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010527 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010528 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010529 /*
10530 * SPEC
10531 * "...the third alternative (neither <simpleContent> nor
10532 * <complexContent>) is chosen. This case is understood as shorthand
10533 * for complex content restricting the ·ur-type definition·, and the
10534 * details of the mappings should be modified as necessary.
10535 */
10536 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10537 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010538 /*
10539 * Parse model groups.
10540 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010541 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010542 type->subtypes = (xmlSchemaTypePtr)
10543 xmlSchemaParseModelGroup(ctxt, schema, child,
10544 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010545 child = child->next;
10546 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010547 type->subtypes = (xmlSchemaTypePtr)
10548 xmlSchemaParseModelGroup(ctxt, schema, child,
10549 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010550 child = child->next;
10551 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010552 type->subtypes = (xmlSchemaTypePtr)
10553 xmlSchemaParseModelGroup(ctxt, schema, child,
10554 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010555 child = child->next;
10556 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010557 type->subtypes = (xmlSchemaTypePtr)
10558 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010559 child = child->next;
10560 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010561 /*
10562 * Parse attribute decls/refs.
10563 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010564 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010565 /*
10566 * Parse attribute wildcard.
10567 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010568 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010569 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10570 child = child->next;
10571 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010572 }
10573 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010574 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010575 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010576 &des, type, node, child,
10577 NULL, "(annotation?, (simpleContent | complexContent | "
10578 "((group | all | choice | sequence)?, ((attribute | "
10579 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010580 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010581 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010582 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010583 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010584 return (type);
10585}
10586
Daniel Veillard4255d502002-04-16 15:50:10 +000010587/**
10588 * xmlSchemaParseSchema:
10589 * @ctxt: a schema validation context
10590 * @node: a subtree containing XML Schema informations
10591 *
10592 * parse a XML schema definition from a node set
10593 * *WARNING* this interface is highly subject to change
10594 *
10595 * Returns the internal XML Schema structure built from the resource or
10596 * NULL in case of error
10597 */
10598static xmlSchemaPtr
10599xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10600{
10601 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010602 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010603 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010604 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010605
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010606 /*
10607 * This one is called by xmlSchemaParse only and is used if
10608 * the schema to be parsed was specified via the API; i.e. not
10609 * automatically by the validated instance document.
10610 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010611 if ((ctxt == NULL) || (node == NULL))
10612 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010613 nberrors = ctxt->nberrors;
10614 ctxt->nberrors = 0;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010615 ctxt->isS4S = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010616 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010617 xmlSchemaImportPtr import;
10618
Daniel Veillard4255d502002-04-16 15:50:10 +000010619 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010620 if (schema == NULL)
10621 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010622 attr = xmlSchemaGetPropNode(node, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +000010623 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010624 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010625 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10626 /*
10627 * TODO: Should we proceed with an invalid target namespace?
10628 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010629 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010630 if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
10631 /*
10632 * We are parsing the schema for schema!
10633 */
10634 ctxt->isS4S = 1;
10635 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010636 } else {
10637 schema->targetNamespace = NULL;
10638 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010639 /*
10640 * Add the current ns name and location to the import table;
10641 * this is needed to have a consistent mechanism, regardless
10642 * if all schemata are constructed dynamically fired by the
10643 * instance or if the schema to be used was specified via
10644 * the API.
10645 */
10646 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10647 schema->targetNamespace);
10648 if (import == NULL) {
10649 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10650 NULL, NULL, (xmlNodePtr) ctxt->doc,
10651 "Internal error: xmlSchemaParseSchema, "
10652 "failed to add an import entry", NULL);
10653 xmlSchemaFree(schema);
10654 schema = NULL;
10655 return (NULL);
10656 }
10657 import->schemaLocation = ctxt->URL;
10658 /*
10659 * NOTE: We won't set the doc here, otherwise it will be freed
10660 * if the import struct is freed.
10661 * import->doc = ctxt->doc;
10662 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010663 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010664 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10665 } else {
10666 xmlDocPtr doc;
10667
10668 doc = node->doc;
10669
10670 if ((doc != NULL) && (doc->URL != NULL)) {
10671 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10672 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010673 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010674 } else {
10675 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10676 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010677 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010678 }
10679 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010680 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010681 if (ctxt->nberrors != 0) {
10682 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010683 xmlSchemaFree(schema);
10684 schema = NULL;
10685 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010686 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010687 if (schema != NULL)
10688 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010689 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010690#ifdef DEBUG
10691 if (schema == NULL)
10692 xmlGenericError(xmlGenericErrorContext,
10693 "xmlSchemaParse() failed\n");
10694#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010695 return (schema);
10696}
10697
10698/************************************************************************
10699 * *
10700 * Validating using Schemas *
10701 * *
10702 ************************************************************************/
10703
10704/************************************************************************
10705 * *
10706 * Reading/Writing Schemas *
10707 * *
10708 ************************************************************************/
10709
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010710#if 0 /* Will be enabled if it is clear what options are needed. */
10711/**
10712 * xmlSchemaParserCtxtSetOptions:
10713 * @ctxt: a schema parser context
10714 * @options: a combination of xmlSchemaParserOption
10715 *
10716 * Sets the options to be used during the parse.
10717 *
10718 * Returns 0 in case of success, -1 in case of an
10719 * API error.
10720 */
10721static int
10722xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10723 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010724
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010725{
10726 int i;
10727
10728 if (ctxt == NULL)
10729 return (-1);
10730 /*
10731 * WARNING: Change the start value if adding to the
10732 * xmlSchemaParseOption.
10733 */
10734 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10735 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010736 return (-1);
10737 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010738 }
10739 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010740 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010741}
10742
10743/**
10744 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010745 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010746 *
10747 * Returns the option combination of the parser context.
10748 */
10749static int
10750xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010751
10752{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010753 if (ctxt == NULL)
10754 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010755 else
10756 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010757}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010758#endif
10759
Daniel Veillard4255d502002-04-16 15:50:10 +000010760/**
10761 * xmlSchemaNewParserCtxt:
10762 * @URL: the location of the schema
10763 *
10764 * Create an XML Schemas parse context for that file/resource expected
10765 * to contain an XML Schemas file.
10766 *
10767 * Returns the parser context or NULL in case of error
10768 */
10769xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010770xmlSchemaNewParserCtxt(const char *URL)
10771{
Daniel Veillard4255d502002-04-16 15:50:10 +000010772 xmlSchemaParserCtxtPtr ret;
10773
10774 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010775 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010776
10777 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10778 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010779 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010780 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010781 return (NULL);
10782 }
10783 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010784 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010785 ret->dict = xmlDictCreate();
10786 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010787 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010788 return (ret);
10789}
10790
10791/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010792 * xmlSchemaNewMemParserCtxt:
10793 * @buffer: a pointer to a char array containing the schemas
10794 * @size: the size of the array
10795 *
10796 * Create an XML Schemas parse context for that memory buffer expected
10797 * to contain an XML Schemas file.
10798 *
10799 * Returns the parser context or NULL in case of error
10800 */
10801xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010802xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10803{
Daniel Veillard6045c902002-10-09 21:13:59 +000010804 xmlSchemaParserCtxtPtr ret;
10805
10806 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010807 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010808
10809 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10810 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010811 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010812 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010813 return (NULL);
10814 }
10815 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10816 ret->buffer = buffer;
10817 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010818 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010819 return (ret);
10820}
10821
10822/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010823 * xmlSchemaNewDocParserCtxt:
10824 * @doc: a preparsed document tree
10825 *
10826 * Create an XML Schemas parse context for that document.
10827 * NB. The document may be modified during the parsing process.
10828 *
10829 * Returns the parser context or NULL in case of error
10830 */
10831xmlSchemaParserCtxtPtr
10832xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10833{
10834 xmlSchemaParserCtxtPtr ret;
10835
10836 if (doc == NULL)
10837 return (NULL);
10838
10839 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10840 if (ret == NULL) {
10841 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10842 NULL);
10843 return (NULL);
10844 }
10845 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10846 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010847 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010848 /* The application has responsibility for the document */
10849 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010850
10851 return (ret);
10852}
10853
10854/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010855 * xmlSchemaFreeParserCtxt:
10856 * @ctxt: the schema parser context
10857 *
10858 * Free the resources associated to the schema parser context
10859 */
10860void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010861xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10862{
Daniel Veillard4255d502002-04-16 15:50:10 +000010863 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010864 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010865 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010866 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010867 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010868 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010869 xmlFree(ctxt->assemble);
10870 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010871 if (ctxt->vctxt != NULL) {
10872 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10873 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010874 if (ctxt->localImports != NULL)
10875 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010876 if (ctxt->substGroups != NULL)
10877 xmlHashFree(ctxt->substGroups,
10878 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010879 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010880 xmlFree(ctxt);
10881}
10882
10883/************************************************************************
10884 * *
10885 * Building the content models *
10886 * *
10887 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010888
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010889static void
10890xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000010891 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010892{
Daniel Veillarda980bef2005-07-18 21:34:03 +000010893 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010894 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010895 xmlSchemaSubstGroupPtr substGroup;
10896 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010897
10898 elemDecl = (xmlSchemaElementPtr) particle->children;
10899 /*
10900 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010901 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010902 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000010903 if (end == NULL)
10904 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010905 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
10906 if (substGroup == NULL) {
10907 xmlSchemaPErr(pctxt, GET_NODE(particle),
10908 XML_SCHEMAP_INTERNAL,
10909 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
10910 "declaration is marked having a subst. group but none "
10911 "available.\n", elemDecl->name, NULL);
10912 return;
10913 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000010914 if (counter >= 0) {
10915 /*
10916 * NOTE that we put the declaration in, even if it's abstract,
10917 */
10918 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
10919 xmlAutomataNewTransition2(pctxt->am, tmp, end,
10920 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10921 /*
10922 * Add subst. group members.
10923 */
10924 for (i = 0; i < substGroup->members->nbItems; i++) {
10925 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10926 xmlAutomataNewTransition2(pctxt->am, tmp, end,
10927 member->name, member->targetNamespace, member);
10928 }
10929 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010930 /*
10931 * NOTE that we put the declaration in, even if it's abstract,
10932 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010933 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010934 xmlAutomataNewTransition2(pctxt->am,
10935 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010936 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
10937 /*
10938 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010939 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010940 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010941 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000010942 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
10943 member->name, member->targetNamespace,
10944 1, 1, member);
10945 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010946 }
10947 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010948 xmlAutomataStatePtr hop;
10949 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10950 UNBOUNDED : particle->maxOccurs - 1;
10951 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
10952
10953 counter =
10954 xmlAutomataNewCounter(pctxt->am, minOccurs,
10955 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010956 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010957
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010958 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010959 xmlAutomataNewTransition2(pctxt->am,
10960 start, NULL,
10961 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010962 hop);
10963 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000010964 * Add subst. group members.
10965 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010966 for (i = 0; i < substGroup->members->nbItems; i++) {
10967 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10968 xmlAutomataNewEpsilon(pctxt->am,
10969 xmlAutomataNewTransition2(pctxt->am,
10970 start, NULL,
10971 member->name, member->targetNamespace, member),
10972 hop);
10973 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010974 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
10975 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
10976 }
10977 if (particle->minOccurs == 0)
10978 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010979 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010980}
10981
10982static void
10983xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
10984 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010985{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010986 if (((xmlSchemaElementPtr) particle->children)->flags &
10987 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010988 /*
10989 * Substitution groups.
10990 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000010991 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010992 } else {
10993 xmlSchemaElementPtr elemDecl;
10994 xmlAutomataStatePtr start;
10995
10996 elemDecl = (xmlSchemaElementPtr) particle->children;
10997
10998 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010999 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011000 if (particle->maxOccurs == 1) {
11001 start = ctxt->state;
11002 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011003 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11004 } else if ((particle->maxOccurs >= UNBOUNDED) &&
11005 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011006 /* Special case. */
11007 start = ctxt->state;
11008 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11009 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011010 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011011 } else {
11012 int counter;
11013 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11014 UNBOUNDED : particle->maxOccurs - 1;
11015 int minOccurs = particle->minOccurs < 1 ?
11016 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011017
11018 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011019 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11020 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11021 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11022 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
11023 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
11024 NULL, counter);
11025 }
11026 if (particle->minOccurs == 0)
11027 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
11028 }
11029}
11030
Daniel Veillard4255d502002-04-16 15:50:10 +000011031/**
11032 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011033 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011034 * @particle: the particle component
11035 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011036 *
11037 * Generate the automata sequence needed for that type
11038 */
11039static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011040xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011041 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011042 const xmlChar * name)
11043{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011044 if (particle == NULL) {
11045 xmlSchemaPErr(ctxt, NULL,
11046 XML_SCHEMAP_INTERNAL,
11047 "Internal error: xmlSchemaBuildAContentModel, "
11048 "particle is NULL.\n", NULL, NULL);
11049 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011050 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011051 if (particle->children == NULL) {
11052 xmlSchemaPErr(ctxt, GET_NODE(particle),
11053 XML_SCHEMAP_INTERNAL,
11054 "Internal error: xmlSchemaBuildAContentModel, "
11055 "no term on particle.\n", NULL, NULL);
11056 return;
11057 }
11058
11059 switch (particle->children->type) {
11060 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011061 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011062 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011063 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011064
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011065 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011066
Daniel Veillardc0826a72004-08-10 14:17:33 +000011067 start = ctxt->state;
11068 end = xmlAutomataNewState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011069
11070 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011071 if (wild->any == 1) {
11072 /*
11073 * We need to add both transitions:
11074 *
11075 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011076 */
11077 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011078 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011079 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011080 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11081 /*
11082 * 2. the {"*"} for elements in no namespace.
11083 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011084 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011085 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011086 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011087 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11088
11089 } else if (wild->nsSet != NULL) {
11090 ns = wild->nsSet;
11091 do {
11092 ctxt->state = start;
11093 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011094 ctxt->state, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011095 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11096 ns = ns->next;
11097 } while (ns != NULL);
11098
11099 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011100
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011101 /*
11102 * Lead nodes with the negated namespace to the sink-state
11103 * {"*", "##other"}.
11104 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011105 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011106 BAD_CAST "*", wild->negNsSet->value, wild);
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011107 /*
11108 * Open a door for nodes with any other namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011109 * {"*", "*"}
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011110 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011111 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011112 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011113 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011114 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011115 } else {
11116 int counter;
11117 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011118 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011119 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011120 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011121 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011122
Daniel Veillardc0826a72004-08-10 14:17:33 +000011123 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011124 hop = xmlAutomataNewState(ctxt->am);
11125 if (wild->any == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011126 ctxt->state =
11127 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011128 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011129 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011130 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011131 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011132 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011133 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011134 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011135 ns = wild->nsSet;
11136 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011137 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011138 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011139 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011140 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11141 ns = ns->next;
11142 } while (ns != NULL);
11143
11144 } else if (wild->negNsSet != NULL) {
Daniel Veillard9efc4762005-07-19 14:33:55 +000011145 ctxt->state = xmlAutomataNewNegTrans(ctxt->am,
11146 start, hop, BAD_CAST "*", wild->negNsSet->value,
11147 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011148 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011149 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
11150 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
11151 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011152 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011153 xmlAutomataNewEpsilon(ctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011154 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011155 ctxt->state = end;
11156 break;
11157 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011158 case XML_SCHEMA_TYPE_ELEMENT:
11159 xmlSchemaBuildContentModelForElement(ctxt, particle);
11160 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011161 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011162 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011163
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011164 /*
11165 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011166 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011167 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011168 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11169 sub = particle->children->children;
11170 while (sub != NULL) {
11171 xmlSchemaBuildAContentModel(ctxt,
11172 (xmlSchemaParticlePtr) sub, name);
11173 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011174 }
11175 } else {
11176 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011177
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011178 if (particle->maxOccurs >= UNBOUNDED) {
11179 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011180 xmlAutomataStatePtr tmp;
11181 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011182
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011183 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011184 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011185 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011186
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011187 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011188 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011189
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011190 sub = particle->children->children;
11191 while (sub != NULL) {
11192 xmlSchemaBuildAContentModel(ctxt,
11193 (xmlSchemaParticlePtr) sub, name);
11194 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011195 }
11196 tmp = ctxt->state;
11197 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11198 oldstate, counter);
11199 ctxt->state =
11200 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11201 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011202
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011203 } else {
Daniel Veillardafc05b62005-07-17 06:11:19 +000011204 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
11205 oldstate, NULL);
11206 oldstate = ctxt->state;
11207
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011208 sub = particle->children->children;
11209 while (sub != NULL) {
11210 xmlSchemaBuildAContentModel(ctxt,
11211 (xmlSchemaParticlePtr) sub, name);
11212 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011213 }
11214 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11215 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011216 /*
11217 * epsilon needed to block previous trans from
11218 * being allowed to enter back from another
11219 * construct
11220 */
11221 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
11222 ctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011223 if (particle->minOccurs == 0) {
11224 xmlAutomataNewEpsilon(ctxt->am,
11225 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011226 }
11227 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011228 } else if ((particle->maxOccurs > 1)
11229 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011230 xmlAutomataStatePtr tmp;
11231 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011232
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011233 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011234 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011235 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011236
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011237 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011238 particle->minOccurs - 1,
11239 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011240
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011241 sub = particle->children->children;
11242 while (sub != NULL) {
11243 xmlSchemaBuildAContentModel(ctxt,
11244 (xmlSchemaParticlePtr) sub, name);
11245 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011246 }
11247 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011248 xmlAutomataNewCountedTrans(ctxt->am,
11249 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011250 ctxt->state =
11251 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11252 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011253 if (particle->minOccurs == 0) {
11254 xmlAutomataNewEpsilon(ctxt->am,
11255 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011256 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011257 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011258 sub = particle->children->children;
11259 while (sub != NULL) {
11260 xmlSchemaBuildAContentModel(ctxt,
11261 (xmlSchemaParticlePtr) sub, name);
11262 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011263 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011264 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011265 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11266 ctxt->state);
11267 }
11268 }
11269 }
11270 break;
11271 }
11272 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011273 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011274 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011275
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011276 start = ctxt->state;
11277 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011278
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011279 /*
11280 * iterate over the subtypes and remerge the end with an
11281 * epsilon transition
11282 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011283 if (particle->maxOccurs == 1) {
11284 sub = particle->children->children;
11285 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011286 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011287 xmlSchemaBuildAContentModel(ctxt,
11288 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011289 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011290 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011291 }
11292 } else {
11293 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011294 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011295 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11296 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011297 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011298 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011299
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011300 /*
11301 * use a counter to keep track of the number of transtions
11302 * which went through the choice.
11303 */
11304 counter =
Daniel Veillardafc05b62005-07-17 06:11:19 +000011305 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011306 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011307 base = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011308
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011309 sub = particle->children->children;
11310 while (sub != NULL) {
Daniel Veillardafc05b62005-07-17 06:11:19 +000011311 ctxt->state = base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011312 xmlSchemaBuildAContentModel(ctxt,
11313 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011314 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011315 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000011316 }
Daniel Veillardafc05b62005-07-17 06:11:19 +000011317 xmlAutomataNewEpsilon(ctxt->am, start, base);
11318 xmlAutomataNewCountedTrans(ctxt->am, hop, base, counter);
11319 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011320 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011321 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011322 xmlAutomataNewEpsilon(ctxt->am, start, end);
11323 }
11324 ctxt->state = end;
11325 break;
11326 }
11327 case XML_SCHEMA_TYPE_ALL:{
Daniel Veillarda980bef2005-07-18 21:34:03 +000011328 xmlAutomataStatePtr start, hop;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011329 xmlSchemaParticlePtr sub;
11330 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011331 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011332
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011333 sub = (xmlSchemaParticlePtr) particle->children->children;
11334 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011335 break;
11336 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011337 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011338 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011339
11340 elemDecl = (xmlSchemaElementPtr) sub->children;
11341 if (elemDecl == NULL) {
11342 xmlSchemaPErr(ctxt, NULL,
11343 XML_SCHEMAP_INTERNAL,
11344 "Internal error: xmlSchemaBuildAContentModel, "
11345 "<element> particle a NULL term.\n", NULL, NULL);
11346 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011347 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011348 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011349 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011350 * {particles} of the group must be 0 or 1; this is
11351 * already ensured during the parse of the content of
11352 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011353 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000011354 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
11355 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011356
Daniel Veillarda980bef2005-07-18 21:34:03 +000011357 /*
11358 * This is an abstract group, we need to share
11359 * the same counter for all the element transitions
11360 * derived from the group
11361 */
11362 counter = xmlAutomataNewCounter(ctxt->am,
11363 sub->minOccurs, sub->maxOccurs);
11364 xmlSchemaBuildContentModelForSubstGroup(ctxt,
11365 sub, counter, ctxt->state);
11366 } else {
11367 if ((sub->minOccurs == 1) &&
11368 (sub->maxOccurs == 1)) {
11369 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
11370 ctxt->state,
11371 elemDecl->name,
11372 elemDecl->targetNamespace,
11373 1, 1, elemDecl);
11374 } else if ((sub->minOccurs == 0) &&
11375 (sub->maxOccurs == 1)) {
11376
11377 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
11378 ctxt->state,
11379 elemDecl->name,
11380 elemDecl->targetNamespace,
11381 0,
11382 1,
11383 elemDecl);
11384 }
11385 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011386 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011387 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011388 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011389 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011390 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011391 break;
11392 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011393 default:
11394 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011395 "Internal error: xmlSchemaBuildAContentModel, found "
11396 "unexpected term of type %d in content model of complex "
11397 "type '%s'.\n",
11398 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011399 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011400 }
11401}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011402
Daniel Veillard4255d502002-04-16 15:50:10 +000011403/**
11404 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011405 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011406 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011407 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011408 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011409 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011410 */
11411static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011412xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011413 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011414 const xmlChar * name)
11415{
Daniel Veillard4255d502002-04-16 15:50:10 +000011416 xmlAutomataStatePtr start;
11417
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011418 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11419 (type->contModel != NULL) ||
11420 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11421 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011422 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011423
11424#ifdef DEBUG_CONTENT
11425 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011426 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011427#endif
11428
Daniel Veillard4255d502002-04-16 15:50:10 +000011429 ctxt->am = xmlNewAutomata();
11430 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011431 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011432 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011433 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011434 }
11435 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011436 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011437 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011438 type->contModel = xmlAutomataCompile(ctxt->am);
11439 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011440 xmlSchemaPCustomErr(ctxt,
11441 XML_SCHEMAP_INTERNAL,
11442 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011443 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011444 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011445 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011446 XML_SCHEMAP_NOT_DETERMINISTIC,
11447 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011448 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011449 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011450 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011451#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011452 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011453 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011454 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011455#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011456 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011457 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011458 xmlFreeAutomata(ctxt->am);
11459 ctxt->am = NULL;
11460}
11461
11462/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011463 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011464 * @elem: the schema element context
11465 * @ctxt: the schema parser context
11466 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011467 * Resolves the references of an element declaration
11468 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011469 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011470 */
11471static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011472xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011473 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011474 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011475 const xmlChar * context ATTRIBUTE_UNUSED,
11476 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011477{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011478 if ((ctxt == NULL) || (elemDecl == NULL) ||
11479 ((elemDecl != NULL) &&
11480 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011481 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011482 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011483
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011484 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011485 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011486
11487 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011488 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011489 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011490 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011491 elemDecl->namedTypeNs);
11492 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011493 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011494 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011495 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011496 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011497 XML_SCHEMA_TYPE_BASIC, "type definition");
11498 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011499 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011500 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011501 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011502 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011503
Daniel Veillardc0826a72004-08-10 14:17:33 +000011504 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011505 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011506 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011507 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011508 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11509 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011510 if (substHead == NULL) {
11511 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011512 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011513 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011514 "substitutionGroup", elemDecl->substGroup,
11515 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011516 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011517 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011518 /*
11519 * Set the "substitution group affiliation".
11520 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011521 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011522 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011523 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011524 * (type definition)...otherwise the {type definition} of the
11525 * element declaration ·resolved· to by the ·actual value· of
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011526 * the substitutionGroup [attribute], if present
11527 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011528 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011529 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011530 }
11531 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011532 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11533 (elemDecl->substGroup == NULL))
11534 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011535}
11536
11537/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011538 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011539 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011540 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011541 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011542 * Checks and builds the "member type definitions" property of the union
11543 * simple type. This handles part (1), part (2) is done in
11544 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11545 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011546 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011547 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011548static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011549xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11550 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011551{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011552
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011553 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011554 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011555
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011556 /*
11557 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
11558 * define the explicit members as the type definitions ·resolved·
11559 * to by the items in the ·actual value· of the memberTypes [attribute],
11560 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011561 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011562 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011563 /*
11564 * Resolve references.
11565 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011566 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011567 lastLink = NULL;
11568 while (link != NULL) {
11569 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011570
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011571 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11572 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11573
11574 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11575 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11576 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011577 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011578 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11579 /*
11580 * Remove the member type link.
11581 */
11582 if (lastLink == NULL)
11583 type->memberTypes = link->next;
11584 else
11585 lastLink->next = link->next;
11586 newLink = link;
11587 link = link->next;
11588 xmlFree(newLink);
11589 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011590 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011591 lastLink = link;
11592 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011593 }
11594 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011595 /*
11596 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011597 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011598 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011599 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011600 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11601 if (link == NULL) {
11602 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11603 return (-1);
11604 }
11605 link->type = memberType;
11606 link->next = NULL;
11607 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011608 type->memberTypes = link;
11609 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000011610 lastLink->next = link;
11611 lastLink = link;
11612 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011613 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011614 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011615}
11616
Daniel Veillard4255d502002-04-16 15:50:10 +000011617/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011618 * xmlSchemaIsDerivedFromBuiltInType:
11619 * @ctxt: the schema parser context
11620 * @type: the type definition
11621 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011622 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011623 *
11624 * Returns 1 if the type has the given value type, or
11625 * is derived from such a type.
11626 */
William M. Brack803812b2004-06-03 02:11:24 +000011627static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011628xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011629{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011630 if (type == NULL)
11631 return (0);
11632 if (IS_COMPLEX_TYPE(type))
11633 return (0);
11634 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11635 if (type->builtInType == valType)
11636 return(1);
11637 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11638 (type->builtInType == XML_SCHEMAS_ANYTYPE))
11639 return (0);
11640 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11641 } else
11642 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000011643
11644 return (0);
11645}
11646
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011647#if 0
11648/**
11649 * xmlSchemaIsDerivedFromBuiltInType:
11650 * @ctxt: the schema parser context
11651 * @type: the type definition
11652 * @valType: the value type
11653 *
11654 *
11655 * Returns 1 if the type has the given value type, or
11656 * is derived from such a type.
11657 */
11658static int
11659xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
11660{
11661 if (type == NULL)
11662 return (0);
11663 if (IS_COMPLEX_TYPE(type))
11664 return (0);
11665 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11666 if (type->builtInType == valType)
11667 return(1);
11668 return (0);
11669 } else
11670 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11671
11672 return (0);
11673}
11674#endif
11675
11676static xmlSchemaTypePtr
11677xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
11678{
11679 if (type == NULL)
11680 return (NULL);
11681 if (IS_COMPLEX_TYPE(type))
11682 return (NULL);
11683 if (type->type == XML_SCHEMA_TYPE_BASIC)
11684 return(type);
11685 else
11686 return(xmlSchemaQueryBuiltInType(type->subtypes));
11687
11688 return (NULL);
11689}
11690
Daniel Veillard3646d642004-06-02 19:19:14 +000011691/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011692 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011693 * @type: the simpleType definition
11694 *
11695 * Returns the primitive type of the given type or
11696 * NULL in case of error.
11697 */
11698static xmlSchemaTypePtr
11699xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11700{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011701
Daniel Veillard01fa6152004-06-29 17:04:39 +000011702 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011703 /*
11704 * Note that anySimpleType is actually not a primitive type
11705 * but we need that here.
11706 */
11707 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11708 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011709 return (type);
11710 type = type->baseType;
11711 }
11712
11713 return (NULL);
11714}
11715
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011716#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011717/**
11718 * xmlSchemaGetBuiltInTypeAncestor:
11719 * @type: the simpleType definition
11720 *
11721 * Returns the primitive type of the given type or
11722 * NULL in case of error.
11723 */
11724static xmlSchemaTypePtr
11725xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11726{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011727 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011728 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011729 while (type != NULL) {
11730 if (type->type == XML_SCHEMA_TYPE_BASIC)
11731 return (type);
11732 type = type->baseType;
11733 }
11734
11735 return (NULL);
11736}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011737#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011738
Daniel Veillard01fa6152004-06-29 17:04:39 +000011739/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011740 * xmlSchemaBuildAttributeUsesOwned:
11741 * @ctxt: the schema parser context
11742 * @type: the complex type definition
11743 * @cur: the attribute declaration list
11744 * @lastUse: the top of the attribute use list
11745 *
11746 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011747 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000011748 * xmlSchemaBuildAttributeValidation only.
11749 */
11750static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011751xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011752 xmlSchemaAttributePtr cur,
11753 xmlSchemaAttributeLinkPtr *uses,
11754 xmlSchemaAttributeLinkPtr *lastUse)
11755{
11756 xmlSchemaAttributeLinkPtr tmp;
11757 while (cur != NULL) {
11758 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011759 /*
11760 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11761 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000011762 * <attributeGroup> [children], if any."
11763 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011764 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11765 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Daniel Veillard3646d642004-06-02 19:19:14 +000011766 lastUse) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011767 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011768 }
11769 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011770 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000011771 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011772 */
11773 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000011774 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11775 if (tmp == NULL) {
11776 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11777 return (-1);
11778 }
11779 tmp->attr = cur;
11780 tmp->next = NULL;
11781 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011782 *uses = tmp;
11783 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011784 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011785 *lastUse = tmp;
11786 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011787 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011788 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011789 return (0);
11790}
11791
Daniel Veillard50355f02004-06-08 17:52:16 +000011792/**
11793 * xmlSchemaCloneWildcardNsConstraints:
11794 * @ctxt: the schema parser context
11795 * @dest: the destination wildcard
11796 * @source: the source wildcard
11797 *
11798 * Clones the namespace constraints of source
11799 * and assignes them to dest.
11800 * Returns -1 on internal error, 0 otherwise.
11801 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011802static int
11803xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11804 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011805 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000011806{
11807 xmlSchemaWildcardNsPtr cur, tmp, last;
11808
11809 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011810 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011811 (*dest)->any = source->any;
11812 cur = source->nsSet;
11813 last = NULL;
11814 while (cur != NULL) {
11815 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11816 if (tmp == NULL)
11817 return(-1);
11818 tmp->value = cur->value;
11819 if (last == NULL)
11820 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011821 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011822 last->next = tmp;
11823 last = tmp;
11824 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011825 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011826 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011827 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000011828 if (source->negNsSet != NULL) {
11829 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11830 if ((*dest)->negNsSet == NULL)
11831 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011832 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000011833 } else
11834 (*dest)->negNsSet = NULL;
11835 return(0);
11836}
11837
Daniel Veillard50355f02004-06-08 17:52:16 +000011838/**
11839 * xmlSchemaUnionWildcards:
11840 * @ctxt: the schema parser context
11841 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011842 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000011843 *
11844 * Unions the namespace constraints of the given wildcards.
11845 * @completeWild will hold the resulting union.
11846 * Returns a positive error code on failure, -1 in case of an
11847 * internal error, 0 otherwise.
11848 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011849static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011850xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011851 xmlSchemaWildcardPtr completeWild,
11852 xmlSchemaWildcardPtr curWild)
11853{
11854 xmlSchemaWildcardNsPtr cur, curB, tmp;
11855
11856 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011857 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000011858 * value.
11859 */
11860 if ((completeWild->any == curWild->any) &&
11861 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11862 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011863
Daniel Veillard3646d642004-06-02 19:19:14 +000011864 if ((completeWild->negNsSet == NULL) ||
11865 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011866
Daniel Veillard3646d642004-06-02 19:19:14 +000011867 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011868 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011869
11870 /*
11871 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000011872 */
11873 cur = completeWild->nsSet;
11874 while (cur != NULL) {
11875 found = 0;
11876 curB = curWild->nsSet;
11877 while (curB != NULL) {
11878 if (cur->value == curB->value) {
11879 found = 1;
11880 break;
11881 }
11882 curB = curB->next;
11883 }
11884 if (!found)
11885 break;
11886 cur = cur->next;
11887 }
11888 if (found)
11889 return(0);
11890 } else
11891 return(0);
11892 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011893 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011894 /*
11895 * 2 If either O1 or O2 is any, then any must be the value
11896 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011897 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011898 if (completeWild->any == 0) {
11899 completeWild->any = 1;
11900 if (completeWild->nsSet != NULL) {
11901 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11902 completeWild->nsSet = NULL;
11903 }
11904 if (completeWild->negNsSet != NULL) {
11905 xmlFree(completeWild->negNsSet);
11906 completeWild->negNsSet = NULL;
11907 }
11908 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011909 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011910 }
11911 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011912 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000011913 * then the union of those sets must be the value.
11914 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011915 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011916 int found;
11917 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011918
Daniel Veillard3646d642004-06-02 19:19:14 +000011919 cur = curWild->nsSet;
11920 start = completeWild->nsSet;
11921 while (cur != NULL) {
11922 found = 0;
11923 curB = start;
11924 while (curB != NULL) {
11925 if (cur->value == curB->value) {
11926 found = 1;
11927 break;
11928 }
11929 curB = curB->next;
11930 }
11931 if (!found) {
11932 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011933 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011934 return (-1);
11935 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011936 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000011937 completeWild->nsSet = tmp;
11938 }
11939 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011940 }
11941
Daniel Veillard3646d642004-06-02 19:19:14 +000011942 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011943 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011944 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011945 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000011946 * or ·absent·), then a pair of not and ·absent· must be the value.
11947 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011948 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011949 (curWild->negNsSet != NULL) &&
11950 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11951 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011952
11953 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011954 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011955 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011956 * 5.
11957 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011958 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011959 (completeWild->negNsSet->value != NULL) &&
11960 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011961 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011962 (curWild->negNsSet->value != NULL) &&
11963 (completeWild->nsSet != NULL))) {
11964
11965 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011966
Daniel Veillard3646d642004-06-02 19:19:14 +000011967 if (completeWild->nsSet != NULL) {
11968 cur = completeWild->nsSet;
11969 curB = curWild->negNsSet;
11970 } else {
11971 cur = curWild->nsSet;
11972 curB = completeWild->negNsSet;
11973 }
11974 nsFound = 0;
11975 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011976 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011977 absentFound = 1;
11978 else if (cur->value == curB->value)
11979 nsFound = 1;
11980 if (nsFound && absentFound)
11981 break;
11982 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011983 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011984
11985 if (nsFound && absentFound) {
11986 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011987 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000011988 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011989 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011990 completeWild->any = 1;
11991 if (completeWild->nsSet != NULL) {
11992 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11993 completeWild->nsSet = NULL;
11994 }
11995 if (completeWild->negNsSet != NULL) {
11996 xmlFree(completeWild->negNsSet);
11997 completeWild->negNsSet = NULL;
11998 }
11999 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012000 /*
12001 * 5.2 If the set S includes the negated namespace name
12002 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000012003 * be the value.
12004 */
12005 if (completeWild->nsSet != NULL) {
12006 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12007 completeWild->nsSet = NULL;
12008 }
12009 if (completeWild->negNsSet == NULL) {
12010 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12011 if (completeWild->negNsSet == NULL)
12012 return (-1);
12013 }
12014 completeWild->negNsSet->value = NULL;
12015 } else if ((!nsFound) && absentFound) {
12016 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012017 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000012018 * namespace name, then the union is not expressible.
12019 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012020 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000012021 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012022 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012023 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012024 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012025 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012026 /*
12027 * 5.4 If the set S does not include either the negated namespace
12028 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012029 * and a namespace name must be the value.
12030 */
12031 if (completeWild->negNsSet == NULL) {
12032 if (completeWild->nsSet != NULL) {
12033 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12034 completeWild->nsSet = NULL;
12035 }
12036 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12037 if (completeWild->negNsSet == NULL)
12038 return (-1);
12039 completeWild->negNsSet->value = curWild->negNsSet->value;
12040 }
12041 }
12042 return (0);
12043 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012044 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012045 * 6.
12046 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012047 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012048 (completeWild->negNsSet->value == NULL) &&
12049 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012050 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012051 (curWild->negNsSet->value == NULL) &&
12052 (completeWild->nsSet != NULL))) {
12053
12054 if (completeWild->nsSet != NULL) {
12055 cur = completeWild->nsSet;
12056 } else {
12057 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012058 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012059 while (cur != NULL) {
12060 if (cur->value == NULL) {
12061 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012062 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012063 * value.
12064 */
12065 completeWild->any = 1;
12066 if (completeWild->nsSet != NULL) {
12067 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12068 completeWild->nsSet = NULL;
12069 }
12070 if (completeWild->negNsSet != NULL) {
12071 xmlFree(completeWild->negNsSet);
12072 completeWild->negNsSet = NULL;
12073 }
12074 return (0);
12075 }
12076 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012077 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012078 if (completeWild->negNsSet == NULL) {
12079 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012080 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012081 * and ·absent· must be the value.
12082 */
12083 if (completeWild->nsSet != NULL) {
12084 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12085 completeWild->nsSet = NULL;
12086 }
12087 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12088 if (completeWild->negNsSet == NULL)
12089 return (-1);
12090 completeWild->negNsSet->value = NULL;
12091 }
12092 return (0);
12093 }
12094 return (0);
12095
12096}
12097
Daniel Veillard50355f02004-06-08 17:52:16 +000012098/**
12099 * xmlSchemaIntersectWildcards:
12100 * @ctxt: the schema parser context
12101 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012102 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012103 *
12104 * Intersects the namespace constraints of the given wildcards.
12105 * @completeWild will hold the resulting intersection.
12106 * Returns a positive error code on failure, -1 in case of an
12107 * internal error, 0 otherwise.
12108 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012109static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012110xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012111 xmlSchemaWildcardPtr completeWild,
12112 xmlSchemaWildcardPtr curWild)
12113{
William M. Brack803812b2004-06-03 02:11:24 +000012114 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012115
12116 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012117 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012118 * value.
12119 */
12120 if ((completeWild->any == curWild->any) &&
12121 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12122 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012123
Daniel Veillard3646d642004-06-02 19:19:14 +000012124 if ((completeWild->negNsSet == NULL) ||
12125 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012126
Daniel Veillard3646d642004-06-02 19:19:14 +000012127 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012128 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012129
12130 /*
12131 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012132 */
12133 cur = completeWild->nsSet;
12134 while (cur != NULL) {
12135 found = 0;
12136 curB = curWild->nsSet;
12137 while (curB != NULL) {
12138 if (cur->value == curB->value) {
12139 found = 1;
12140 break;
12141 }
12142 curB = curB->next;
12143 }
12144 if (!found)
12145 break;
12146 cur = cur->next;
12147 }
12148 if (found)
12149 return(0);
12150 } else
12151 return(0);
12152 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012153 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012154 /*
12155 * 2 If either O1 or O2 is any, then the other must be the value.
12156 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012157 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012158 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012159 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012160 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012161 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012162 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012163 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12164 * name or ·absent·) and the other is a set of (namespace names or
12165 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012166 * the set, minus ·absent· if it was in the set, must be the value.
12167 */
12168 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12169 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12170 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012171
Daniel Veillard3646d642004-06-02 19:19:14 +000012172 if (completeWild->nsSet == NULL) {
12173 neg = completeWild->negNsSet->value;
12174 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12175 return(-1);
12176 } else
12177 neg = curWild->negNsSet->value;
12178 /*
12179 * Remove absent and negated.
12180 */
12181 prev = NULL;
12182 cur = completeWild->nsSet;
12183 while (cur != NULL) {
12184 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012185 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012186 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012187 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012188 prev->next = cur->next;
12189 xmlFree(cur);
12190 break;
12191 }
12192 prev = cur;
12193 cur = cur->next;
12194 }
12195 if (neg != NULL) {
12196 prev = NULL;
12197 cur = completeWild->nsSet;
12198 while (cur != NULL) {
12199 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012200 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012201 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012202 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012203 prev->next = cur->next;
12204 xmlFree(cur);
12205 break;
12206 }
12207 prev = cur;
12208 cur = cur->next;
12209 }
12210 }
12211
12212 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012213 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012214 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012215 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012216 * then the intersection of those sets must be the value.
12217 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012218 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012219 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012220
Daniel Veillard3646d642004-06-02 19:19:14 +000012221 cur = completeWild->nsSet;
12222 prev = NULL;
12223 while (cur != NULL) {
12224 found = 0;
12225 curB = curWild->nsSet;
12226 while (curB != NULL) {
12227 if (cur->value == curB->value) {
12228 found = 1;
12229 break;
12230 }
12231 curB = curB->next;
12232 }
12233 if (!found) {
12234 if (prev == NULL)
12235 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012236 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012237 prev->next = cur->next;
12238 tmp = cur->next;
12239 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012240 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012241 continue;
12242 }
12243 prev = cur;
12244 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012245 }
12246
Daniel Veillard3646d642004-06-02 19:19:14 +000012247 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012248 }
12249 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012250 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012251 */
12252 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012253 (curWild->negNsSet != NULL) &&
12254 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012255 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012256 (curWild->negNsSet->value != NULL)) {
12257
12258 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012259 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012260 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012261 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012262 }
12263 /*
12264 * 6 If the one is a negation of a namespace name and the other
12265 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012266 * of a namespace name must be the value.
12267 */
12268 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12269 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012270 (completeWild->negNsSet->value == NULL)) {
12271 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012272 }
12273 return(0);
12274}
12275
Daniel Veillard50355f02004-06-08 17:52:16 +000012276/**
12277 * xmlSchemaIsWildcardNsConstraintSubset:
12278 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012279 * @sub: the first wildcard
12280 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012281 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012282 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12283 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012284 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012285 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012286 */
12287static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012288xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12289 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012290{
Daniel Veillard50355f02004-06-08 17:52:16 +000012291 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012292 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012293 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012294 if (super->any)
12295 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012296 /*
12297 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12298 * 2.2 super must be a pair of not and the same value.
12299 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012300 if ((sub->negNsSet != NULL) &&
12301 (super->negNsSet != NULL) &&
12302 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012303 return (0);
12304 /*
12305 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012306 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012307 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012308 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012309 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012310 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012311 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012312 xmlSchemaWildcardNsPtr cur, curB;
12313 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012314
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012315 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012316 while (cur != NULL) {
12317 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012318 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012319 while (curB != NULL) {
12320 if (cur->value == curB->value) {
12321 found = 1;
12322 break;
12323 }
12324 curB = curB->next;
12325 }
12326 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012327 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012328 cur = cur->next;
12329 }
12330 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012331 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012332 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012333 xmlSchemaWildcardNsPtr cur;
12334 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012335 * 3.2.2 super must be a pair of not and a namespace name or
12336 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012337 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012338 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012339 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012340 if (cur->value == super->negNsSet->value)
12341 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012342 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012343 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012344 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012345 }
12346 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012347 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012348}
12349
12350/**
12351 * xmlSchemaBuildCompleteAttributeWildcard:
12352 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012353 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000012354 * @completeWild: the resulting complete wildcard
12355 *
12356 * Returns -1 in case of an internal error, 0 otherwise.
12357 */
12358static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012359xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012360 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012361 xmlSchemaWildcardPtr *completeWild)
12362{
Daniel Veillard3646d642004-06-02 19:19:14 +000012363 while (attrs != NULL) {
12364 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12365 xmlSchemaAttributeGroupPtr group;
12366
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012367 group = (xmlSchemaAttributeGroupPtr) attrs;
12368 /*
12369 * Handle attribute group references.
12370 */
12371 if (group->ref != NULL) {
12372 if (group->refItem == NULL) {
12373 /*
12374 * TODO: Should we raise a warning here?
12375 */
12376 /*
12377 * The referenced attribute group definition could not
12378 * be resolved beforehand, so skip.
12379 */
12380 attrs = attrs->next;
12381 continue;
12382 } else
12383 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012384 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012385 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012386 * For every attribute group definition, an intersected wildcard
12387 * will be created (assumed that a wildcard exists on the
12388 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012389 * at all).
12390 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12391 * that the intersection will be performed only once.
12392 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012393 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12394 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012395 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012396 group->attributes, &group->attributeWildcard) == -1)
12397 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012398 }
12399 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012400 }
12401 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012402 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012403 /*
12404 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012405 *
12406 * Although the complete wildcard might not correspond to any
12407 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012408 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012409 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12410 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12411 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012412 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012413 completeWild, group->attributeWildcard) == -1)
12414 return (-1);
12415 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012416 (*completeWild)->node = group->attributeWildcard->node;
12417 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012418 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012419 }
12420 }
12421 attrs = attrs->next;
12422 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012423
12424 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012425}
12426
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012427static int
12428xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12429 int *fixed,
12430 const xmlChar **value,
12431 xmlSchemaValPtr *val)
12432{
12433 *fixed = 0;
12434 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012435 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012436 *val = NULL;
12437
12438 if (item->defValue == NULL)
12439 item = item->refDecl;
12440
12441 if (item == NULL)
12442 return (0);
12443
12444 if (item->defValue != NULL) {
12445 *value = item->defValue;
12446 if (val != 0)
12447 *val = item->defVal;
12448 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12449 *fixed = 1;
12450 return (1);
12451 }
12452 return (0);
12453}
Daniel Veillard3646d642004-06-02 19:19:14 +000012454/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012455 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000012456 * @wild: the wildcard
12457 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012458 *
12459 * Validation Rule: Wildcard allows Namespace Name
12460 * (cvc-wildcard-namespace)
12461 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012462 *
12463 * Returns 1 if the given namespace matches the wildcard,
12464 * 0 otherwise.
12465 */
12466static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012467xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
12468 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000012469{
12470 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012471 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012472
12473 if (wild->any)
12474 return(1);
12475 else if (wild->nsSet != NULL) {
12476 xmlSchemaWildcardNsPtr cur;
12477
12478 cur = wild->nsSet;
12479 while (cur != NULL) {
12480 if (xmlStrEqual(cur->value, ns))
12481 return(1);
12482 cur = cur->next;
12483 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012484 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012485 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012486 return(1);
12487
Daniel Veillard3646d642004-06-02 19:19:14 +000012488 return(0);
12489}
12490
12491/**
12492 * xmlSchemaBuildAttributeValidation:
12493 * @ctxt: the schema parser context
12494 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012495 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012496 *
12497 * Builds the wildcard and the attribute uses on the given complex type.
12498 * Returns -1 if an internal error occurs, 0 otherwise.
12499 */
12500static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012501xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
12502 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000012503{
12504 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012505 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
12506 prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012507 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012508 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012509 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012510 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012511
Daniel Veillard01fa6152004-06-29 17:04:39 +000012512 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012513 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012514 * Complex Type Definition with complex content Schema Component.
12515 *
12516 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012517 * TODO: Add checks for absent referenced attribute declarations and
12518 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012519 */
12520 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012521 PERROR_INT("xmlSchemaBuildAttributeValidation",
12522 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000012523 return (-1);
12524 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012525 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012526 PERROR_INT("xmlSchemaBuildAttributeValidation",
12527 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012528 return (-1);
12529 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012530 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012531 /*
12532 * Inherit the attribute uses of the base type.
12533 */
12534 /*
12535 * NOTE: It is allowed to "extend" the anyType complex type.
12536 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012537 if (! IS_ANYTYPE(baseType)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012538 if (baseType != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012539 for (cur = baseType->attributeUses; cur != NULL;
12540 cur = cur->next) {
12541 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012542 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12543 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012544 xmlSchemaPErrMemory(pctxt,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012545 "building attribute uses of complexType", NULL);
12546 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012547 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012548 tmp->attr = cur->attr;
12549 tmp->next = NULL;
12550 if (type->attributeUses == NULL) {
12551 type->attributeUses = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012552 } else
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012553 lastBaseUse->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012554 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012555 }
12556 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012557 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012558 attrs = type->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012559 /*
12560 * Handle attribute wildcards.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012561 */
12562 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
12563 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012564 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012565 * NOTE: During the parse time, the wildcard is created on the complexType
12566 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012567 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012568 if (err == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012569 PERROR_INT("xmlSchemaBuildAttributeValidation",
12570 "failed to build an intersected attribute wildcard");
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012571 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012572 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012573
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012574 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12575 ((IS_ANYTYPE(baseType)) ||
12576 ((baseType != NULL) &&
12577 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12578 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012579 if (type->attributeWildcard != NULL) {
12580 /*
12581 * Union the complete wildcard with the base wildcard.
12582 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012583 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012584 baseType->attributeWildcard) == -1)
12585 return (-1);
12586 } else {
12587 /*
12588 * Just inherit the wildcard.
12589 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012590 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012591 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012592 * wildcard is shared.
12593 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012594 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012595 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012596 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012597
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012598 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12599 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012600 /*
12601 * Derivation Valid (Restriction, Complex)
12602 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012603 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012604 if (baseType->attributeWildcard == NULL) {
12605 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012606 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012607 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012608 "The type has an attribute wildcard, "
12609 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012610 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012611 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012612 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012613 } else if (xmlSchemaCheckCOSNSSubset(
12614 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012615 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012616 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012617 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012618 NULL, type, NULL,
12619 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012620 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012621 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12622 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012623 return (1);
12624 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012625 /* 4.3 Unless the {base type definition} is the ·ur-type
12626 * definition·, the complex type definition's {attribute
12627 * wildcard}'s {process contents} must be identical to or
12628 * stronger than the {base type definition}'s {attribute
12629 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012630 * than lax is stronger than skip.
12631 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012632 if ((! IS_ANYTYPE(baseType)) &&
12633 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012634 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012635 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012636 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012637 NULL, type, NULL,
12638 "The 'process contents' of the attribute wildcard is "
12639 "weaker than the one in the base type %s",
12640 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012641 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012642 return (1);
12643 }
12644 }
12645 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12646 /*
12647 * Derivation Valid (Extension)
12648 * At this point the type and the base have both, either
12649 * no wildcard or a wildcard.
12650 */
12651 if ((baseType->attributeWildcard != NULL) &&
12652 (baseType->attributeWildcard != type->attributeWildcard)) {
12653 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012654 if (xmlSchemaCheckCOSNSSubset(
12655 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012656 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012657 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012658 NULL, type, NULL,
12659 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012660 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012661 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12662 FREE_AND_NULL(str)
12663 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012664 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012665 }
12666 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012667
Daniel Veillard3646d642004-06-02 19:19:14 +000012668 /*
12669 * Gather attribute uses defined by this type.
12670 */
12671 if (attrs != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012672 if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
Daniel Veillard3646d642004-06-02 19:19:14 +000012673 &uses, &lastUse) == -1) {
12674 return (-1);
12675 }
12676 }
12677 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012678 * "Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012679 * not have identical {name}s and {target namespace}s."
12680 *
12681 * For "extension" this is done further down.
12682 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012683 if ((uses != NULL) && ((type->flags &
12684 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012685 cur = uses;
12686 while (cur != NULL) {
12687 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012688 while (tmp != NULL) {
12689 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012690 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012691 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012692 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12693
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012694 xmlSchemaPAttrUseErr(pctxt,
12695 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12696 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012697 "Duplicate attribute use %s specified",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012698 xmlSchemaFormatQName(&str,
12699 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12700 xmlSchemaGetAttrName(tmp->attr)));
12701 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012702 break;
12703 }
12704 tmp = tmp->next;
12705 }
12706 cur = cur->next;
12707 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012708 }
12709 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012710 /*
12711 * Derive by restriction.
12712 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012713 if (IS_ANYTYPE(baseType)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012714 type->attributeUses = uses;
12715 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012716 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012717 const xmlChar *bEffValue;
12718 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012719
12720 cur = uses;
12721 while (cur != NULL) {
12722 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012723 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012724 base = type->attributeUses;
12725 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012726 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012727 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012728 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012729 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012730
12731 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012732
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012733 if ((cur->attr->occurs ==
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012734 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12735 (base->attr->occurs ==
12736 XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
12737 /*
12738 * NOOP.
12739 */
12740 } else if ((cur->attr->occurs ==
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012741 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12742 (base->attr->occurs ==
12743 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012744 /*
12745 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000012746 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012747 xmlSchemaPAttrUseErr(pctxt,
12748 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
12749 type, cur->attr,
12750 "The 'optional' use is inconsistent with a "
12751 "matching 'required' use of the base type",
12752 NULL);
12753 } else if ((cur->attr->occurs ==
12754 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12755 (base->attr->occurs ==
12756 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12757 /*
12758 * derivation-ok-restriction 3
12759 */
12760 xmlSchemaPCustomErr(pctxt,
12761 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12762 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012763 "A matching attribute use for the 'required' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012764 "attribute use '%s' of the base type is "
12765 "missing",
12766 xmlSchemaFormatQName(&str,
12767 xmlSchemaGetAttrTargetNsURI(base->attr),
12768 xmlSchemaGetAttrName(base->attr)));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012769 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012770 } else if (xmlSchemaCheckCOSSTDerivedOK(
12771 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
12772
12773 /*
12774 * SPEC (2.1.2) "R's {attribute declaration}'s
12775 * {type definition} must be validly derived from
12776 * B's {type definition} given the empty set as
12777 * defined in Type Derivation OK (Simple) (§3.14.6)."
12778 */
12779 xmlSchemaPAttrUseErr(pctxt,
12780 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
12781 type, cur->attr,
12782 "The attribute declaration's type "
12783 "definition is not validly derived from "
12784 "the corresponding definition in the "
12785 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012786 } else {
12787 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012788 * 2.1.3 [Definition:] Let the effective value
12789 * constraint of an attribute use be its {value
12790 * constraint}, if present, otherwise its {attribute
12791 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012792 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012793 xmlSchemaGetEffectiveValueConstraint(base->attr,
12794 &effFixed, &bEffValue, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012795 /*
12796 * 2.1.3 ... one of the following must be true
12797 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012798 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012799 * ·absent· or default.
12800 */
12801 if ((bEffValue != NULL) &&
12802 (effFixed == 1)) {
12803 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012804
12805 xmlSchemaGetEffectiveValueConstraint(base->attr,
12806 &effFixed, &rEffValue, 0);
12807 /*
12808 * 2.1.3.2 R's ·effective value constraint· is
12809 * fixed with the same string as B's.
12810 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012811 */
12812 if ((effFixed == 0) ||
12813 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012814 xmlSchemaPAttrUseErr(pctxt,
12815 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12816 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012817 "The effective value constraint of the "
12818 "attribute use is inconsistent with "
12819 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012820 NULL);
12821 } else {
12822 /*
12823 * Override the attribute use.
12824 */
12825 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012826 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012827 } else
12828 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000012829 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012830
Daniel Veillard3646d642004-06-02 19:19:14 +000012831 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012832 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012833 base = base->next;
12834 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012835
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012836 if ((!found) && (cur->attr->occurs !=
12837 XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
12838 /*
12839 * derivation-ok-restriction 2.2
12840 */
12841 if ((baseType->attributeWildcard == NULL) ||
12842 (xmlSchemaCheckCVCWildcardNamespace(
12843 baseType->attributeWildcard,
12844 cur->attr->targetNamespace) != 1)) {
12845 xmlSchemaPAttrUseErr(pctxt,
12846 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12847 type, cur->attr,
12848 "Neither a matching attribute use, "
12849 "nor a matching wildcard in the base type does exist",
12850 NULL);
12851 } else {
12852 /*
12853 * Add the attribute use.
12854 *
12855 * Note that this may lead to funny derivation error reports, if
12856 * multiple equal attribute uses exist; but this is not
12857 * allowed anyway, and it will be reported beforehand.
12858 */
12859 tmp = cur;
12860 if (prev != NULL)
12861 prev->next = cur->next;
12862 else
12863 uses = cur->next;
12864 cur = cur->next;
12865 tmp->next = NULL;
12866 if (type->attributeUses == NULL) {
12867 type->attributeUses = tmp;
12868 } else
12869 lastBaseUse->next = tmp;
12870 lastBaseUse = tmp;
12871
12872 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012873 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012874 }
12875 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000012876 cur = cur->next;
12877 }
12878 if (uses != NULL)
12879 xmlSchemaFreeAttributeUseList(uses);
12880 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012881 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012882 /*
12883 * The spec allows only appending, and not other kinds of extensions.
12884 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012885 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000012886 */
12887 if (uses != NULL) {
12888 if (type->attributeUses == NULL) {
12889 type->attributeUses = uses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012890 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000012891 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012892 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012893 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012894 PERROR_INT("xmlSchemaBuildAttributeValidation",
12895 "no derivation method");
12896 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012897 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012898 /*
12899 * 3.4.6 -> Complex Type Definition Properties Correct
12900 */
12901 if (type->attributeUses != NULL) {
12902 cur = type->attributeUses;
12903 prev = NULL;
12904 while (cur != NULL) {
12905 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012906 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012907 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012908 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012909 * Note that this was already done for "restriction" and types derived from
12910 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012911 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012912 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12913 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012914 while (tmp != NULL) {
12915 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012916 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012917 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012918 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012919
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012920 xmlSchemaPAttrUseErr(pctxt,
12921 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12922 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012923 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012924 break;
12925 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012926 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012927 }
12928 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012929 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012930 * 5. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012931 * not have {type definition}s which are or are derived from ID.
12932 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012933 if ((cur->attr->subtypes != NULL) &&
12934 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
12935 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012936 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012937 xmlSchemaPAttrUseErr(pctxt,
12938 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12939 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012940 "There must not exist more than one attribute use, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012941 "declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000012942 NULL);
12943 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012944 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012945 id = cur;
12946 }
12947 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012948 * Remove "prohibited" attribute uses. The reason this is done at this late
Daniel Veillard3646d642004-06-02 19:19:14 +000012949 * stage is to be able to catch dublicate attribute uses. So we had to keep
12950 * prohibited uses in the list as well.
12951 */
12952 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12953 tmp = cur;
12954 if (prev == NULL)
12955 type->attributeUses = cur->next;
12956 else
12957 prev->next = cur->next;
12958 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012959 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012960 } else {
12961 prev = cur;
12962 cur = cur->next;
12963 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012964 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012965 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012966 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012967 * TODO: This check should be removed if we are 100% sure of
12968 * the base type attribute uses already being built.
12969 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012970 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012971 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012972 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012973 PERROR_INT("xmlSchemaBuildAttributeValidation",
12974 "attribute uses not builded on base type");
12975 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012976 return (0);
12977}
12978
12979/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000012980 * xmlSchemaTypeFinalContains:
12981 * @schema: the schema
12982 * @type: the type definition
12983 * @final: the final
12984 *
12985 * Evaluates if a type definition contains the given "final".
12986 * This does take "finalDefault" into account as well.
12987 *
12988 * Returns 1 if the type does containt the given "final",
12989 * 0 otherwise.
12990 */
12991static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012992xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012993{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012994 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012995 return (0);
12996 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012997 return (1);
12998 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012999 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013000}
13001
13002/**
13003 * xmlSchemaGetUnionSimpleTypeMemberTypes:
13004 * @type: the Union Simple Type
13005 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013006 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013007 * returns NULL otherwise.
13008 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013009static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000013010xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
13011{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013012 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013013 if (type->memberTypes != NULL)
13014 return (type->memberTypes);
13015 else
13016 type = type->baseType;
13017 }
13018 return (NULL);
13019}
13020
13021/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013022 * xmlSchemaGetParticleTotalRangeMin:
13023 * @particle: the particle
13024 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013025 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013026 * (all and sequence) + (choice)
13027 *
13028 * Returns the minimun Effective Total Range.
13029 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013030static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013031xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013032{
13033 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013034 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013035 return (0);
13036 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013037 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013038 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013039 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013040
13041 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013042 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013043 while (part != NULL) {
13044 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13045 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013046 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013047 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013048 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013049 if (cur == 0)
13050 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013051 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013052 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013053 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013054 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013055 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013056 } else {
13057 /* <all> and <sequence> */
13058 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013059 xmlSchemaParticlePtr part =
13060 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013061
13062 if (part == NULL)
13063 return (0);
13064 do {
13065 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13066 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013067 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013068 else
13069 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013070 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013071 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013072 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013073 }
13074}
13075
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013076/**
13077 * xmlSchemaGetParticleTotalRangeMax:
13078 * @particle: the particle
13079 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013080 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013081 * (all and sequence) + (choice)
13082 *
13083 * Returns the maximum Effective Total Range.
13084 */
13085static int
13086xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13087{
13088 if ((particle->children == NULL) ||
13089 (particle->children->children == NULL))
13090 return (0);
13091 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13092 int max = -1, cur;
13093 xmlSchemaParticlePtr part =
13094 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013095
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013096 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13097 if (part->children == NULL)
13098 continue;
13099 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13100 (part->children->type == XML_SCHEMA_TYPE_ANY))
13101 cur = part->maxOccurs;
13102 else
13103 cur = xmlSchemaGetParticleTotalRangeMax(part);
13104 if (cur == UNBOUNDED)
13105 return (UNBOUNDED);
13106 if ((max < cur) || (max == -1))
13107 max = cur;
13108 }
13109 /* TODO: Handle overflows? */
13110 return (particle->maxOccurs * max);
13111 } else {
13112 /* <all> and <sequence> */
13113 int sum = 0, cur;
13114 xmlSchemaParticlePtr part =
13115 (xmlSchemaParticlePtr) particle->children->children;
13116
13117 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13118 if (part->children == NULL)
13119 continue;
13120 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13121 (part->children->type == XML_SCHEMA_TYPE_ANY))
13122 cur = part->maxOccurs;
13123 else
13124 cur = xmlSchemaGetParticleTotalRangeMax(part);
13125 if (cur == UNBOUNDED)
13126 return (UNBOUNDED);
13127 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13128 return (UNBOUNDED);
13129 sum += cur;
13130 }
13131 /* TODO: Handle overflows? */
13132 return (particle->maxOccurs * sum);
13133 }
13134}
13135
13136/**
13137 * xmlSchemaIsParticleEmptiable:
13138 * @particle: the particle
13139 *
13140 * Schema Component Constraint: Particle Emptiable
13141 * Checks whether the given particle is emptiable.
13142 *
13143 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013144 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013145static int
13146xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13147{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013148 /*
13149 * SPEC (1) "Its {min occurs} is 0."
13150 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013151 if ((particle == NULL) || (particle->minOccurs == 0) ||
13152 (particle->children == NULL))
13153 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013154 /*
13155 * SPEC (2) "Its {term} is a group and the minimum part of the
13156 * effective total range of that group, [...] is 0."
13157 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013158 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013159 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013160 return (1);
13161 }
13162 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013163}
13164
13165/**
13166 * xmlSchemaCheckCOSSTDerivedOK:
13167 * @type: the derived simple type definition
13168 * @baseType: the base type definition
13169 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013170 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013171 * Type Derivation OK (Simple) (cos-st-derived-OK)
13172 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013173 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013174 * derived from @baseType.
13175 *
13176 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013177 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013178static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013179xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13180 xmlSchemaTypePtr baseType,
13181 int subset)
13182{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013183 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013184 * 1 They are the same type definition.
13185 * TODO: The identy check might have to be more complex than this.
13186 */
13187 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013188 return (0);
13189 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013190 * 2.1 restriction is not in the subset, or in the {final}
13191 * of its own {base type definition};
13192 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013193 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013194 (xmlSchemaTypeFinalContains(type->baseType,
13195 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13196 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013197 }
13198 /* 2.2 */
13199 if (type->baseType == baseType) {
13200 /*
13201 * 2.2.1 D's ·base type definition· is B.
13202 */
13203 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013204 }
13205 /*
13206 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13207 * and is validly derived from B given the subset, as defined by this
13208 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013209 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013210 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013211 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013212 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013213 return (0);
13214 }
13215 /*
13216 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000013217 * definition·.
13218 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013219 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013220 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013221 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013222 }
13223 /*
13224 * 2.2.4 B's {variety} is union and D is validly derived from a type
13225 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000013226 * defined by this constraint.
13227 *
13228 * NOTE: This seems not to involve built-in types, since there is no
13229 * built-in Union Simple Type.
13230 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013231 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013232 xmlSchemaTypeLinkPtr cur;
13233
13234 cur = baseType->memberTypes;
13235 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013236 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013237 return (0);
13238 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013239 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013240 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013241
Daniel Veillard01fa6152004-06-29 17:04:39 +000013242 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13243}
13244
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013245/**
13246 * xmlSchemaCheckTypeDefCircularInternal:
13247 * @pctxt: the schema parser context
13248 * @ctxtType: the type definition
13249 * @ancestor: an ancestor of @ctxtType
13250 *
13251 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013252 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013253 *
13254 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13255 * circular, 0 otherwise.
13256 */
13257static int
13258xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13259 xmlSchemaTypePtr ctxtType,
13260 xmlSchemaTypePtr ancestor)
13261{
13262 int ret;
13263
13264 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13265 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013266
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013267 if (ctxtType == ancestor) {
13268 xmlSchemaPCustomErr(pctxt,
13269 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13270 NULL, ctxtType, GET_NODE(ctxtType),
13271 "The definition is circular", NULL);
13272 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13273 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013274 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13275 /*
13276 * Avoid inifinite recursion on circular types not yet checked.
13277 */
13278 return (0);
13279 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013280 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13281 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13282 ancestor->baseType);
13283 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13284 return (ret);
13285}
13286
13287/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013288 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013289 * @item: the complex/simple type definition
13290 * @ctxt: the parser context
13291 * @name: the name
13292 *
13293 * Checks for circular type definitions.
13294 */
13295static void
13296xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013297 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013298 const xmlChar * name ATTRIBUTE_UNUSED)
13299{
13300 if ((item == NULL) ||
13301 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13302 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13303 return;
13304 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13305
13306}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013307
13308/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013309 * xmlSchemaResolveTypeDefs:
13310 * @item: the complex/simple type definition
13311 * @ctxt: the parser context
13312 * @name: the name
13313 *
13314 * Checks for circular type definitions.
13315 */
13316static void
13317xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013318 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013319 const xmlChar * name ATTRIBUTE_UNUSED)
13320{
13321 if (typeDef == NULL)
13322 return;
13323
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013324 /*
13325 * Resolve the base type.
13326 */
13327 if (typeDef->baseType == NULL) {
13328 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13329 typeDef->base, typeDef->baseNs);
13330 if (typeDef->baseType == NULL) {
13331 xmlSchemaPResCompAttrErr(ctxt,
13332 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013333 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013334 "base", typeDef->base, typeDef->baseNs,
13335 XML_SCHEMA_TYPE_SIMPLE, NULL);
13336 return;
13337 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013338 }
13339 if (IS_SIMPLE_TYPE(typeDef)) {
13340 if (VARIETY_UNION(typeDef)) {
13341 /*
13342 * Resolve the memberTypes.
13343 */
13344 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13345 return;
13346 } else if (VARIETY_LIST(typeDef)) {
13347 /*
13348 * Resolve the itemType.
13349 */
13350 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13351 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13352 typeDef->ref, typeDef->refNs);
13353 if ((typeDef->subtypes == NULL) ||
13354 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13355 typeDef->subtypes = NULL;
13356 xmlSchemaPResCompAttrErr(ctxt,
13357 XML_SCHEMAP_SRC_RESOLVE,
13358 typeDef, typeDef->node,
13359 "itemType", typeDef->ref, typeDef->refNs,
13360 XML_SCHEMA_TYPE_SIMPLE, NULL);
13361 }
13362 }
13363 return;
13364 }
13365 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013366}
13367
13368
13369
13370/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013371 * xmlSchemaCheckSTPropsCorrect:
13372 * @ctxt: the schema parser context
13373 * @type: the simple type definition
13374 *
13375 * Checks st-props-correct.
13376 *
13377 * Returns 0 if the properties are correct,
13378 * if not, a positive error code and -1 on internal
13379 * errors.
13380 */
13381static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013382xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013383 xmlSchemaTypePtr type)
13384{
13385 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13386 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013387 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013388
Daniel Veillardc0826a72004-08-10 14:17:33 +000013389 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013390 /*
13391 * Schema Component Constraint: Simple Type Definition Properties Correct
13392 *
13393 * NOTE: This is somehow redundant, since we actually built a simple type
13394 * to have all the needed information; this acts as an self test.
13395 */
13396 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13397 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013398 /* Base type: If the datatype has been ·derived· by ·restriction·
13399 * then the Simple Type Definition component from which it is ·derived·,
13400 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013401 */
13402 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013403 /*
13404 * TODO: Think about: "modulo the impact of Missing
13405 * Sub-components (§5.3)."
13406 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013407 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013408 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013409 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013410 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013411 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013412
Daniel Veillard01fa6152004-06-29 17:04:39 +000013413 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013414 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013415 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013416 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013417 NULL, type, NULL,
13418 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013419 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013420 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013421 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13422 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013423 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
13424 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13425 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013426 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013427 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013428 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013429 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013430 "the simple ur-type definition as base type, not '%s'",
13431 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013432 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013433 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13434 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013435 /*
13436 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013437 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013438 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
13439 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013440 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013441 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013442 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013443 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013444 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13445 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013446 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013447
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013448 /*
13449 * 3 The {final} of the {base type definition} must not contain restriction.
13450 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013451 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013452 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13453 xmlSchemaPCustomErr(ctxt,
13454 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013455 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013456 "The 'final' of its base type '%s' must not contain "
13457 "'restriction'",
13458 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013459 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013460 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013461 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013462
13463 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013464 * 2 All simple type definitions must be derived ultimately from the ·simple
13465 * ur-type definition (so· circular definitions are disallowed). That is, it
13466 * must be possible to reach a built-in primitive datatype or the ·simple
13467 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013468 *
13469 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013470 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013471 return (0);
13472}
13473
13474/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013475 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013476 * @ctxt: the schema parser context
13477 * @type: the simple type definition
13478 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013479 * Schema Component Constraint:
13480 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13481
13482 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013483 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013484 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013485 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013486 * a positive error code otherwise.
13487 */
13488static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013489xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013490 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013491{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013492 xmlChar *str = NULL;
13493
Daniel Veillard01fa6152004-06-29 17:04:39 +000013494 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013495 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13496 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013497 return (-1);
13498 }
13499
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013500 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013501 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013502 /*
13503 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000013504 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013505 */
13506 if (! VARIETY_ATOMIC(type->baseType)) {
13507 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013508 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013509 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013510 "The base type '%s' is not an atomic simple type",
13511 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013512 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013513 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13514 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013515 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000013516 * restriction.
13517 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013518 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013519 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013520 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013521 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013522 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013523 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013524 "The final of its base type '%s' must not contain 'restriction'",
13525 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013526 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013527 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13528 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013529
13530 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013531 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013532 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013533 * Primitive datatypes.
13534 */
13535 if (type->facets != NULL) {
13536 xmlSchemaFacetPtr facet;
13537 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013538
Daniel Veillard01fa6152004-06-29 17:04:39 +000013539 primitive = xmlSchemaGetPrimitiveType(type);
13540 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013541 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13542 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013543 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013544 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013545 facet = type->facets;
13546 do {
13547 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013548 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013549 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013550 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013551 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013552 }
13553 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013554 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013555 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013556 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013557 }
13558 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013559 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13560 * of the {base type definition} (call this BF),then the DF's {value}
13561 * must be a valid restriction of BF's {value} as defined in
13562 * [XML Schemas: Datatypes]."
13563 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013564 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013565 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013566 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013567 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013568 xmlSchemaTypePtr itemType = NULL;
13569
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013570 itemType = type->subtypes;
13571 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013572 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13573 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013574 return (-1);
13575 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013576 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013577 xmlSchemaTypeFixup(itemType, pctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013578 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013579 * 2.1 The {item type definition} must have a {variety} of atomic or
13580 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013581 * must be atomic).
13582 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013583 if ((! VARIETY_ATOMIC(itemType)) &&
13584 (! VARIETY_UNION(itemType))) {
13585 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013586 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013587 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013588 "The item type '%s' does not have a variety of atomic or union",
13589 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013590 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013591 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013592 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013593 xmlSchemaTypeLinkPtr member;
13594
13595 member = itemType->memberTypes;
13596 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013597 if (! VARIETY_ATOMIC(member->type)) {
13598 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013599 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013600 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013601 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013602 "member type '%s' of this item type is not atomic",
13603 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013604 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013605 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13606 }
13607 member = member->next;
13608 }
13609 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013610
13611 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013612 xmlSchemaFacetPtr facet;
13613 /*
13614 * This is the case if we have: <simpleType><list ..
13615 */
13616 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013617 * 2.3.1
13618 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000013619 * contain list.
13620 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013621 if (xmlSchemaTypeFinalContains(itemType,
13622 XML_SCHEMAS_TYPE_FINAL_LIST)) {
13623 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013624 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013625 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013626 "The final of its item type '%s' must not contain 'list'",
13627 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013628 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013629 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13630 }
13631 /*
13632 * 2.3.1.2 The {facets} must only contain the whiteSpace
13633 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013634 * OPTIMIZE TODO: the S4S already disallows any facet
13635 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013636 */
13637 if (type->facets != NULL) {
13638 facet = type->facets;
13639 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013640 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013641 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013642 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013643 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013644 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13645 }
13646 facet = facet->next;
13647 } while (facet != NULL);
13648 }
13649 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013650 * MAYBE TODO: (Hmm, not really) Datatypes states:
13651 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13652 * whose ·lexical space· allows space (such as string or anyURI)or
13653 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000013654 * ·lexical space· allows space.
13655 */
13656 } else {
13657 /*
13658 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013659 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013660 */
13661 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013662 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013663 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13664 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013665 if (! VARIETY_LIST(type->baseType)) {
13666 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013667 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013668 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013669 "The base type '%s' must be a list type",
13670 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013671 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013672 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13673 }
13674 /*
13675 * 2.3.2.2 The {final} of the {base type definition} must not
13676 * contain restriction.
13677 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013678 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013679 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013680 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013681 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013682 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013683 "The 'final' of the base type '%s' must not contain 'restriction'",
13684 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013685 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013686 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13687 }
13688 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013689 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000013690 * from the {base type definition}'s {item type definition} given
13691 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13692 */
13693 {
13694 xmlSchemaTypePtr baseItemType;
13695
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013696 baseItemType = type->baseType->subtypes;
13697 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013698 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13699 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013700 return (-1);
13701 }
13702 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013703 (xmlSchemaCheckCOSSTDerivedOK(itemType,
13704 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013705 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013706 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013707 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013708 NULL, type, NULL,
13709 "The item type '%s' is not validly derived from "
13710 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013711 xmlSchemaGetComponentQName(&str, itemType),
13712 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13713 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013714
13715 FREE_AND_NULL(str)
13716 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013717 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013718 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13719 }
13720 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013721
Daniel Veillard01fa6152004-06-29 17:04:39 +000013722 if (type->facets != NULL) {
13723 xmlSchemaFacetPtr facet;
13724 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013725 /*
13726 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000013727 * and enumeration facet components are allowed among the {facets}.
13728 */
13729 facet = type->facets;
13730 do {
13731 switch (facet->type) {
13732 case XML_SCHEMA_FACET_LENGTH:
13733 case XML_SCHEMA_FACET_MINLENGTH:
13734 case XML_SCHEMA_FACET_MAXLENGTH:
13735 case XML_SCHEMA_FACET_WHITESPACE:
13736 /*
13737 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013738 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013739 */
13740 case XML_SCHEMA_FACET_PATTERN:
13741 case XML_SCHEMA_FACET_ENUMERATION:
13742 break;
13743 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013744 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013745 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013746 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013747 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013748 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000013749 * invalid facets.
13750 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013751 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013752 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013753 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013754 facet = facet->next;
13755 } while (facet != NULL);
13756 if (ok == 0)
13757 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13758 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013759 * SPEC (2.3.2.5) (same as 1.3.2)
13760 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013761 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013762 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013763 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013764 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013765 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013766 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013767 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013768 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000013769 * atomic or list.
13770 */
13771 xmlSchemaTypeLinkPtr member;
13772
13773 member = type->memberTypes;
13774 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013775 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013776 xmlSchemaTypeFixup(member->type, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013777
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013778 if ((! VARIETY_ATOMIC(member->type)) &&
13779 (! VARIETY_LIST(member->type))) {
13780 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013781 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013782 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013783 "The member type '%s' is neither an atomic, nor a list type",
13784 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013785 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013786 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13787 }
13788 member = member->next;
13789 }
13790 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013791 * 3.3.1 If the {base type definition} is the ·simple ur-type
13792 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000013793 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013794 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013795 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013796 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000013797 * {final} which does not contain union.
13798 */
13799 member = type->memberTypes;
13800 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013801 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013802 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013803 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013804 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013805 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013806 "The 'final' of member type '%s' contains 'union'",
13807 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013808 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013809 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13810 }
13811 member = member->next;
13812 }
13813 /*
13814 * 3.3.1.2 The {facets} must be empty.
13815 */
13816 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013817 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013818 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013819 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013820 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013821 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13822 }
13823 } else {
13824 /*
13825 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013826 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013827 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013828 if (! VARIETY_UNION(type->baseType)) {
13829 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013830 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013831 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013832 "The base type '%s' is not a union type",
13833 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013834 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013835 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13836 }
13837 /*
13838 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13839 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013840 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013841 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013842 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013843 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013844 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013845 "The 'final' of its base type '%s' must not contain 'restriction'",
13846 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013847 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013848 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13849 }
13850 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013851 * 3.3.2.3 The {member type definitions}, in order, must be validly
13852 * derived from the corresponding type definitions in the {base
13853 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013854 * as defined in Type Derivation OK (Simple) (§3.14.6).
13855 */
13856 {
13857 xmlSchemaTypeLinkPtr baseMember;
13858
13859 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013860 * OPTIMIZE: if the type is restricting, it has no local defined
13861 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013862 * thus a check for equality can be skipped.
13863 */
13864 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013865 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013866 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000013867 * types of it's base type. This check seems not necessary with
13868 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013869 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013870 */
13871 if (type->memberTypes != NULL) {
13872 member = type->memberTypes;
13873 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013874 if ((member == NULL) && (baseMember != NULL)) {
13875 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13876 "different number of member types in base");
13877 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013878 while (member != NULL) {
13879 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013880 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13881 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013882 }
13883 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013884 (xmlSchemaCheckCOSSTDerivedOK(
13885 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013886 xmlChar *strBMT = NULL, *strBT = NULL;
13887
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013888 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013889 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13890 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013891 "The member type %s is not validly "
13892 "derived from its corresponding member "
13893 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013894 xmlSchemaGetComponentQName(&str, member->type),
13895 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13896 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013897 FREE_AND_NULL(str)
13898 FREE_AND_NULL(strBMT)
13899 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013900 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013901 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013902 member = member->next;
13903 baseMember = baseMember->next;
13904 }
13905 }
13906 }
13907 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013908 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000013909 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013910 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013911 if (type->facets != NULL) {
13912 xmlSchemaFacetPtr facet;
13913 int ok = 1;
13914
13915 facet = type->facets;
13916 do {
13917 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13918 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013919 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013920 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013921 NULL, type, facet);
13922 ok = 0;
13923 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013924 facet = facet->next;
13925 } while (facet != NULL);
13926 if (ok == 0)
13927 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013928
Daniel Veillard01fa6152004-06-29 17:04:39 +000013929 }
13930 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013931 * SPEC (3.3.2.5) (same as 1.3.2)
13932 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013933 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013934 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013935 */
13936 }
13937 }
13938
13939 return (0);
13940}
13941
13942/**
13943 * xmlSchemaCheckSRCSimpleType:
13944 * @ctxt: the schema parser context
13945 * @type: the simple type definition
13946 *
13947 * Checks crc-simple-type constraints.
13948 *
13949 * Returns 0 if the constraints are satisfied,
13950 * if not a positive error code and -1 on internal
13951 * errors.
13952 */
13953static int
13954xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
13955 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013956{
13957 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013958 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013959 * must satisfy the conditions set out in Constraints on Simple Type
13960 * Definition Schema Components (§3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013961 */
13962 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
13963 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
13964 /*
13965 * TODO: Removed this, since it got annoying to get an
13966 * extra error report, if anything failed until now.
13967 * Enable this if needed.
13968 */
13969 /*
13970 xmlSchemaPErr(ctxt, type->node,
13971 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013972 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013973 "on simple type definitions.\n",
13974 type->name, NULL);
13975 */
13976 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
13977 }
13978
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013979 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013980 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013981 * src-simple-type.2 If the <restriction> alternative is chosen,
13982 * either it must have a base [attribute] or a <simpleType> among its
Daniel Veillard01fa6152004-06-29 17:04:39 +000013983 * [children], but not both.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013984 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013985 /*
13986 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013987 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013988 */
13989 } else if (VARIETY_LIST(type)) {
13990 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
13991 * an itemType [attribute] or a <simpleType> among its [children],
Daniel Veillard01fa6152004-06-29 17:04:39 +000013992 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013993 *
13994 * REMOVED: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013995 */
13996 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013997 xmlSchemaTypeLinkPtr member;
13998 xmlSchemaTypePtr ancestor, anySimpleType;
13999
14000 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14001
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014002 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
14003 * the <union> alternative is chosen, there must not be any entries
14004 * in the memberTypes [attribute] at any depth which resolve to the
Daniel Veillard01fa6152004-06-29 17:04:39 +000014005 * component corresponding to the <simpleType>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014006 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014007 member = type->memberTypes;
14008 while (member != NULL) {
14009 ancestor = member->type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014010 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014011 if (ancestor == type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014012 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014013 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014014 NULL, type, NULL,
14015 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014016 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014017 }
14018 if (IS_NOT_TYPEFIXED(ancestor))
14019 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014020 if (VARIETY_LIST(ancestor)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014021 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014022 * TODO, FIXME: Although a list simple type must not have a union ST
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014023 * type as item type, which in turn has a list ST as member
14024 * type, we will assume this here as well, since this check
Daniel Veillard01fa6152004-06-29 17:04:39 +000014025 * was not yet performed.
14026 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014027 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014028
Daniel Veillard01fa6152004-06-29 17:04:39 +000014029 ancestor = ancestor->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014030 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014031 member = member->next;
14032 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014033 }
14034
14035 return (0);
14036}
14037
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014038static int
14039xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
14040{
14041 if (ctxt->vctxt == NULL) {
14042 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
14043 if (ctxt->vctxt == NULL) {
14044 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014045 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014046 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014047 "failed to create a temp. validation context.\n",
14048 NULL, NULL);
14049 return (-1);
14050 }
14051 /* TODO: Pass user data. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014052 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014053 }
14054 return (0);
14055}
14056
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014057static int
14058xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
14059 xmlNodePtr node,
14060 xmlSchemaTypePtr type,
14061 const xmlChar *value,
14062 xmlSchemaValPtr *retVal,
14063 int fireErrors,
14064 int normalize,
14065 int isNormalized);
14066
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014067/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014068 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014069 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014070 * @type: the simple type definition
14071 * @value: the default value
14072 * @node: an optional node (the holder of the value)
14073 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014074 * Schema Component Constraint: Element Default Valid (Immediate)
14075 * (cos-valid-default)
14076 * This will be used by the parser only. For the validator there's
14077 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014078 *
14079 * Returns 0 if the constraints are satisfied,
14080 * if not, a positive error code and -1 on internal
14081 * errors.
14082 */
14083static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014084xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14085 xmlNodePtr node,
14086 xmlSchemaTypePtr type,
14087 const xmlChar *value,
14088 xmlSchemaValPtr *val)
14089{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014090 int ret = 0;
14091
14092 /*
14093 * cos-valid-default:
14094 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014095 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014096 * definition the appropriate case among the following must be true:
14097 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014098 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014099 /*
14100 * Complex type.
14101 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014102 * SPEC (2.1) "its {content type} must be a simple type definition
14103 * or mixed."
14104 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014105 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014106 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014107 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014108 if ((! HAS_SIMPLE_CONTENT(type)) &&
14109 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14110 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014111 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014112 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014113 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014114 "For a string to be a valid default, the type definition "
14115 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014116 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014117 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14118 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014119 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014120 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014121 * 1 If the type definition is a simple type definition, then the string
14122 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014123 * Valid (§3.14.4).
14124 *
14125 * AND
14126 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014127 * 2.2.1 If the {content type} is a simple type definition, then the
14128 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014129 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014130 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014131 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014132 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14133 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014134 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014135 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14136 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014137 else
14138 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014139
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014140 if (ret < 0) {
14141 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14142 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014143 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014144
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014145 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014146}
14147
14148/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014149 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014150 * @ctxt: the schema parser context
14151 * @type: the complex type definition
14152 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014153 *.(4.6) Constraints on Complex Type Definition Schema Components
14154 * Schema Component Constraint:
14155 * Complex Type Definition Properties Correct (ct-props-correct)
14156 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014157 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014158 * Returns 0 if the constraints are satisfied, a positive
14159 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014160 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014161static int
14162xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14163 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014164{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014165 /*
14166 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14167 *
14168 * SPEC (1) "The values of the properties of a complex type definition must
14169 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014170 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014171 * Sub-components (§5.3)."
14172 */
14173 if ((type->baseType != NULL) &&
14174 (IS_SIMPLE_TYPE(type->baseType)) &&
14175 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14176 /*
14177 * SPEC (2) "If the {base type definition} is a simple type definition,
14178 * the {derivation method} must be extension."
14179 */
14180 xmlSchemaPCustomErr(pctxt,
14181 XML_SCHEMAP_SRC_CT_1,
14182 NULL, type, NULL,
14183 "If the base type is a simple type, the derivation method must be "
14184 "'extension'", NULL);
14185 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014186 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014187 /*
14188 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14189 * definition·. That is, it must be possible to reach the ·ur-type
14190 * definition by repeatedly following the {base type definition}."
14191 *
14192 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14193 *
14194 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014195 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014196 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14197 * must not have {type definition}s which are or are derived from ID."
14198 *
14199 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14200 */
14201 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014202}
14203
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014204static int
14205xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14206 xmlSchemaTypePtr typeB)
14207{
14208 /*
14209 * TODO: This should implement component-identity
14210 * in the future.
14211 */
14212 if ((typeA == NULL) || (typeB == NULL))
14213 return (0);
14214 return (typeA == typeB);
14215}
14216
14217/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014218 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014219 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014220 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014221 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014222 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014223 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014224 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014225 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14226 *
14227 * STATUS: completed
14228 *
14229 * Returns 0 if the constraints are satisfied, or 1
14230 * if not.
14231 */
14232static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014233xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014234 xmlSchemaTypePtr baseType,
14235 int set)
14236{
14237 int equal = xmlSchemaAreEqualTypes(type, baseType);
14238 /* TODO: Error codes. */
14239 /*
14240 * SPEC "For a complex type definition (call it D, for derived)
14241 * to be validly derived from a type definition (call this
14242 * B, for base) given a subset of {extension, restriction}
14243 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014244 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014245 if (! equal) {
14246 /*
14247 * SPEC (1) "If B and D are not the same type definition, then the
14248 * {derivation method} of D must not be in the subset."
14249 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014250 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014251 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014252 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014253 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014254 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014255 } else {
14256 /*
14257 * SPEC (2.1) "B and D must be the same type definition."
14258 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014259 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014260 }
14261 /*
14262 * SPEC (2.2) "B must be D's {base type definition}."
14263 */
14264 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014265 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014266 /*
14267 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14268 * definition·."
14269 */
14270 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014271 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014272
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014273 if (IS_COMPLEX_TYPE(type->baseType)) {
14274 /*
14275 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14276 * must be validly derived from B given the subset as defined by this
14277 * constraint."
14278 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014279 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014280 baseType, set));
14281 } else {
14282 /*
14283 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14284 * must be validly derived from B given the subset as defined in Type
14285 * Derivation OK (Simple) (§3.14.6).
14286 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014287 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
14288 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014289}
14290
14291/**
14292 * xmlSchemaCheckCOSDerivedOK:
14293 * @type: the derived simple type definition
14294 * @baseType: the base type definition
14295 *
14296 * Calls:
14297 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014298 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014299 * Checks wheter @type can be validly derived from @baseType.
14300 *
14301 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014302 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014303static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014304xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014305 xmlSchemaTypePtr baseType,
14306 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014307{
14308 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014309 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014310 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014311 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014312}
14313
William M. Brack2f2a6632004-08-20 23:09:47 +000014314/**
14315 * xmlSchemaCheckCOSCTExtends:
14316 * @ctxt: the schema parser context
14317 * @type: the complex type definition
14318 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014319 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014320 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014321 * Derivation Valid (Extension) (cos-ct-extends)
14322 *
14323 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014324 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014325 * (1.5)
14326 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014327 *
14328 * Returns 0 if the constraints are satisfied, a positive
14329 * error code if not and -1 if an internal error occured.
14330 */
14331static int
14332xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14333 xmlSchemaTypePtr type)
14334{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014335 xmlSchemaTypePtr base = type->baseType;
14336 /*
14337 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14338 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014339 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014340 /*
14341 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014342 * then all of the following must be true:"
14343 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014344 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14345 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014346 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014347 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014348 */
14349 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14350 xmlSchemaPCustomErr(ctxt,
14351 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14352 NULL, type, NULL,
14353 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014354 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014355 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14356 }
14357 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014358 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014359 * uses}
14360 * of the complex type definition itself, that is, for every attribute
14361 * use in the {attribute uses} of the {base type definition}, there
14362 * must be an attribute use in the {attribute uses} of the complex
14363 * type definition itself whose {attribute declaration} has the same
14364 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014365 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014366 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014367 * NOTE (1.2): This will be already satisfied by the way the attribute
14368 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14369 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014370 */
14371
14372 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014373 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14374 * definition must also have one, and the base type definition's
14375 * {attribute wildcard}'s {namespace constraint} must be a subset
14376 * of the complex type definition's {attribute wildcard}'s {namespace
14377 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014378 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014379 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014380 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014381 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014382 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014383 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014384 if ((type->contentTypeDef != NULL) &&
14385 (type->contentTypeDef == base->contentTypeDef)) {
14386 /*
14387 * SPEC (1.4.1) "The {content type} of the {base type definition}
14388 * and the {content type} of the complex type definition itself
14389 * must be the same simple type definition"
14390 * PASS
14391 */
14392 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14393 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14394 /*
14395 * SPEC (1.4.2) "The {content type} of both the {base type
14396 * definition} and the complex type definition itself must
14397 * be empty."
14398 * PASS
14399 */
14400 } else {
14401 /*
14402 * SPEC (1.4.3) "All of the following must be true:"
14403 */
14404 if (type->subtypes == NULL) {
14405 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014406 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014407 * definition itself must specify a particle.
14408 */
14409 xmlSchemaPCustomErr(ctxt,
14410 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14411 NULL, type, NULL,
14412 "The content type must specify a particle", NULL);
14413 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14414 }
14415 /*
14416 * SPEC (1.4.3.2) "One of the following must be true:"
14417 */
14418 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14419 /*
14420 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14421 * definition} must be empty.
14422 * PASS
14423 */
14424 } else {
14425 /*
14426 * SPEC (1.4.3.2.2) "All of the following must be true:"
14427 */
14428 if ((type->contentType != base->contentType) ||
14429 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14430 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14431 /*
14432 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14433 * or both must be element-only."
14434 */
14435 xmlSchemaPCustomErr(ctxt,
14436 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14437 NULL, type, NULL,
14438 "The content type of both, the type and its base "
14439 "type, must either 'mixed' or 'element-only'", NULL);
14440 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014441 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014442 /*
14443 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14444 * complex type definition must be a ·valid extension·
14445 * of the {base type definition}'s particle, as defined
14446 * in Particle Valid (Extension) (§3.9.6)."
14447 *
14448 * NOTE that we won't check "Particle Valid (Extension)",
14449 * since it is ensured by the derivation process in
14450 * xmlSchemaTypeFixup(). We need to implement this when heading
14451 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014452 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014453 }
14454 /*
14455 * TODO (1.5)
14456 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014457 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014458 } else {
14459 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014460 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014461 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014462 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014463 if (type->contentTypeDef != base) {
14464 /*
14465 * SPEC (2.1) "The {content type} must be the same simple type
14466 * definition."
14467 */
14468 xmlSchemaPCustomErr(ctxt,
14469 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14470 NULL, type, NULL,
14471 "The content type must be the simple base type", NULL);
14472 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14473 }
14474 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14475 /*
14476 * SPEC (2.2) "The {final} of the {base type definition} must not
14477 * contain extension"
14478 * NOTE that this is the same as (1.1).
14479 */
14480 xmlSchemaPCustomErr(ctxt,
14481 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14482 NULL, type, NULL,
14483 "The 'final' of the base type definition "
14484 "contains 'extension'", NULL);
14485 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014486 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014487 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014488 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014489}
14490
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014491/**
14492 * xmlSchemaCheckDerivationOKRestriction:
14493 * @ctxt: the schema parser context
14494 * @type: the complex type definition
14495 *
14496 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014497 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014498 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14499 *
14500 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014501 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014502 * (5.4.2), (5.2.2.1)
14503 *
14504 * Returns 0 if the constraints are satisfied, a positive
14505 * error code if not and -1 if an internal error occured.
14506 */
14507static int
14508xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14509 xmlSchemaTypePtr type)
14510{
14511 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014512
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014513 /*
14514 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14515 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014516 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014517 base = type->baseType;
14518 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14519 /*
14520 * SPEC (1) "The {base type definition} must be a complex type
14521 * definition whose {final} does not contain restriction."
14522 */
14523 xmlSchemaPCustomErr(ctxt,
14524 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14525 NULL, type, NULL,
14526 "The 'final' of the base type definition "
14527 "contains 'restriction'", NULL);
14528 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14529 }
14530 /*
14531 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14532 *
14533 * SPEC (5) "One of the following must be true:"
14534 */
14535 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14536 /*
14537 * SPEC (5.1) "The {base type definition} must be the
14538 * ·ur-type definition·."
14539 * PASS
14540 */
14541 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14542 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14543 /*
14544 * SPEC (5.2.1) "The {content type} of the complex type definition
14545 * must be a simple type definition"
14546 *
14547 * SPEC (5.2.2) "One of the following must be true:"
14548 */
14549 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14550 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14551 /*
14552 * SPEC (5.2.2.1) "The {content type} of the {base type
14553 * definition} must be a simple type definition from which
14554 * the {content type} is validly derived given the empty
14555 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14556 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014557 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014558 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14559 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014560 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014561 /*
14562 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14563 * and have a particle which is ·emptiable· as defined in
14564 * Particle Emptiable (§3.9.6)."
14565 * PASS
14566 */
14567 } else {
14568 xmlSchemaPCustomErr(ctxt,
14569 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14570 NULL, type, NULL,
14571 "The content type of the base type must be either "
14572 "a simple type or 'mixed' and an emptiable particle", NULL);
14573 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14574 }
14575 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14576 /*
14577 * SPEC (5.3.1) "The {content type} of the complex type itself must
14578 * be empty"
14579 */
14580 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14581 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014582 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014583 * definition} must also be empty."
14584 * PASS
14585 */
14586 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14587 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14588 xmlSchemaIsParticleEmptiable(
14589 (xmlSchemaParticlePtr) base->subtypes)) {
14590 /*
14591 * SPEC (5.3.2.2) "The {content type} of the {base type
14592 * definition} must be elementOnly or mixed and have a particle
14593 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14594 * PASS
14595 */
14596 } else {
14597 xmlSchemaPCustomErr(ctxt,
14598 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14599 NULL, type, NULL,
14600 "The content type of the base type must be either "
14601 "empty or 'mixed' (or 'elements-only') and an emptiable "
14602 "particle", NULL);
14603 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14604 }
14605 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014606 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014607 /*
14608 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14609 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014610 */
14611 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
14612 /*
14613 * SPEC (5.4.1.2) "The {content type} of the complex type
14614 * definition itself and of the {base type definition} must be
14615 * mixed"
14616 */
14617 xmlSchemaPCustomErr(ctxt,
14618 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14619 NULL, type, NULL,
14620 "If the content type is 'mixed', then the content type of the "
14621 "base type must also be 'mixed'", NULL);
14622 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14623 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014624 /*
14625 * SPEC (5.4.2) "The particle of the complex type definition itself
14626 * must be a ·valid restriction· of the particle of the {content
14627 * type} of the {base type definition} as defined in Particle Valid
14628 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014629 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014630 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014631 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014632 } else {
14633 xmlSchemaPCustomErr(ctxt,
14634 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14635 NULL, type, NULL,
14636 "The type is not a valid restriction of its base type", NULL);
14637 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14638 }
14639 return (0);
14640}
14641
14642/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014643 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014644 * @ctxt: the schema parser context
14645 * @type: the complex type definition
14646 *
14647 * (3.4.6) Constraints on Complex Type Definition Schema Components
14648 *
14649 * Returns 0 if the constraints are satisfied, a positive
14650 * error code if not and -1 if an internal error occured.
14651 */
14652static int
14653xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14654 xmlSchemaTypePtr type)
14655{
14656 int ret;
14657 /*
14658 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014659 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014660 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14661 if (ret != 0)
14662 return (ret);
14663 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14664 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14665 else
14666 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14667 return (ret);
14668}
14669
14670/**
14671 * xmlSchemaCheckSRCCT:
14672 * @ctxt: the schema parser context
14673 * @type: the complex type definition
14674 *
14675 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014676 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014677 * Complex Type Definition Representation OK (src-ct)
14678 *
14679 * Returns 0 if the constraints are satisfied, a positive
14680 * error code if not and -1 if an internal error occured.
14681 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014682static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014683xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014684 xmlSchemaTypePtr type)
14685{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014686 xmlSchemaTypePtr base;
14687 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014688
14689 /*
14690 * TODO: Adjust the error codes here, as I used
14691 * XML_SCHEMAP_SRC_CT_1 only yet.
14692 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014693 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014694 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014695 /*
14696 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014697 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014698 * must be a complex type definition;
14699 */
14700 if (! IS_COMPLEX_TYPE(base)) {
14701 xmlChar *str = NULL;
14702 xmlSchemaPCustomErr(ctxt,
14703 XML_SCHEMAP_SRC_CT_1,
14704 NULL, type, type->node,
14705 "If using <complexContent>, the base type is expected to be "
14706 "a complex type. The base type '%s' is a simple type",
14707 xmlSchemaFormatQName(&str, base->targetNamespace,
14708 base->name));
14709 FREE_AND_NULL(str)
14710 return (XML_SCHEMAP_SRC_CT_1);
14711 }
14712 } else {
14713 /*
14714 * SPEC
14715 * 2 If the <simpleContent> alternative is chosen, all of the
14716 * following must be true:
14717 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14718 * base [attribute] must be one of the following:
14719 */
14720 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014721 if ((type->flags &
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014722 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14723 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014724 /*
14725 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014726 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014727 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014728 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014729 xmlSchemaPCustomErr(ctxt,
14730 XML_SCHEMAP_SRC_CT_1,
14731 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014732 "If using <simpleContent> and <restriction>, the base "
14733 "type must be a complex type. The base type '%s' is "
14734 "a simple type",
14735 xmlSchemaFormatQName(&str, base->targetNamespace,
14736 base->name));
14737 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014738 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014739 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014740 } else {
14741 /* Base type is a complex type. */
14742 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14743 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14744 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014745 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014746 * simple type definition;
14747 * PASS
14748 */
14749 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014750 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014751 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014752 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014753 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014754 type->name);
14755 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014756 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014757 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14758 (type->flags &
14759 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014760
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014761 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014762 * 2.1.2 only if the <restriction> alternative is also
14763 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014764 * is mixed and a particle emptiable.
14765 */
14766 if (! xmlSchemaIsParticleEmptiable(
14767 (xmlSchemaParticlePtr) base->subtypes)) {
14768 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014769 } else
14770 /*
14771 * Attention: at this point the <simpleType> child is in
14772 * ->contentTypeDef (put there during parsing).
14773 */
14774 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014775 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014776 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014777 * 2.2 If clause 2.1.2 above is satisfied, then there
14778 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014779 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014780 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014781 /* TODO: Change error code to ..._SRC_CT_2_2. */
14782 xmlSchemaPCustomErr(ctxt,
14783 XML_SCHEMAP_SRC_CT_1,
14784 NULL, type, NULL,
14785 "A <simpleType> is expected among the children "
14786 "of <restriction>, if <simpleContent> is used and "
14787 "the base type '%s' is a complex type",
14788 xmlSchemaFormatQName(&str, base->targetNamespace,
14789 base->name));
14790 FREE_AND_NULL(str)
14791 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014792 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014793 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014794 ret = XML_SCHEMAP_SRC_CT_1;
14795 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014796 }
14797 if (ret > 0) {
14798 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014799 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014800 xmlSchemaPCustomErr(ctxt,
14801 XML_SCHEMAP_SRC_CT_1,
14802 NULL, type, NULL,
14803 "If <simpleContent> and <restriction> is used, the "
14804 "base type must be a simple type or a complex type with "
14805 "mixed content and particle emptiable. The base type "
14806 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014807 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014808 base->name));
14809 } else {
14810 xmlSchemaPCustomErr(ctxt,
14811 XML_SCHEMAP_SRC_CT_1,
14812 NULL, type, NULL,
14813 "If <simpleContent> and <extension> is used, the "
14814 "base type must be a simple type. The base type '%s' "
14815 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014816 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014817 base->name));
14818 }
14819 FREE_AND_NULL(str)
14820 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014821 }
14822 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014823 * SPEC (3) "The corresponding complex type definition component must
14824 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014825 * Definition Schema Components (§3.4.6);"
14826 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014827 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014828 /*
14829 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014830 * above for {attribute wildcard} is satisfied, the intensional
14831 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014832 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014833 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014834 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014835 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014836}
William M. Brack2f2a6632004-08-20 23:09:47 +000014837
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014838#ifdef ENABLE_PARTICLE_RESTRICTION
14839/**
14840 * xmlSchemaCheckParticleRangeOK:
14841 * @ctxt: the schema parser context
14842 * @type: the complex type definition
14843 *
14844 * (3.9.6) Constraints on Particle Schema Components
14845 * Schema Component Constraint:
14846 * Occurrence Range OK (range-ok)
14847 *
14848 * STATUS: complete
14849 *
14850 * Returns 0 if the constraints are satisfied, a positive
14851 * error code if not and -1 if an internal error occured.
14852 */
14853static int
14854xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
14855 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014856{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014857 if (rmin < bmin)
14858 return (1);
14859 if ((bmax != UNBOUNDED) &&
14860 (rmax > bmax))
14861 return (1);
14862 return (0);
14863}
14864
14865/**
14866 * xmlSchemaCheckRCaseNameAndTypeOK:
14867 * @ctxt: the schema parser context
14868 * @r: the restricting element declaration particle
14869 * @b: the base element declaration particle
14870 *
14871 * (3.9.6) Constraints on Particle Schema Components
14872 * Schema Component Constraint:
14873 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
14874 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014875 *
14876 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014877 * MISSING (3.2.3)
14878 * CLARIFY: (3.2.2)
14879 *
14880 * Returns 0 if the constraints are satisfied, a positive
14881 * error code if not and -1 if an internal error occured.
14882 */
14883static int
14884xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
14885 xmlSchemaParticlePtr r,
14886 xmlSchemaParticlePtr b)
14887{
14888 xmlSchemaElementPtr elemR, elemB;
14889
14890 /* TODO: Error codes (rcase-NameAndTypeOK). */
14891 elemR = (xmlSchemaElementPtr) r->children;
14892 elemB = (xmlSchemaElementPtr) b->children;
14893 /*
14894 * SPEC (1) "The declarations' {name}s and {target namespace}s are
14895 * the same."
14896 */
14897 if ((elemR != elemB) &&
14898 ((! xmlStrEqual(elemR->name, elemB->name)) ||
14899 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
14900 return (1);
14901 /*
14902 * SPEC (2) "R's occurrence range is a valid restriction of B's
14903 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14904 */
14905 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14906 b->minOccurs, b->maxOccurs) != 0)
14907 return (1);
14908 /*
14909 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
14910 * {scope} are global."
14911 */
14912 if (elemR == elemB)
14913 return (0);
14914 /*
14915 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
14916 */
14917 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
14918 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
14919 return (1);
14920 /*
14921 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
14922 * or is not fixed, or R's declaration's {value constraint} is fixed
14923 * with the same value."
14924 */
14925 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
14926 ((elemR->value == NULL) ||
14927 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
14928 /* TODO: Equality of the initial value or normalized or canonical? */
14929 (! xmlStrEqual(elemR->value, elemB->value))))
14930 return (1);
14931 /*
14932 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
14933 * definitions} is a subset of B's declaration's {identity-constraint
14934 * definitions}, if any."
14935 */
14936 if (elemB->idcs != NULL) {
14937 /* TODO */
14938 }
14939 /*
14940 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
14941 * superset of B's declaration's {disallowed substitutions}."
14942 */
14943 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
14944 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
14945 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
14946 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
14947 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
14948 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
14949 return (1);
14950 /*
14951 * SPEC (3.2.5) "R's {type definition} is validly derived given
14952 * {extension, list, union} from B's {type definition}"
14953 *
14954 * BADSPEC TODO: What's the point of adding "list" and "union" to the
14955 * set, if the corresponding constraints handle "restriction" and
14956 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014957 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014958 */
14959 {
14960 int set = 0;
14961
14962 set |= SUBSET_EXTENSION;
14963 set |= SUBSET_LIST;
14964 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014965 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014966 elemB->subtypes, set) != 0)
14967 return (1);
14968 }
14969 return (0);
14970}
14971
14972/**
14973 * xmlSchemaCheckRCaseNSCompat:
14974 * @ctxt: the schema parser context
14975 * @r: the restricting element declaration particle
14976 * @b: the base wildcard particle
14977 *
14978 * (3.9.6) Constraints on Particle Schema Components
14979 * Schema Component Constraint:
14980 * Particle Derivation OK (Elt:Any -- NSCompat)
14981 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014982 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014983 * STATUS: complete
14984 *
14985 * Returns 0 if the constraints are satisfied, a positive
14986 * error code if not and -1 if an internal error occured.
14987 */
14988static int
14989xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
14990 xmlSchemaParticlePtr r,
14991 xmlSchemaParticlePtr b)
14992{
14993 /* TODO:Error codes (rcase-NSCompat). */
14994 /*
14995 * SPEC "For an element declaration particle to be a ·valid restriction·
14996 * of a wildcard particle all of the following must be true:"
14997 *
14998 * SPEC (1) "The element declaration's {target namespace} is ·valid·
14999 * with respect to the wildcard's {namespace constraint} as defined by
15000 * Wildcard allows Namespace Name (§3.10.4)."
15001 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015002 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015003 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
15004 return (1);
15005 /*
15006 * SPEC (2) "R's occurrence range is a valid restriction of B's
15007 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15008 */
15009 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15010 b->minOccurs, b->maxOccurs) != 0)
15011 return (1);
15012
15013 return (0);
15014}
15015
15016/**
15017 * xmlSchemaCheckRCaseRecurseAsIfGroup:
15018 * @ctxt: the schema parser context
15019 * @r: the restricting element declaration particle
15020 * @b: the base model group particle
15021 *
15022 * (3.9.6) Constraints on Particle Schema Components
15023 * Schema Component Constraint:
15024 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
15025 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015026 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015027 * STATUS: TODO
15028 *
15029 * Returns 0 if the constraints are satisfied, a positive
15030 * error code if not and -1 if an internal error occured.
15031 */
15032static int
15033xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
15034 xmlSchemaParticlePtr r,
15035 xmlSchemaParticlePtr b)
15036{
15037 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
15038 TODO
15039 return (0);
15040}
15041
15042/**
15043 * xmlSchemaCheckRCaseNSSubset:
15044 * @ctxt: the schema parser context
15045 * @r: the restricting wildcard particle
15046 * @b: the base wildcard particle
15047 *
15048 * (3.9.6) Constraints on Particle Schema Components
15049 * Schema Component Constraint:
15050 * Particle Derivation OK (Any:Any -- NSSubset)
15051 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015052 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015053 * STATUS: complete
15054 *
15055 * Returns 0 if the constraints are satisfied, a positive
15056 * error code if not and -1 if an internal error occured.
15057 */
15058static int
15059xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15060 xmlSchemaParticlePtr r,
15061 xmlSchemaParticlePtr b,
15062 int isAnyTypeBase)
15063{
15064 /* TODO: Error codes (rcase-NSSubset). */
15065 /*
15066 * SPEC (1) "R's occurrence range is a valid restriction of B's
15067 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15068 */
15069 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15070 b->minOccurs, b->maxOccurs))
15071 return (1);
15072 /*
15073 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15074 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15075 */
15076 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15077 (xmlSchemaWildcardPtr) b->children))
15078 return (1);
15079 /*
15080 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15081 * definition·, R's {process contents} must be identical to or stronger
15082 * than B's {process contents}, where strict is stronger than lax is
15083 * stronger than skip."
15084 */
15085 if (! isAnyTypeBase) {
15086 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15087 ((xmlSchemaWildcardPtr) b->children)->processContents)
15088 return (1);
15089 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015090
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015091 return (0);
15092}
15093
15094/**
15095 * xmlSchemaCheckCOSParticleRestrict:
15096 * @ctxt: the schema parser context
15097 * @type: the complex type definition
15098 *
15099 * (3.9.6) Constraints on Particle Schema Components
15100 * Schema Component Constraint:
15101 * Particle Valid (Restriction) (cos-particle-restrict)
15102 *
15103 * STATUS: TODO
15104 *
15105 * Returns 0 if the constraints are satisfied, a positive
15106 * error code if not and -1 if an internal error occured.
15107 */
15108static int
15109xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15110 xmlSchemaParticlePtr r,
15111 xmlSchemaParticlePtr b)
15112{
15113 int ret = 0;
15114
15115 /*part = GET_PARTICLE(type);
15116 basePart = GET_PARTICLE(base);
15117 */
15118
15119 TODO
15120
15121 /*
15122 * SPEC (1) "They are the same particle."
15123 */
15124 if (r == b)
15125 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015126
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015127
15128 return (0);
15129}
15130
15131/**
15132 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15133 * @ctxt: the schema parser context
15134 * @r: the model group particle
15135 * @b: the base wildcard particle
15136 *
15137 * (3.9.6) Constraints on Particle Schema Components
15138 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015139 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015140 * NSRecurseCheckCardinality)
15141 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015142 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015143 * STATUS: TODO: subst-groups
15144 *
15145 * Returns 0 if the constraints are satisfied, a positive
15146 * error code if not and -1 if an internal error occured.
15147 */
15148static int
15149xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15150 xmlSchemaParticlePtr r,
15151 xmlSchemaParticlePtr b)
15152{
15153 xmlSchemaParticlePtr part;
15154 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15155 if ((r->children == NULL) || (r->children->children == NULL))
15156 return (-1);
15157 /*
15158 * SPEC "For a group particle to be a ·valid restriction· of a
15159 * wildcard particle..."
15160 *
15161 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015162 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015163 * Particle Valid (Restriction) (§3.9.6)."
15164 */
15165 part = (xmlSchemaParticlePtr) r->children->children;
15166 do {
15167 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15168 return (1);
15169 part = (xmlSchemaParticlePtr) part->next;
15170 } while (part != NULL);
15171 /*
15172 * SPEC (2) "The effective total range of the group [...] is a
15173 * valid restriction of B's occurrence range as defined by
15174 * Occurrence Range OK (§3.9.6)."
15175 */
15176 if (xmlSchemaCheckParticleRangeOK(
15177 xmlSchemaGetParticleTotalRangeMin(r),
15178 xmlSchemaGetParticleTotalRangeMax(r),
15179 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015180 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015181 return (0);
15182}
15183
15184/**
15185 * xmlSchemaCheckRCaseRecurse:
15186 * @ctxt: the schema parser context
15187 * @r: the <all> or <sequence> model group particle
15188 * @b: the base <all> or <sequence> model group particle
15189 *
15190 * (3.9.6) Constraints on Particle Schema Components
15191 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015192 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015193 Recurse)
15194 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015195 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015196 * STATUS: ?
15197 * TODO: subst-groups
15198 *
15199 * Returns 0 if the constraints are satisfied, a positive
15200 * error code if not and -1 if an internal error occured.
15201 */
15202static int
15203xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15204 xmlSchemaParticlePtr r,
15205 xmlSchemaParticlePtr b)
15206{
15207 /* xmlSchemaParticlePtr part; */
15208 /* TODO: Error codes (rcase-Recurse). */
15209 if ((r->children == NULL) || (b->children == NULL) ||
15210 (r->children->type != b->children->type))
15211 return (-1);
15212 /*
15213 * SPEC "For an all or sequence group particle to be a ·valid
15214 * restriction· of another group particle with the same {compositor}..."
15215 *
15216 * SPEC (1) "R's occurrence range is a valid restriction of B's
15217 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15218 */
15219 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15220 b->minOccurs, b->maxOccurs))
15221 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015222
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015223
15224 return (0);
15225}
15226
15227#endif
15228
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015229#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15230 xmlSchemaPCustomErrExt(pctxt, \
15231 XML_SCHEMAP_INVALID_FACET_VALUE, \
15232 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15233 "It is an error for both '%s' and '%s' to be specified on the "\
15234 "same type definition", \
15235 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15236 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15237
15238#define FACET_RESTR_ERR(fac1, msg) \
15239 xmlSchemaPCustomErr(pctxt, \
15240 XML_SCHEMAP_INVALID_FACET_VALUE, \
15241 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015242 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015243
15244#define FACET_RESTR_FIXED_ERR(fac) \
15245 xmlSchemaPCustomErr(pctxt, \
15246 XML_SCHEMAP_INVALID_FACET_VALUE, \
15247 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15248 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015249 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015250
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015251static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015252xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15253 xmlSchemaFacetPtr facet1,
15254 xmlSchemaFacetPtr facet2,
15255 int lessGreater,
15256 int orEqual,
15257 int ofBase)
15258{
15259 xmlChar *msg = NULL;
15260
15261 msg = xmlStrdup(BAD_CAST "'");
15262 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15263 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15264 if (lessGreater == 0)
15265 msg = xmlStrcat(msg, BAD_CAST " equal to");
15266 if (lessGreater == 1)
15267 msg = xmlStrcat(msg, BAD_CAST " greater than");
15268 else
15269 msg = xmlStrcat(msg, BAD_CAST " less than");
15270
15271 if (orEqual)
15272 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15273 msg = xmlStrcat(msg, BAD_CAST " '");
15274 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15275 if (ofBase)
15276 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15277 else
15278 msg = xmlStrcat(msg, BAD_CAST "'");
15279
15280 xmlSchemaPCustomErr(pctxt,
15281 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015282 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015283 (const char *) msg, NULL);
15284
15285 if (msg != NULL)
15286 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015287}
15288
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015289static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015290xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15291 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015292{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015293 xmlSchemaTypePtr base = type->baseType;
15294 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015295 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015296 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15297 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15298 fmininc = NULL, fmaxinc = NULL,
15299 fminexc = NULL, fmaxexc = NULL,
15300 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15301 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15302 bfmininc = NULL, bfmaxinc = NULL,
15303 bfminexc = NULL, bfmaxexc = NULL;
15304 int res, err = 0, fixedErr;
15305 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015306 * 3 The {facets} of R are the union of S and the {facets}
15307 * of B, eliminating duplicates. To eliminate duplicates,
15308 * when a facet of the same kind occurs in both S and the
15309 * {facets} of B, the one in the {facets} of B is not
15310 * included, with the exception of enumeration and pattern
15311 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015312 * are allowed.
15313 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015314
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015315 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15316 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015317
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015318 last = type->facetSet;
15319 if (last != NULL)
15320 while (last->next != NULL)
15321 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015322
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015323 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15324 facet = cur->facet;
15325 switch (facet->type) {
15326 case XML_SCHEMA_FACET_LENGTH:
15327 flength = facet; break;
15328 case XML_SCHEMA_FACET_MINLENGTH:
15329 fminlen = facet; break;
15330 case XML_SCHEMA_FACET_MININCLUSIVE:
15331 fmininc = facet; break;
15332 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15333 fminexc = facet; break;
15334 case XML_SCHEMA_FACET_MAXLENGTH:
15335 fmaxlen = facet; break;
15336 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15337 fmaxinc = facet; break;
15338 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15339 fmaxexc = facet; break;
15340 case XML_SCHEMA_FACET_TOTALDIGITS:
15341 ftotdig = facet; break;
15342 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15343 ffracdig = facet; break;
15344 default:
15345 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015346 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015347 }
15348 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15349 facet = cur->facet;
15350 switch (facet->type) {
15351 case XML_SCHEMA_FACET_LENGTH:
15352 bflength = facet; break;
15353 case XML_SCHEMA_FACET_MINLENGTH:
15354 bfminlen = facet; break;
15355 case XML_SCHEMA_FACET_MININCLUSIVE:
15356 bfmininc = facet; break;
15357 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15358 bfminexc = facet; break;
15359 case XML_SCHEMA_FACET_MAXLENGTH:
15360 bfmaxlen = facet; break;
15361 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15362 bfmaxinc = facet; break;
15363 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15364 bfmaxexc = facet; break;
15365 case XML_SCHEMA_FACET_TOTALDIGITS:
15366 bftotdig = facet; break;
15367 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15368 bffracdig = facet; break;
15369 default:
15370 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015371 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015372 }
15373 err = 0;
15374 /*
15375 * length and minLength or maxLength (2.2) + (3.2)
15376 */
15377 if (flength && (fminlen || fmaxlen)) {
15378 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15379 "either of 'minLength' or 'maxLength' to be specified on "
15380 "the same type definition")
15381 }
15382 /*
15383 * Mutual exclusions in the same derivation step.
15384 */
15385 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015386 /*
15387 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015388 */
15389 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15390 }
15391 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015392 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015393 * SCC "minInclusive and minExclusive"
15394 */
15395 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015396 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015397
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015398 if (flength && bflength) {
15399 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015400 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015401 * The values have to be equal.
15402 */
15403 res = xmlSchemaCompareValues(flength->val, bflength->val);
15404 if (res == -2)
15405 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015406 if (res != 0)
15407 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15408 if ((res != 0) && (bflength->fixed)) {
15409 FACET_RESTR_FIXED_ERR(flength)
15410 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015411
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015412 }
15413 if (fminlen && bfminlen) {
15414 /*
15415 * SCC "minLength valid restriction"
15416 * minLength >= BASE minLength
15417 */
15418 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15419 if (res == -2)
15420 goto internal_error;
15421 if (res == -1)
15422 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15423 if ((res != 0) && (bfminlen->fixed)) {
15424 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015425 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015426 }
15427 if (fmaxlen && bfmaxlen) {
15428 /*
15429 * SCC "maxLength valid restriction"
15430 * maxLength <= BASE minLength
15431 */
15432 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15433 if (res == -2)
15434 goto internal_error;
15435 if (res == 1)
15436 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15437 if ((res != 0) && (bfmaxlen->fixed)) {
15438 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015439 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015440 }
15441 /*
15442 * SCC "length and minLength or maxLength"
15443 */
15444 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015445 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015446 if (flength) {
15447 if (! fminlen)
15448 flength = bflength;
15449 if (fminlen) {
15450 /* (1.1) length >= minLength */
15451 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15452 if (res == -2)
15453 goto internal_error;
15454 if (res == -1)
15455 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15456 }
15457 if (! fmaxlen)
15458 fmaxlen = bfmaxlen;
15459 if (fmaxlen) {
15460 /* (2.1) length <= maxLength */
15461 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15462 if (res == -2)
15463 goto internal_error;
15464 if (res == 1)
15465 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15466 }
15467 }
15468 if (fmaxinc) {
15469 /*
15470 * "maxInclusive"
15471 */
15472 if (fmininc) {
15473 /* SCC "maxInclusive >= minInclusive" */
15474 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15475 if (res == -2)
15476 goto internal_error;
15477 if (res == -1) {
15478 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15479 }
15480 }
15481 /*
15482 * SCC "maxInclusive valid restriction"
15483 */
15484 if (bfmaxinc) {
15485 /* maxInclusive <= BASE maxInclusive */
15486 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15487 if (res == -2)
15488 goto internal_error;
15489 if (res == 1)
15490 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15491 if ((res != 0) && (bfmaxinc->fixed)) {
15492 FACET_RESTR_FIXED_ERR(fmaxinc)
15493 }
15494 }
15495 if (bfmaxexc) {
15496 /* maxInclusive < BASE maxExclusive */
15497 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15498 if (res == -2)
15499 goto internal_error;
15500 if (res != -1) {
15501 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15502 }
15503 }
15504 if (bfmininc) {
15505 /* maxInclusive >= BASE minInclusive */
15506 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15507 if (res == -2)
15508 goto internal_error;
15509 if (res == -1) {
15510 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15511 }
15512 }
15513 if (bfminexc) {
15514 /* maxInclusive > BASE minExclusive */
15515 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15516 if (res == -2)
15517 goto internal_error;
15518 if (res != 1) {
15519 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15520 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015521 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015522 }
15523 if (fmaxexc) {
15524 /*
15525 * "maxExclusive >= minExclusive"
15526 */
15527 if (fminexc) {
15528 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15529 if (res == -2)
15530 goto internal_error;
15531 if (res == -1) {
15532 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15533 }
15534 }
15535 /*
15536 * "maxExclusive valid restriction"
15537 */
15538 if (bfmaxexc) {
15539 /* maxExclusive <= BASE maxExclusive */
15540 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15541 if (res == -2)
15542 goto internal_error;
15543 if (res == 1) {
15544 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15545 }
15546 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015547 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015548 }
15549 }
15550 if (bfmaxinc) {
15551 /* maxExclusive <= BASE maxInclusive */
15552 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15553 if (res == -2)
15554 goto internal_error;
15555 if (res == 1) {
15556 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15557 }
15558 }
15559 if (bfmininc) {
15560 /* maxExclusive > BASE minInclusive */
15561 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15562 if (res == -2)
15563 goto internal_error;
15564 if (res != 1) {
15565 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15566 }
15567 }
15568 if (bfminexc) {
15569 /* maxExclusive > BASE minExclusive */
15570 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15571 if (res == -2)
15572 goto internal_error;
15573 if (res != 1) {
15574 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15575 }
15576 }
15577 }
15578 if (fminexc) {
15579 /*
15580 * "minExclusive < maxInclusive"
15581 */
15582 if (fmaxinc) {
15583 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15584 if (res == -2)
15585 goto internal_error;
15586 if (res != -1) {
15587 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15588 }
15589 }
15590 /*
15591 * "minExclusive valid restriction"
15592 */
15593 if (bfminexc) {
15594 /* minExclusive >= BASE minExclusive */
15595 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15596 if (res == -2)
15597 goto internal_error;
15598 if (res == -1) {
15599 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15600 }
15601 if ((res != 0) && (bfminexc->fixed)) {
15602 FACET_RESTR_FIXED_ERR(fminexc)
15603 }
15604 }
15605 if (bfmaxinc) {
15606 /* minExclusive <= BASE maxInclusive */
15607 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15608 if (res == -2)
15609 goto internal_error;
15610 if (res == 1) {
15611 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15612 }
15613 }
15614 if (bfmininc) {
15615 /* minExclusive >= BASE minInclusive */
15616 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15617 if (res == -2)
15618 goto internal_error;
15619 if (res == -1) {
15620 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15621 }
15622 }
15623 if (bfmaxexc) {
15624 /* minExclusive < BASE maxExclusive */
15625 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15626 if (res == -2)
15627 goto internal_error;
15628 if (res != -1) {
15629 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15630 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015631 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015632 }
15633 if (fmininc) {
15634 /*
15635 * "minInclusive < maxExclusive"
15636 */
15637 if (fmaxexc) {
15638 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15639 if (res == -2)
15640 goto internal_error;
15641 if (res != -1) {
15642 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15643 }
15644 }
15645 /*
15646 * "minExclusive valid restriction"
15647 */
15648 if (bfmininc) {
15649 /* minInclusive >= BASE minInclusive */
15650 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15651 if (res == -2)
15652 goto internal_error;
15653 if (res == -1) {
15654 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15655 }
15656 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015657 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015658 }
15659 }
15660 if (bfmaxinc) {
15661 /* minInclusive <= BASE maxInclusive */
15662 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15663 if (res == -2)
15664 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000015665 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015666 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15667 }
15668 }
15669 if (bfminexc) {
15670 /* minInclusive > BASE minExclusive */
15671 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15672 if (res == -2)
15673 goto internal_error;
15674 if (res != 1)
15675 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15676 }
15677 if (bfmaxexc) {
15678 /* minInclusive < BASE maxExclusive */
15679 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15680 if (res == -2)
15681 goto internal_error;
15682 if (res != -1)
15683 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15684 }
15685 }
15686 if (ftotdig && bftotdig) {
15687 /*
15688 * SCC " totalDigits valid restriction"
15689 * totalDigits <= BASE totalDigits
15690 */
15691 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15692 if (res == -2)
15693 goto internal_error;
15694 if (res == 1)
15695 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15696 -1, 1, 1);
15697 if ((res != 0) && (bftotdig->fixed)) {
15698 FACET_RESTR_FIXED_ERR(ftotdig)
15699 }
15700 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015701 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015702 /*
15703 * SCC "fractionDigits valid restriction"
15704 * fractionDigits <= BASE fractionDigits
15705 */
15706 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15707 if (res == -2)
15708 goto internal_error;
15709 if (res == 1)
15710 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15711 -1, 1, 1);
15712 if ((res != 0) && (bffracdig->fixed)) {
15713 FACET_RESTR_FIXED_ERR(ffracdig)
15714 }
15715 }
15716 /*
15717 * SCC "fractionDigits less than or equal to totalDigits"
15718 */
15719 if (! ftotdig)
15720 ftotdig = bftotdig;
15721 if (! ffracdig)
15722 ffracdig = bffracdig;
15723 if (ftotdig && ffracdig) {
15724 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15725 if (res == -2)
15726 goto internal_error;
15727 if (res == 1)
15728 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15729 -1, 1, 0);
15730 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015731 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015732 * *Enumerations* won' be added here, since only the first set
15733 * of enumerations in the ancestor-or-self axis is used
15734 * for validation, plus we need to use the base type of those
15735 * enumerations for whitespace.
15736 *
15737 * *Patterns*: won't be add here, since they are ORed at
15738 * type level and ANDed at ancestor level. This will
15739 * happed during validation by walking the base axis
15740 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015741 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015742 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15743 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015744 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015745 * Special handling of enumerations and patterns.
15746 * TODO: hmm, they should not appear in the set, so remove this.
15747 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015748 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015749 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015750 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015751 /*
15752 * Search for a duplicate facet in the current type.
15753 */
15754 link = type->facetSet;
15755 err = 0;
15756 fixedErr = 0;
15757 while (link != NULL) {
15758 facet = link->facet;
15759 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015760 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015761 case XML_SCHEMA_FACET_WHITESPACE:
15762 /*
15763 * The whitespace must be stronger.
15764 */
15765 if (facet->whitespace < bfacet->whitespace) {
15766 FACET_RESTR_ERR(flength,
15767 "The 'whitespace' value has to be equal to "
15768 "or stronger than the 'whitespace' value of "
15769 "the base type")
15770 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015771 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015772 (facet->whitespace != bfacet->whitespace)) {
15773 FACET_RESTR_FIXED_ERR(facet)
15774 }
15775 break;
15776 default:
15777 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015778 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015779 /* Duplicate found. */
15780 break;
15781 }
15782 link = link->next;
15783 }
15784 /*
15785 * If no duplicate was found: add the base types's facet
15786 * to the set.
15787 */
15788 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015789 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015790 xmlMalloc(sizeof(xmlSchemaFacetLink));
15791 if (link == NULL) {
15792 xmlSchemaPErrMemory(pctxt,
15793 "deriving facets, creating a facet link", NULL);
15794 return (-1);
15795 }
15796 link->facet = cur->facet;
15797 link->next = NULL;
15798 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015799 type->facetSet = link;
15800 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015801 last->next = link;
15802 last = link;
15803 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015804
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015805 }
15806
15807 return (0);
15808internal_error:
15809 xmlSchemaPCustomErr(pctxt,
15810 XML_SCHEMAP_INVALID_FACET_VALUE,
15811 NULL, type, NULL,
15812 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15813 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015814}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015815
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015816static int
15817xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15818 xmlSchemaTypePtr type)
15819{
15820 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
15821 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015822 * The actual value is then formed by replacing any union type
15823 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015824 * {member type definitions}, in order.
15825 */
15826 link = type->memberTypes;
15827 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015828
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015829 if (IS_NOT_TYPEFIXED(link->type))
15830 xmlSchemaTypeFixup(link->type, pctxt, NULL);
15831
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015832 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015833 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015834 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015835 link->type = subLink->type;
15836 if (subLink->next != NULL) {
15837 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015838 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015839 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015840 while (subLink != NULL) {
15841 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015842 xmlMalloc(sizeof(xmlSchemaTypeLink));
15843 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015844 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015845 NULL);
15846 return (-1);
15847 }
15848 newLink->type = subLink->type;
15849 prevLink->next = newLink;
15850 prevLink = newLink;
15851 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015852
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015853 subLink = subLink->next;
15854 }
15855 }
15856 }
15857 }
15858 link = link->next;
15859 }
15860 return (0);
15861}
15862
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015863static void
15864xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
15865{
15866 int has = 0, needVal = 0, normVal = 0;
15867
15868 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
15869 if (has) {
15870 needVal = (type->baseType->flags &
15871 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
15872 normVal = (type->baseType->flags &
15873 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
15874 }
15875 if (type->facets != NULL) {
15876 xmlSchemaFacetPtr fac;
15877
15878 for (fac = type->facets; fac != NULL; fac = fac->next) {
15879 switch (fac->type) {
15880 case XML_SCHEMA_FACET_WHITESPACE:
15881 break;
15882 case XML_SCHEMA_FACET_PATTERN:
15883 normVal = 1;
15884 has = 1;
15885 break;
15886 case XML_SCHEMA_FACET_ENUMERATION:
15887 needVal = 1;
15888 normVal = 1;
15889 has = 1;
15890 break;
15891 default:
15892 has = 1;
15893 break;
15894 }
15895 }
15896 }
15897 if (normVal)
15898 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
15899 if (needVal)
15900 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15901 if (has)
15902 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
15903
15904 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
15905 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
15906 /*
15907 * OPTIMIZE VAL TODO: Some facets need a computed value.
15908 */
15909 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
15910 (prim->builtInType != XML_SCHEMAS_STRING)) {
15911 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15912 }
15913 }
15914}
15915
15916static int
15917xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
15918{
15919
15920
15921 /*
15922 * Evaluate the whitespace-facet value.
15923 */
15924 if (VARIETY_LIST(type)) {
15925 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15926 return (0);
15927 } else if (VARIETY_UNION(type))
15928 return (0);
15929
15930 if (type->facetSet != NULL) {
15931 xmlSchemaFacetLinkPtr lin;
15932
15933 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
15934 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
15935 switch (lin->facet->whitespace) {
15936 case XML_SCHEMAS_FACET_PRESERVE:
15937 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15938 break;
15939 case XML_SCHEMAS_FACET_REPLACE:
15940 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15941 break;
15942 case XML_SCHEMAS_FACET_COLLAPSE:
15943 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15944 break;
15945 default:
15946 return (-1);
15947 }
15948 return (0);
15949 }
15950 }
15951 }
15952 /*
15953 * For all ·atomic· datatypes other than string (and types ·derived·
15954 * by ·restriction· from it) the value of whiteSpace is fixed to
15955 * collapse
15956 */
15957 {
15958 xmlSchemaTypePtr anc;
15959
15960 for (anc = type->baseType; anc != NULL &&
15961 anc->builtInType != XML_SCHEMAS_ANYTYPE;
15962 anc = anc->baseType) {
15963
15964 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
15965 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
15966 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15967
15968 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
15969 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
15970 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15971
15972 } else
15973 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15974 break;
15975 }
15976 }
15977 return (0);
15978 }
15979 return (0);
15980}
15981
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015982/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015983 * xmlSchemaTypeFixup:
15984 * @typeDecl: the schema type definition
15985 * @ctxt: the schema parser context
15986 *
15987 * Fixes the content model of the type.
15988 */
15989static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015990xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015991 xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000015992{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015993 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000015994 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015995 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
15996 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015997 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015998 if (! IS_NOT_TYPEFIXED(type))
15999 return;
16000 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000016001 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016002 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016003
16004 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016005 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016006 XML_SCHEMAP_INTERNAL,
16007 NULL, type, NULL,
16008 "Internal error: xmlSchemaTypeFixup, "
16009 "baseType is missing on '%s'", type->name);
16010 return;
16011 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016012
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016013 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016014 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016015
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016016 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016017 * Type-fix the base type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016018 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016019 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016020 xmlSchemaTypeFixup(baseType, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016021 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
16022 /*
16023 * Skip fixup if the base type is invalid.
16024 * TODO: Generate a warning!
16025 */
16026 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016027 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016028 /*
16029 * This basically checks if the base type can be derived.
16030 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016031 if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016032 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
16033 return;
16034 }
16035 /*
16036 * Fixup the content type.
16037 */
16038 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
16039 /*
16040 * Corresponds to <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016041 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016042 if ((IS_COMPLEX_TYPE(baseType)) &&
16043 (baseType->contentTypeDef != NULL) &&
16044 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016045 xmlSchemaTypePtr contentBase, content;
16046 char buf[30];
16047 const xmlChar *tmpname;
16048 /*
16049 * SPEC (1) If <restriction> + base type is <complexType>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016050 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016051 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016052 if (type->contentTypeDef != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016053 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016054 * SPEC (1.1) "the simple type definition corresponding to the
16055 * <simpleType> among the [children] of <restriction> if there
16056 * is one;"
16057 * Note that this "<simpleType> among the [children]" was put
16058 * into ->contentTypeDef during parsing.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016059 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016060 contentBase = type->contentTypeDef;
16061 type->contentTypeDef = NULL;
16062 } else {
16063 /*
16064 * (1.2) "...otherwise (<restriction> has no <simpleType>
16065 * among its [children]), the simple type definition which
16066 * is the {content type} of the ... base type."
16067 */
16068 contentBase = baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016069 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016070 /*
16071 * SPEC
16072 * "... a simple type definition which restricts the simple
16073 * type definition identified in clause 1.1 or clause 1.2
16074 * with a set of facet components"
16075 *
16076 * Create the anonymous simple type, which will be the content
16077 * type of the complex type.
16078 */
16079 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
16080 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
16081 content = xmlSchemaAddType(pctxt,
16082 pctxt->schema, tmpname, tmpname, type->node);
16083 if (content == NULL)
16084 return;
16085 /*
16086 * We will use the same node as for the <complexType>
16087 * to have it somehow anchored in the schema doc.
16088 */
16089 content->node = type->node;
16090 content->type = XML_SCHEMA_TYPE_SIMPLE;
16091 content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16092 content->baseType = contentBase;
16093 /*
16094 * Move the facets, previously anchored on the complexType.
16095 */
16096 content->facets = type->facets;
16097 type->facets = NULL;
16098 content->facetSet = type->facetSet;
16099 type->facetSet = NULL;
16100
16101 type->contentTypeDef = content;
16102 if (IS_NOT_TYPEFIXED(contentBase))
16103 xmlSchemaTypeFixup(contentBase, pctxt, NULL);
16104 xmlSchemaTypeFixup(content, pctxt, NULL);
16105
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016106 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16107 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16108 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16109 /*
16110 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16111 * an emptiable particle, then a simple type definition which
16112 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016113 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016114 if ((type->contentTypeDef == NULL) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016115 (type->contentTypeDef->baseType == NULL)) {
16116 /*
16117 * TODO: Check if this ever happens.
16118 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016119 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016120 XML_SCHEMAP_INTERNAL,
16121 NULL, type, NULL,
16122 "Internal error: xmlSchemaTypeFixup, "
16123 "complex type '%s': the <simpleContent><restriction> "
16124 "is missing a <simpleType> child, but was not catched "
16125 "by xmlSchemaCheckSRCCT()", type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016126 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016127 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16128 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16129 /*
16130 * SPEC (3) If <extension> + base is <complexType> with
16131 * <simpleType> content, "...then the {content type} of that
16132 * complex type definition"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016133 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016134 if (baseType->contentTypeDef == NULL) {
16135 /*
16136 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16137 * should have catched this already.
16138 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016139 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016140 XML_SCHEMAP_INTERNAL,
16141 NULL, type, NULL,
16142 "Internal error: xmlSchemaTypeFixup, "
16143 "complex type '%s': the <extension>ed base type is "
16144 "a complex type with no simple content type",
16145 type->name);
16146 }
16147 type->contentTypeDef = baseType->contentTypeDef;
16148 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16149 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16150 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016151 * SPEC (4) <extension> + base is <simpleType>
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016152 * "... then that simple type definition"
16153 */
16154 type->contentTypeDef = baseType;
16155 } else {
16156 /*
16157 * TODO: Check if this ever happens.
16158 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016159 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016160 XML_SCHEMAP_INTERNAL,
16161 NULL, type, NULL,
16162 "Internal error: xmlSchemaTypeFixup, "
16163 "complex type '%s' with <simpleContent>: unhandled "
16164 "derivation case", type->name);
16165 }
16166 } else {
16167 int dummySequence = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016168 xmlSchemaParticlePtr particle =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016169 (xmlSchemaParticlePtr) type->subtypes;
16170 /*
16171 * Corresponds to <complexType><complexContent>...
16172 *
16173 * NOTE that the effective mixed was already set during parsing of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016174 * <complexType> and <complexContent>; its flag value is
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016175 * XML_SCHEMAS_TYPE_MIXED.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016176 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016177 * Compute the "effective content":
16178 * (2.1.1) + (2.1.2) + (2.1.3)
16179 */
16180 if ((particle == NULL) ||
16181 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16182 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16183 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16184 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16185 (particle->minOccurs == 0))) &&
16186 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016187 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016188 /*
16189 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16190 * a particle whose properties are as follows:..."
16191 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016192 * Empty sequence model group with
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016193 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16194 * NOTE that we sill assign it the <complexType> node to
16195 * somehow anchor it in the doc.
16196 */
16197 if ((particle == NULL) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016198 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016199 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016200 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016201 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016202 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016203 type->node, 1, 1);
16204 if (particle == NULL)
16205 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016206 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016207 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016208 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016209 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016210 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016211 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16212 if (particle->children == NULL)
16213 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016214
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016215 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016216 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016217 dummySequence = 1;
16218 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16219 } else {
16220 /*
16221 * SPEC (2.1.5) "otherwise empty"
16222 */
16223 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016224 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016225 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016226 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016227 * SPEC (2.2) "otherwise the particle corresponding to the
16228 * <all>, <choice>, <group> or <sequence> among the
16229 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016230 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016231 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16232 }
16233 /*
16234 * Compute the "content type".
16235 */
16236 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016237 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016238 * SPEC (3.1) "If <restriction>..."
16239 * (3.1.1) + (3.1.2) */
16240 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16241 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16242 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16243 }
16244 } else {
16245 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016246 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016247 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016248 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16249 /*
16250 * SPEC (3.2.1)
16251 */
16252 type->contentType = baseType->contentType;
16253 type->subtypes = baseType->subtypes;
16254 /*
16255 * NOTE that the effective mixed is ignored here.
16256 */
16257 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16258 /*
16259 * SPEC (3.2.2)
16260 */
16261 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16262 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16263 } else {
16264 /*
16265 * SPEC (3.2.3)
16266 */
16267 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16268 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16269 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016270 * "A model group whose {compositor} is sequence and whose
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016271 * {particles} are..."
16272 */
16273 if (! dummySequence) {
16274 xmlSchemaTreeItemPtr effectiveContent =
16275 (xmlSchemaTreeItemPtr) type->subtypes;
16276 /*
16277 * Create the particle.
16278 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016279 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016280 type->node, 1, 1);
16281 if (particle == NULL)
16282 return;
16283 /*
16284 * Create the "sequence" model group.
16285 */
16286 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016287 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016288 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16289 if (particle->children == NULL)
16290 return;
16291 type->subtypes = (xmlSchemaTypePtr) particle;
16292 /*
16293 * SPEC "the particle of the {content type} of
16294 * the ... base ..."
16295 * Create a duplicate of the base type's particle
16296 * and assign its "term" to it.
16297 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016298 particle->children->children =
16299 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
16300 pctxt->schema, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016301 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016302 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016303 if (particle->children->children == NULL)
16304 return;
16305 particle = (xmlSchemaParticlePtr)
16306 particle->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016307 particle->children =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016308 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16309 /*
16310 * SPEC "followed by the ·effective content·."
16311 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016312 particle->next = effectiveContent;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016313 } else {
16314 /*
16315 * This is the case when there is already an empty
16316 * <sequence> with minOccurs==maxOccurs==1.
16317 * Just add the base types's content type.
16318 * NOTE that, although we miss to add an intermediate
16319 * <sequence>, this should produce no difference to
16320 * neither the regex compilation of the content model,
16321 * nor to the complex type contraints.
16322 */
16323 particle->children->children =
16324 (xmlSchemaTreeItemPtr) baseType->subtypes;
16325 }
16326 }
16327 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016328 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016329 /*
16330 * Apply the complex type component constraints; this will not
16331 * check attributes, since this is done in
16332 * xmlSchemaBuildAttributeValidation().
16333 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016334 if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
16335 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016336 /*
16337 * Inherit & check constraints for attributes.
16338 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016339 xmlSchemaBuildAttributeValidation(pctxt, type);
16340 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016341 /*
16342 * Simple Type Definition Schema Component
16343 */
16344 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016345 if (VARIETY_LIST(type)) {
16346 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016347 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016348 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016349 if (type->subtypes == NULL) {
16350 /*
16351 * This one is really needed, so get out.
16352 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016353 PERROR_INT("xmlSchemaTypeFixup",
16354 "list type has no item-type assigned");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016355 return;
16356 }
16357 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016358 xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
16359 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016360 /*
16361 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016362 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016363 if (type->memberTypes == NULL) {
16364 /*
16365 * This one is really needed, so get out.
16366 */
16367 return;
16368 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016369 if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016370 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016371 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016372 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016373 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016374 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016375 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016376 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016377 xmlSchemaTypeFixup(baseType, pctxt, NULL);
16378 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016379 * Variety
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016380 * If the <restriction> alternative is chosen, then the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016381 * {variety} of the {base type definition}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016382 */
16383 if (VARIETY_ATOMIC(baseType))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016384 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016385 else if (VARIETY_LIST(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016386 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16387 /*
16388 * Inherit the itemType.
16389 */
16390 type->subtypes = baseType->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016391 } else if (VARIETY_UNION(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016392 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16393 /*
16394 * NOTE that we won't assign the memberTypes of the base,
16395 * since this will make trouble when freeing them; we will
16396 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016397 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016398 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016399 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016400 /*
16401 * Check constraints.
16402 *
16403 * TODO: Split this somehow, we need to know first if we can derive
16404 * from the base type at all!
16405 */
16406 if (type->baseType != NULL) {
16407 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016408 * Schema Component Constraint: Simple Type Restriction
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016409 * (Facets)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016410 * NOTE: Satisfaction of 1 and 2 arise from the fixup
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016411 * applied beforehand.
16412 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016413 xmlSchemaCheckSRCSimpleType(pctxt, type);
16414 xmlSchemaCheckFacetValues(type, pctxt);
16415 if ((type->facetSet != NULL) ||
16416 (type->baseType->facetSet != NULL))
16417 xmlSchemaDeriveAndValidateFacets(pctxt, type);
16418 /*
16419 * Whitespace value.
16420 */
16421 xmlSchemaTypeFixupWhitespace(type);
16422 xmlSchemaTypeFixupOptimFacets(type);
16423 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016424 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016425
Daniel Veillard8651f532002-04-17 09:06:27 +000016426#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016427 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016428 xmlGenericError(xmlGenericErrorContext,
16429 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016430 type->node->doc->URL,
16431 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016432 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016433 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016434 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016435 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16436 switch (type->contentType) {
16437 case XML_SCHEMA_CONTENT_SIMPLE:
16438 xmlGenericError(xmlGenericErrorContext, "simple\n");
16439 break;
16440 case XML_SCHEMA_CONTENT_ELEMENTS:
16441 xmlGenericError(xmlGenericErrorContext, "elements\n");
16442 break;
16443 case XML_SCHEMA_CONTENT_UNKNOWN:
16444 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16445 break;
16446 case XML_SCHEMA_CONTENT_EMPTY:
16447 xmlGenericError(xmlGenericErrorContext, "empty\n");
16448 break;
16449 case XML_SCHEMA_CONTENT_MIXED:
16450 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016451 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016452 xmlGenericError(xmlGenericErrorContext,
16453 "mixed as emptiable particle\n");
16454 else
16455 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16456 break;
16457 /* Removed, since not used. */
16458 /*
16459 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16460 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16461 break;
16462 */
16463 case XML_SCHEMA_CONTENT_BASIC:
16464 xmlGenericError(xmlGenericErrorContext, "basic\n");
16465 break;
16466 default:
16467 xmlGenericError(xmlGenericErrorContext,
16468 "not registered !!!\n");
16469 break;
16470 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016471 }
16472#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016473}
16474
16475/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016476 * xmlSchemaCheckFacet:
16477 * @facet: the facet
16478 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000016479 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016480 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016481 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016482 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016483 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016484 * Returns 0 if valid, a positive error code if not valid and
16485 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016486 */
16487int
16488xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016489 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016490 xmlSchemaParserCtxtPtr pctxt,
16491 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016492{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016493 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016494
Daniel Veillardce682bc2004-11-05 17:22:25 +000016495 if ((facet == NULL) || (typeDecl == NULL))
16496 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016497 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016498 * TODO: will the parser context be given if used from
16499 * the relaxNG module?
16500 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016501 if (pctxt == NULL)
16502 ctxtGiven = 0;
16503 else
16504 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016505
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016506 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016507 case XML_SCHEMA_FACET_MININCLUSIVE:
16508 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16509 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016510 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16511 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016512 /*
16513 * Okay we need to validate the value
16514 * at that point.
16515 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016516 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016517
16518 /* 4.3.5.5 Constraints on enumeration Schema Components
16519 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016520 * It is an ·error· if any member of {value} is not in the
16521 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016522 *
16523 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016524 * The value ·must· be in the
16525 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016526 */
16527 /*
16528 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016529 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016530 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016531 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016532 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016533 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016534 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016535 */
16536 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16537 base = typeDecl->baseType;
16538 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016539 PERROR_INT("xmlSchemaCheckFacet",
16540 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016541 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016542 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016543 } else
16544 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016545
16546 if (! ctxtGiven) {
16547 /*
16548 * A context is needed if called from RelaxNG.
16549 */
16550 pctxt = xmlSchemaNewParserCtxt("*");
16551 if (pctxt == NULL)
16552 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016553 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016554 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016555 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016556 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016557 * facet->node is just the node holding the facet
16558 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016559 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016560 */
16561 ret = xmlSchemaVCheckCVCSimpleType(
16562 (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
16563 facet->value, &(facet->val), 1, 1, 0);
16564 if (ret != 0) {
16565 if (ret < 0) {
16566 /* No error message for RelaxNG. */
16567 if (ctxtGiven) {
16568 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16569 XML_SCHEMAP_INTERNAL, facet->node, NULL,
16570 "Internal error: xmlSchemaCheckFacet, "
16571 "failed to validate the value '%s' of the "
16572 "facet '%s' against the base type",
16573 facet->value, xmlSchemaFacetTypeToString(facet->type));
16574 }
16575 goto internal_error;
16576 }
16577 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16578 /* No error message for RelaxNG. */
16579 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016580 xmlChar *str = NULL;
16581
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016582 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16583 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016584 "The value '%s' of the facet does not validate "
16585 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016586 facet->value,
16587 xmlSchemaFormatQName(&str,
16588 base->targetNamespace, base->name));
16589 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016590 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016591 goto exit;
16592 } else if (facet->val == NULL) {
16593 if (ctxtGiven) {
16594 PERROR_INT("xmlSchemaCheckFacet",
16595 "value was not computed");
16596 }
16597 TODO
16598 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016599 break;
16600 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016601 case XML_SCHEMA_FACET_PATTERN:
16602 facet->regexp = xmlRegexpCompile(facet->value);
16603 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016604 ret = XML_SCHEMAP_REGEXP_INVALID;
16605 /* No error message for RelaxNG. */
16606 if (ctxtGiven) {
16607 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16608 ret, facet->node, typeDecl,
16609 "The value '%s' of the facet 'pattern' is not a "
16610 "valid regular expression",
16611 facet->value, NULL);
16612 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016613 }
16614 break;
16615 case XML_SCHEMA_FACET_TOTALDIGITS:
16616 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16617 case XML_SCHEMA_FACET_LENGTH:
16618 case XML_SCHEMA_FACET_MAXLENGTH:
16619 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016620 ret = xmlSchemaValidatePredefinedType(
16621 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
16622 facet->value, &(facet->val));
16623 if (ret != 0) {
16624 if (ret < 0) {
16625 /* No error message for RelaxNG. */
16626 if (ctxtGiven) {
16627 PERROR_INT("xmlSchemaCheckFacet",
16628 "validating facet value");
16629 }
16630 goto internal_error;
16631 }
16632 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16633 /* No error message for RelaxNG. */
16634 if (ctxtGiven) {
16635 /* error code */
16636 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16637 ret, facet->node, typeDecl,
16638 "The value '%s' of the facet '%s' is not a valid "
16639 "'nonNegativeInteger'",
16640 facet->value,
16641 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016642 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016643 }
16644 break;
16645 }
16646 case XML_SCHEMA_FACET_WHITESPACE:{
16647 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16648 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16649 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16650 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16651 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16652 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16653 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016654 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16655 /* No error message for RelaxNG. */
16656 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016657 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016658 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16659 ret, facet->node, typeDecl,
16660 "The value '%s' of the facet 'whitespace' is not "
16661 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016662 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016663 }
16664 }
16665 default:
16666 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016667 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016668exit:
16669 if ((! ctxtGiven) && (pctxt != NULL))
16670 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016671 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016672internal_error:
16673 if ((! ctxtGiven) && (pctxt != NULL))
16674 xmlSchemaFreeParserCtxt(pctxt);
16675 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016676}
16677
16678/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016679 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016680 * @typeDecl: the schema type definition
16681 * @ctxt: the schema parser context
16682 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016683 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000016684 */
16685static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016686xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16687 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016688{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016689 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016690 /*
16691 * NOTE: It is intended to use the facets list, instead
16692 * of facetSet.
16693 */
16694 if (typeDecl->facets != NULL) {
16695 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016696
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016697 /*
16698 * Temporarily assign the "schema" to the validation context
16699 * of the parser context. This is needed for NOTATION validation.
16700 */
16701 if (ctxt->vctxt == NULL) {
16702 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16703 return;
16704 }
16705 ctxt->vctxt->schema = ctxt->schema;
16706
Daniel Veillard01fa6152004-06-29 17:04:39 +000016707 while (facet != NULL) {
16708 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16709 facet = facet->next;
16710 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016711
16712 ctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016713 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016714}
16715
16716/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016717 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016718 * @ctxtMGroup: the searched model group
16719 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016720 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016721 *
16722 * This one is intended to be used by
16723 * xmlSchemaCheckGroupDefCircular only.
16724 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016725 * Returns the particle with the circular model group definition reference,
16726 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016727 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016728static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016729xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016730 xmlSchemaTreeItemPtr particle)
16731{
16732 xmlSchemaTreeItemPtr circ = NULL;
16733 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016734 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016735
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016736 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016737 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016738 if (term == NULL)
16739 continue;
16740 switch (term->type) {
16741 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016742 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016743 if (gdef == groupDef)
16744 return (particle);
16745 /*
16746 * Mark this model group definition to avoid infinite
16747 * recursion on circular references not yet examined.
16748 */
16749 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16750 continue;
16751 if (gdef->children != NULL) {
16752 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16753 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16754 gdef->children->children);
16755 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16756 if (circ != NULL)
16757 return (circ);
16758 }
16759 break;
16760 case XML_SCHEMA_TYPE_SEQUENCE:
16761 case XML_SCHEMA_TYPE_CHOICE:
16762 case XML_SCHEMA_TYPE_ALL:
16763 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16764 if (circ != NULL)
16765 return (circ);
16766 break;
16767 default:
16768 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016769 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016770 }
16771 return (NULL);
16772}
16773
16774/**
16775 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016776 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016777 * @ctxt: the parser context
16778 * @name: the name
16779 *
16780 * Checks for circular references to model group definitions.
16781 */
16782static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016783xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016784 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016785 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016786{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016787 /*
16788 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016789 * 2 Circular groups are disallowed. That is, within the {particles}
16790 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016791 * is the group itself.
16792 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016793 if ((item == NULL) ||
16794 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16795 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016796 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016797 {
16798 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016799
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016800 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016801 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016802 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016803 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016804 * TODO: The error report is not adequate: this constraint
16805 * is defined for model groups but not definitions, but since
16806 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016807 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016808 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016809 */
16810 xmlSchemaPCustomErr(ctxt,
16811 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016812 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016813 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016814 "defined", xmlSchemaFormatQName(&str,
16815 item->targetNamespace, item->name));
16816 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016817 /*
16818 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016819 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016820 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016821 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016822 }
16823 }
16824}
16825
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016826/**
16827 * xmlSchemaGroupDefTermFixup:
16828 * @item: the particle with a model group definition as term
16829 * @ctxt: the parser context
16830 * @name: the name
16831 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016832 * Checks cos-all-limited.
16833 *
16834 * Assigns the model group of model group definitions to the "term"
16835 * of the referencing particle.
16836 * In xmlSchemaMiscRefFixup the model group definitions was assigned
16837 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016838 */
16839static void
16840xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016841 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016842 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016843{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016844 if ((item == NULL) ||
16845 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16846 (item->children == NULL) ||
16847 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16848 (item->children->children == NULL))
16849 return;
16850 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016851 /*
16852 * TODO: Not nice, but we will anchor cos-all-limited here.
16853 */
16854 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
16855 (item->maxOccurs != 1)) {
16856 /*
16857 * SPEC (1.2) "the {term} property of a particle with
16858 * {max occurs}=1which is part of a pair which constitutes the
16859 * {content type} of a complex type definition."
16860 */
16861 xmlSchemaPCustomErr(ctxt,
16862 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16863 NULL, (xmlSchemaTypePtr) item, item->node,
16864 "The particle's 'maxOccurs' must be 1, since an xs:all model "
16865 "group is its term", NULL);
16866 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016867}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016868
16869/**
16870 * xmlSchemaGetCircAttrGrRef:
16871 * @ctxtGr: the searched attribute group
16872 * @attr: the current attribute list to be processed
16873 *
16874 * This one is intended to be used by
16875 * xmlSchemaCheckSRCAttributeGroupCircular only.
16876 *
16877 * Returns the circular attribute grou reference, otherwise NULL.
16878 */
16879static xmlSchemaAttributeGroupPtr
16880xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16881 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016882{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016883 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16884 int marked;
16885 /*
16886 * We will search for an attribute group reference which
16887 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016888 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016889 while (attr != NULL) {
16890 marked = 0;
16891 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16892 gr = (xmlSchemaAttributeGroupPtr) attr;
16893 if (gr->refItem != NULL) {
16894 if (gr->refItem == ctxtGr)
16895 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016896 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016897 XML_SCHEMAS_ATTRGROUP_MARKED) {
16898 attr = attr->next;
16899 continue;
16900 } else {
16901 /*
16902 * Mark as visited to avoid infinite recursion on
16903 * circular references not yet examined.
16904 */
16905 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16906 marked = 1;
16907 }
16908 }
16909 if (gr->attributes != NULL)
16910 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16911 /*
16912 * Unmark the visited group's attributes.
16913 */
16914 if (marked)
16915 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16916 if (circ != NULL)
16917 return (circ);
16918 }
16919 attr = attr->next;
16920 }
16921 return (NULL);
16922}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016923
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016924/**
16925 * xmlSchemaCheckSRCAttributeGroupCircular:
16926 * attrGr: the attribute group definition
16927 * @ctxt: the parser context
16928 * @name: the name
16929 *
16930 * Checks for circular references of attribute groups.
16931 */
16932static void
16933xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016934 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016935 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016936{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016937 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016938 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016939 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016940 * 3 Circular group reference is disallowed outside <redefine>.
16941 * That is, unless this element information item's parent is
16942 * <redefine>, then among the [children], if any, there must
16943 * not be an <attributeGroup> with ref [attribute] which resolves
16944 * to the component corresponding to this <attributeGroup>. Indirect
16945 * circularity is also ruled out. That is, when QName resolution
16946 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16947 * any <attributeGroup>s with a ref [attribute] among the [children],
16948 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016949 * which resolves to the component corresponding to this <attributeGroup>.
16950 */
16951 /*
16952 * Only global components can be referenced.
16953 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016954 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016955 (attrGr->attributes == NULL))
16956 return;
16957 else {
16958 xmlSchemaAttributeGroupPtr circ;
16959
16960 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16961 if (circ != NULL) {
16962 /*
16963 * TODO: Report the referenced attr group as QName.
16964 */
16965 xmlSchemaPCustomErr(ctxt,
16966 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16967 NULL, NULL, circ->node,
16968 "Circular reference to the attribute group '%s' "
16969 "defined", attrGr->name);
16970 /*
16971 * NOTE: We will cut the reference to avoid further
16972 * confusion of the processor.
16973 * BADSPEC: The spec should define how to process in this case.
16974 */
16975 circ->attributes = NULL;
16976 circ->refItem = NULL;
16977 }
16978 }
16979}
16980
16981/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000016982 * xmlSchemaAttrGrpFixup:
16983 * @attrgrpDecl: the schema attribute definition
16984 * @ctxt: the schema parser context
16985 * @name: the attribute name
16986 *
16987 * Fixes finish doing the computations on the attributes definitions
16988 */
16989static void
Daniel Veillard3646d642004-06-02 19:19:14 +000016990xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016991 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000016992{
16993 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016994 name = attrgrp->name;
16995 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016996 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000016997 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016998 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000016999
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017000 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017001 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017002 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017003 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017004 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017005 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
17006 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017007 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017008 return;
17009 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017010 attrgrp->refItem = ref;
17011 /*
17012 * Check for self reference!
17013 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017014 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000017015 attrgrp->attributes = ref->attributes;
17016 attrgrp->attributeWildcard = ref->attributeWildcard;
17017 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000017018}
17019
17020/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017021 * xmlSchemaAttrCheckValConstr:
17022 * @item: an schema attribute declaration/use
17023 * @ctxt: a schema parser context
17024 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017025 *
17026 *
17027 * Schema Component Constraint: Attribute Declaration Properties Correct
17028 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017029 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000017030 *
17031 * Fixes finish doing the computations on the attributes definitions
17032 */
17033static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017034xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017035 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017036 const xmlChar * name ATTRIBUTE_UNUSED)
17037{
17038
17039 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017040 * 2 if there is a {value constraint}, the canonical lexical
17041 * representation of its value must be ·valid· with respect
17042 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017043 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017044 if (item->defValue != NULL) {
17045 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017046
17047 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017048 PERROR_INT("xmlSchemaCheckAttrValConstr",
17049 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017050 return;
17051 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017052 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
17053 item->node, item->subtypes, item->defValue, &(item->defVal),
17054 1, 1, 0);
17055 if (ret != 0) {
17056 if (ret < 0) {
17057 PERROR_INT("xmlSchemaAttrCheckValConstr",
17058 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017059 return;
17060 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017061 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
17062 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17063 ret, item->node, (xmlSchemaTypePtr) item,
17064 "The value of the value constraint is not valid", NULL, NULL);
17065 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017066 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017067 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017068}
17069
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017070static xmlSchemaElementPtr
17071xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17072 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017073{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017074 xmlSchemaElementPtr ret;
17075
17076 if (SUBST_GROUP_AFF(ancestor) == NULL)
17077 return (NULL);
17078 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17079 return (ancestor);
17080
17081 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17082 return (NULL);
17083 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17084 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17085 SUBST_GROUP_AFF(ancestor));
17086 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17087
17088 return (ret);
17089}
17090
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017091/**
17092 * xmlSchemaCheckElemPropsCorrect:
17093 * @ctxt: a schema parser context
17094 * @decl: the element declaration
17095 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017096 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017097 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017098 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017099 *
17100 * STATUS:
17101 * missing: (6)
17102 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017103static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017104xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17105 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017106{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017107 int ret = 0;
17108 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017109 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017110 * SPEC (1) "The values of the properties of an element declaration
17111 * must be as described in the property tableau in The Element
17112 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17113 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017114 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017115 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017116 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017117
17118 xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017119 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017120 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017121 * affiliation}, then {scope} must be global."
17122 */
17123 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17124 xmlSchemaPCustomErr(pctxt,
17125 XML_SCHEMAP_E_PROPS_CORRECT_3,
17126 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17127 "Only global element declarations can have a "
17128 "substitution group affiliation", NULL);
17129 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017130 }
17131 /*
17132 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17133 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017134 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017135 * property."
17136 */
17137 if (head == elemDecl)
17138 circ = head;
17139 else if (SUBST_GROUP_AFF(head) != NULL)
17140 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17141 else
17142 circ = NULL;
17143 if (circ != NULL) {
17144 xmlChar *strA = NULL, *strB = NULL;
17145
17146 xmlSchemaPCustomErrExt(pctxt,
17147 XML_SCHEMAP_E_PROPS_CORRECT_6,
17148 NULL, (xmlSchemaTypePtr) circ, circ->node,
17149 "The element declaration '%s' defines a circular "
17150 "substitution group to element declaration '%s'",
17151 xmlSchemaGetComponentQName(&strA, circ),
17152 xmlSchemaGetComponentQName(&strB, head),
17153 NULL);
17154 FREE_AND_NULL(strA)
17155 FREE_AND_NULL(strB)
17156 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17157 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017158 /*
17159 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017160 * the {type definition}
17161 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017162 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017163 * of the {substitution group exclusions} of the {substitution group
17164 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17165 * (if the {type definition} is complex) or as defined in
17166 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017167 * simple)."
17168 *
17169 * NOTE: {substitution group exclusions} means the values of the
17170 * attribute "final".
17171 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017172
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017173 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017174 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017175
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017176 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
17177 set |= SUBSET_EXTENSION;
17178 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
17179 set |= SUBSET_RESTRICTION;
17180
17181 if (xmlSchemaCheckCOSDerivedOK(typeDef,
17182 ELEM_TYPE(head), set) != 0) {
17183 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
17184
17185 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017186 xmlSchemaPCustomErrExt(pctxt,
17187 XML_SCHEMAP_E_PROPS_CORRECT_4,
17188 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017189 "The type definition '%s' was "
17190 "either rejected by the substitution group "
17191 "affiliation '%s', or not validly derived from its type "
17192 "definition '%s'",
17193 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017194 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017195 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017196 FREE_AND_NULL(strA)
17197 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017198 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017199 }
17200 }
17201 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017202 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017203 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017204 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017205 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017206 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017207 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017208 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017209 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017210 ((IS_SIMPLE_TYPE(typeDef) &&
17211 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017212 (IS_COMPLEX_TYPE(typeDef) &&
17213 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017214 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
17215 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017216
17217 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17218 xmlSchemaPCustomErr(pctxt,
17219 XML_SCHEMAP_E_PROPS_CORRECT_5,
17220 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17221 "The type definition (or type definition's content type) is or "
17222 "is derived from ID; value constraints are not allowed in "
17223 "conjunction with such a type definition", NULL);
17224 } else if (elemDecl->value != NULL) {
17225 int vcret;
17226 xmlNodePtr node = NULL;
17227
17228 /*
17229 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17230 * representation of its value must be ·valid· with respect to the
17231 * {type definition} as defined in Element Default Valid (Immediate)
17232 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017233 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017234 if (typeDef == NULL) {
17235 xmlSchemaPErr(pctxt, elemDecl->node,
17236 XML_SCHEMAP_INTERNAL,
17237 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17238 "type is missing... skipping validation of "
17239 "the value constraint", NULL, NULL);
17240 return (-1);
17241 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017242 if (elemDecl->node != NULL) {
17243 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17244 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17245 BAD_CAST "fixed");
17246 else
17247 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17248 BAD_CAST "default");
17249 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017250 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
17251 typeDef, elemDecl->value, &(elemDecl->defVal));
17252 if (vcret != 0) {
17253 if (vcret < 0) {
17254 PERROR_INT("xmlSchemaElemCheckValConstr",
17255 "failed to validate the value constraint of an "
17256 "element declaration");
17257 return (-1);
17258 }
17259 return (vcret);
17260 }
17261 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017262
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017263 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017264}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017265
17266/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017267 * xmlSchemaCheckElemSubstGroup:
17268 * @ctxt: a schema parser context
17269 * @decl: the element declaration
17270 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017271 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017272 * Schema Component Constraint:
17273 * Substitution Group (cos-equiv-class)
17274 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017275 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017276 * a list will be built for each subst. group head, holding all direct
17277 * referents to this head.
17278 * NOTE that this function needs:
17279 * 1. circular subst. groups to be checked beforehand
17280 * 2. the declaration's type to be derived from the head's type
17281 *
17282 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017283 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017284 */
17285static void
17286xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17287 xmlSchemaElementPtr elemDecl)
17288{
17289 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17290 /* SPEC (1) "Its {abstract} is false." */
17291 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17292 return;
17293 {
17294 xmlSchemaElementPtr head;
17295 xmlSchemaTypePtr headType, type;
17296 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017297 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017298 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17299 * {disallowed substitutions} as the blocking constraint, as defined in
17300 * Substitution Group OK (Transitive) (§3.3.6)."
17301 */
17302 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17303 head = SUBST_GROUP_AFF(head)) {
17304 set = 0;
17305 methSet = 0;
17306 /*
17307 * The blocking constraints.
17308 */
17309 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17310 continue;
17311 headType = head->subtypes;
17312 type = elemDecl->subtypes;
17313 if (headType == type)
17314 goto add_member;
17315 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17316 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17317 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17318 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17319 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017320 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017321 * "The set of all {derivation method}s involved in the
17322 * derivation of D's {type definition} from C's {type definition}
17323 * does not intersect with the union of the blocking constraint,
17324 * C's {prohibited substitutions} (if C is complex, otherwise the
17325 * empty set) and the {prohibited substitutions} (respectively the
17326 * empty set) of any intermediate {type definition}s in the
17327 * derivation of D's {type definition} from C's {type definition}."
17328 */
17329 /*
17330 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17331 * subst.head axis, the methSet does not need to be computed for
17332 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017333 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017334 /*
17335 * The set of all {derivation method}s involved in the derivation
17336 */
17337 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017338 if ((type->flags &
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017339 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17340 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17341 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017342
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017343 if ((type->flags &
17344 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17345 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17346 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17347
17348 type = type->baseType;
17349 }
17350 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017351 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017352 * the head's type.
17353 */
17354 type = elemDecl->subtypes->baseType;
17355 while (type != NULL) {
17356 if (IS_COMPLEX_TYPE(type)) {
17357 if ((type->flags &
17358 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17359 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17360 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17361 if ((type->flags &
17362 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17363 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17364 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17365 } else
17366 break;
17367 if (type == headType)
17368 break;
17369 type = type->baseType;
17370 }
17371 if ((set != 0) &&
17372 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17373 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17374 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17375 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17376 continue;
17377 }
17378add_member:
17379 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17380 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17381 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17382 }
17383 }
17384}
17385
17386/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017387 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017388 * @item: an schema element declaration/particle
17389 * @ctxt: a schema parser context
17390 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017391 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017392 * Validates the value constraints of an element declaration.
17393 *
17394 * Fixes finish doing the computations on the element declarations.
17395 */
17396static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017397xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017398 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017399 const xmlChar * name ATTRIBUTE_UNUSED)
17400{
17401 if (elemDecl == NULL)
17402 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017403 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
17404 return;
17405 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017406 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17407 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017408}
17409
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017410/**
17411 * xmlSchemaMiscRefFixup:
17412 * @item: an schema component
17413 * @ctxt: a schema parser context
17414 * @name: the internal name of the component
17415 *
17416 * Resolves references of misc. schema components.
17417 */
17418static void
17419xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017420 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017421 const xmlChar * name ATTRIBUTE_UNUSED)
17422{
17423 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017424 if ((item->children != NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017425 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17426 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17427 xmlSchemaTreeItemPtr refItem;
17428 /*
17429 * Resolve the reference.
17430 */
17431 item->children = NULL;
17432 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17433 ref->itemType, ref->name, ref->targetNamespace);
17434 if (refItem == NULL) {
17435 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017436 NULL, GET_NODE(item), "ref", ref->name,
17437 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017438 } else {
17439 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17440 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017441 * NOTE that we will assign the model group definition
17442 * itself to the "term" of the particle. This will ease
17443 * the check for circular model group definitions. After
17444 * that the "term" will be assigned the model group of the
17445 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017446 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017447 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017448 } else
17449 item->children = refItem;
17450 }
17451 }
17452 }
17453}
17454
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017455static int
17456xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
17457 xmlSchemaValPtr y)
17458{
17459 xmlSchemaTypePtr tx, ty, ptx, pty;
17460 int ret;
17461
17462 while (x != NULL) {
17463 /* Same types. */
17464 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
17465 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
17466 ptx = xmlSchemaGetPrimitiveType(tx);
17467 pty = xmlSchemaGetPrimitiveType(ty);
17468 /*
17469 * (1) if a datatype T' is ·derived· by ·restriction· from an
17470 * atomic datatype T then the ·value space· of T' is a subset of
17471 * the ·value space· of T. */
17472 /*
17473 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
17474 * from a common atomic ancestor T then the ·value space·s of T'
17475 * and T'' may overlap.
17476 */
17477 if (ptx != pty)
17478 return(0);
17479 /*
17480 * We assume computed values to be normalized, so do a fast
17481 * string comparison for string based types.
17482 */
17483 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
17484 IS_ANY_SIMPLE_TYPE(ptx)) {
17485 if (! xmlStrEqual(
17486 xmlSchemaValueGetAsString(x),
17487 xmlSchemaValueGetAsString(y)))
17488 return (0);
17489 } else {
17490 ret = xmlSchemaCompareValuesWhtsp(
17491 x, XML_SCHEMA_WHITESPACE_PRESERVE,
17492 y, XML_SCHEMA_WHITESPACE_PRESERVE);
17493 if (ret == -2)
17494 return(-1);
17495 if (ret != 0)
17496 return(0);
17497 }
17498 /*
17499 * Lists.
17500 */
17501 x = xmlSchemaValueGetNext(x);
17502 if (x != NULL) {
17503 y = xmlSchemaValueGetNext(y);
17504 if (y == NULL)
17505 return (0);
17506 } else if (xmlSchemaValueGetNext(y) != NULL)
17507 return (0);
17508 else
17509 return (1);
17510 }
17511 return (0);
17512}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017513
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017514/**
17515 * xmlSchemaAttrFixup:
17516 * @item: an schema attribute declaration/use.
17517 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017518 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017519 *
17520 * Fixes finish doing the computations on attribute declarations/uses.
17521 */
17522static void
17523xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017524 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017525 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017526{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017527 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017528 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017529 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017530 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017531 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017532 * The simple type definition corresponding to the <simpleType> element
17533 * information item in the [children], if present, otherwise the simple
17534 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000017535 * [attribute], if present, otherwise the ·simple ur-type definition·.
17536 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017537 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017538 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017539 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17540 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017541 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017542 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017543 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017544
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017545 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17546 item->typeNs);
17547 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017548 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017549 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017550 (xmlSchemaTypePtr) item, item->node,
17551 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017552 XML_SCHEMA_TYPE_SIMPLE, NULL);
17553 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017554 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017555
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017556 } else if (item->ref != NULL) {
17557 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017558
Daniel Veillardc0826a72004-08-10 14:17:33 +000017559 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017560 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017561 * attribute declaration.
17562 */
17563 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017564 * TODO: Evaluate, what errors could occur if the declaration is not
17565 * found. It might be possible that the "typefixup" might crash if
17566 * no ref declaration was found.
17567 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017568 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017569 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017570 xmlSchemaPResCompAttrErr(ctxt,
17571 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017572 (xmlSchemaTypePtr) item, item->node,
17573 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017574 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017575 return;
17576 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017577 item->refDecl = decl;
17578 xmlSchemaAttrFixup(decl, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017579 item->subtypes = decl->subtypes;
17580 /*
17581 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017582 * au-props-correct.2: If the {attribute declaration} has a fixed
17583 * {value constraint}, then if the attribute use itself has a
17584 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017585 * that of the {attribute declaration}'s {value constraint}.
17586 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017587 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017588 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017589 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017590 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017591 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17592 NULL, NULL, item->node,
17593 "The attribute declaration has a 'fixed' value constraint "
17594 ", thus it must be 'fixed' in attribute use as well",
17595 NULL);
17596 } else {
17597 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
17598 xmlSchemaPCustomErr(ctxt,
17599 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17600 NULL, NULL, item->node,
17601 "The 'fixed' value constraint of the attribute use "
17602 "must match the attribute declaration's value "
17603 "constraint '%s'",
17604 decl->defValue);
17605 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017606 }
17607 /*
17608 * FUTURE: One should change the values of the attr. use
17609 * if ever validation should be attempted even if the
17610 * schema itself was not fully valid.
17611 */
17612 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017613 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017614 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17615 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017616}
17617
17618/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017619 * xmlSchemaResolveIDCKeyRef:
17620 * @idc: the identity-constraint definition
17621 * @ctxt: the schema parser context
17622 * @name: the attribute name
17623 *
17624 * Resolve keyRef references to key/unique IDCs.
17625 */
17626static void
17627xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017628 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017629 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017630{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017631 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17632 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017633 if (idc->ref->name != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017634 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017635 pctxt->schema->idcDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017636 idc->ref->name,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017637 idc->ref->targetNamespace);
17638 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017639 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017640 * TODO: It is actually not an error to fail to resolve.
17641 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017642 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017643 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017644 (xmlSchemaTypePtr) idc, idc->node,
17645 "refer", idc->ref->name,
17646 idc->ref->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017647 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17648 return;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017649 } else {
17650 if (idc->nbFields !=
17651 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
17652 xmlChar *str = NULL;
17653 xmlSchemaIDCPtr refer;
17654
17655 refer = (xmlSchemaIDCPtr) idc->ref->item;
17656 /*
17657 * SPEC c-props-correct(2)
17658 * "If the {identity-constraint category} is keyref,
17659 * the cardinality of the {fields} must equal that of
17660 * the {fields} of the {referenced key}.
17661 */
17662 xmlSchemaPCustomErr(pctxt,
17663 XML_SCHEMAP_C_PROPS_CORRECT,
17664 NULL, (xmlSchemaTypePtr) idc, idc->node,
17665 "The cardinality of the keyref differs from the "
17666 "cardinality of the referenced key '%s'",
17667 xmlSchemaFormatQName(&str, refer->targetNamespace,
17668 refer->name)
17669 );
17670 FREE_AND_NULL(str)
17671 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017672 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017673 }
17674}
17675
17676/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017677 * xmlSchemaParse:
17678 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017679 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017680 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017681 * XML Shema struture which can be used to validate instances.
17682 * *WARNING* this interface is highly subject to change
17683 *
17684 * Returns the internal XML Schema structure built from the resource or
17685 * NULL in case of error
17686 */
17687xmlSchemaPtr
17688xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17689{
17690 xmlSchemaPtr ret = NULL;
17691 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017692 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017693 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017694
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017695 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017696 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017697 * the API; i.e. not automatically by the validated instance document.
17698 */
17699
Daniel Veillard4255d502002-04-16 15:50:10 +000017700 xmlSchemaInitTypes();
17701
Daniel Veillard6045c902002-10-09 21:13:59 +000017702 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017703 return (NULL);
17704
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017705 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017706 ctxt->counter = 0;
17707 ctxt->container = NULL;
17708
17709 /*
17710 * First step is to parse the input document into an DOM/Infoset
17711 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017712 if (ctxt->URL != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017713 doc = xmlReadFile((const char *) ctxt->URL, NULL,
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017714 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017715 if (doc == NULL) {
17716 xmlSchemaPErr(ctxt, NULL,
17717 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017718 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017719 ctxt->URL, NULL);
17720 return (NULL);
17721 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017722 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017723 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17724 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017725 if (doc == NULL) {
17726 xmlSchemaPErr(ctxt, NULL,
17727 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017728 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017729 NULL, NULL);
17730 return (NULL);
17731 }
17732 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017733 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017734 } else if (ctxt->doc != NULL) {
17735 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017736 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017737 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017738 xmlSchemaPErr(ctxt, NULL,
17739 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017740 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017741 NULL, NULL);
17742 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017743 }
17744
17745 /*
17746 * Then extract the root and Schema parse it
17747 */
17748 root = xmlDocGetRootElement(doc);
17749 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017750 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17751 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017752 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017753 if (!preserve) {
17754 xmlFreeDoc(doc);
17755 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017756 return (NULL);
17757 }
17758
17759 /*
17760 * Remove all the blank text nodes
17761 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017762 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017763
17764 /*
17765 * Then do the parsing for good
17766 */
17767 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017768 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017769 if (!preserve) {
17770 xmlFreeDoc(doc);
17771 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017772 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017773 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017774 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017775 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017776 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017777 ctxt->ctxtType = NULL;
17778 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017779
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017780 /*
17781 * Resolve base types of simple/complex types.
17782 */
17783 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017784
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017785 if (ctxt->nberrors != 0)
17786 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017787
17788 if (ret->volatiles != NULL) {
17789 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17790 int i;
17791 xmlSchemaTreeItemPtr item;
17792
17793 for (i = 0; i < list->nbItems; i++) {
17794 item = (xmlSchemaTreeItemPtr) list->items[i];
17795 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17796 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017797 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017798 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017799 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017800 * Then fixup all attributes declarations
17801 */
17802 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017803 /*
17804 * Then fixup all attributes group declarations
17805 */
17806 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17807 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017808 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017809 * Resolve identity-constraint keyRefs.
17810 */
17811 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017812 /*
17813 * Check type defnitions for circular references.
17814 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017815 xmlHashScan(ret->typeDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017816 xmlSchemaCheckTypeDefCircular, ctxt);
17817 /*
17818 * Check model groups defnitions for circular references.
17819 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017820 xmlHashScan(ret->groupDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017821 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017822 /*
17823 * Set the "term" of particles pointing to model group definitions
17824 * to the contained model group.
17825 */
17826 if (ret->volatiles != NULL) {
17827 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17828 int i;
17829 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017830
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017831 for (i = 0; i < list->nbItems; i++) {
17832 item = (xmlSchemaParticlePtr) list->items[i];
17833 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17834 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17835 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017836 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017837 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017838 * Check attribute groups for circular references.
17839 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017840 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
17841 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017842 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017843 * Then fix references of element declaration; apply constraints.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017844 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017845 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017846 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017847 /*
17848 * We will stop here if the schema was not valid to avoid internal errors
17849 * on missing sub-components. This is not conforming to the spec, since it
17850 * allows missing components, but it might make further processing crash.
17851 * So see it as a very strict handling, which might be made more lax in the
17852 * future.
17853 */
17854 if (ctxt->nberrors != 0)
17855 goto exit;
17856 /*
17857 * Then fixup all types properties
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017858 */
17859 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017860 /*
17861 * Validate the value constraint of attribute declarations/uses.
17862 */
17863 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017864 /*
17865 * Validate the value constraint of element declarations.
17866 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017867 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017868
17869 if (ctxt->nberrors != 0)
17870 goto exit;
17871
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017872 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017873 * TODO: cos-element-consistent, cos-all-limited
17874 *
17875 * Then build the content model for all complex types
17876 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017877 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017878 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017879
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017880exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017881 if (ctxt->nberrors != 0) {
17882 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017883 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017884 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017885 return (ret);
17886}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017887
Daniel Veillard4255d502002-04-16 15:50:10 +000017888/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017889 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017890 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017891 * @err: the error callback
17892 * @warn: the warning callback
17893 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017894 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017895 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017896 */
17897void
17898xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017899 xmlSchemaValidityErrorFunc err,
17900 xmlSchemaValidityWarningFunc warn, void *ctx)
17901{
Daniel Veillard4255d502002-04-16 15:50:10 +000017902 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017903 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017904 ctxt->error = err;
17905 ctxt->warning = warn;
17906 ctxt->userData = ctx;
17907}
17908
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017909/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017910 * xmlSchemaGetParserErrors:
17911 * @ctxt: a XMl-Schema parser context
17912 * @err: the error callback result
17913 * @warn: the warning callback result
17914 * @ctx: contextual data for the callbacks result
17915 *
17916 * Get the callback information used to handle errors for a parser context
17917 *
17918 * Returns -1 in case of failure, 0 otherwise
17919 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017920int
Daniel Veillard259f0df2004-08-18 09:13:18 +000017921xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17922 xmlSchemaValidityErrorFunc * err,
17923 xmlSchemaValidityWarningFunc * warn, void **ctx)
17924{
17925 if (ctxt == NULL)
17926 return(-1);
17927 if (err != NULL)
17928 *err = ctxt->error;
17929 if (warn != NULL)
17930 *warn = ctxt->warning;
17931 if (ctx != NULL)
17932 *ctx = ctxt->userData;
17933 return(0);
17934}
17935
17936/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017937 * xmlSchemaFacetTypeToString:
17938 * @type: the facet type
17939 *
17940 * Convert the xmlSchemaTypeType to a char string.
17941 *
17942 * Returns the char string representation of the facet type if the
17943 * type is a facet and an "Internal Error" string otherwise.
17944 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017945static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017946xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17947{
17948 switch (type) {
17949 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017950 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017951 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017952 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017953 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017954 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017955 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017956 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017957 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017958 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017959 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017960 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017961 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017962 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017963 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017964 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017965 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017966 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017967 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017968 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017969 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017970 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017971 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017972 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017973 default:
17974 break;
17975 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017976 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017977}
17978
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017979static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000017980xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
17981{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017982 /*
17983 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000017984 * from xsd:string.
17985 */
17986 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017987 /*
17988 * Note that we assume a whitespace of preserve for anySimpleType.
17989 */
17990 if ((type->builtInType == XML_SCHEMAS_STRING) ||
17991 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
17992 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017993 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017994 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017995 else {
17996 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017997 * For all ·atomic· datatypes other than string (and types ·derived·
17998 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000017999 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018000 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018001 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018002 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018003 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018004 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018005 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018006 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018007 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018008 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
18009 } else if (VARIETY_UNION(type)) {
18010 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
18011 } else if (VARIETY_ATOMIC(type)) {
18012 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
18013 return (XML_SCHEMA_WHITESPACE_PRESERVE);
18014 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
18015 return (XML_SCHEMA_WHITESPACE_REPLACE);
18016 else
18017 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018018 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018019 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018020}
18021
Daniel Veillard4255d502002-04-16 15:50:10 +000018022/************************************************************************
18023 * *
18024 * Simple type validation *
18025 * *
18026 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000018027
Daniel Veillard4255d502002-04-16 15:50:10 +000018028
18029/************************************************************************
18030 * *
18031 * DOM Validation code *
18032 * *
18033 ************************************************************************/
18034
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018035static void
18036xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
18037{
18038 int i, nbItems;
18039 xmlSchemaTypePtr item, *items;
18040
18041
18042 /*
18043 * During the Assemble of the schema ctxt->curItems has
18044 * been filled with the relevant new items. Fix those up.
18045 */
18046 nbItems = ctxt->assemble->nbItems;
18047 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018048
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018049 for (i = 0; i < nbItems; i++) {
18050 item = items[i];
18051 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018052 case XML_SCHEMA_TYPE_COMPLEX:
18053 case XML_SCHEMA_TYPE_SIMPLE:
18054 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
18055 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018056 case XML_SCHEMA_TYPE_ATTRIBUTE:
18057 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
18058 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018059 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018060 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018061 ctxt, NULL);
18062 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018063 case XML_SCHEMA_TYPE_PARTICLE:
18064 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018065 break;
18066 case XML_SCHEMA_TYPE_IDC_KEY:
18067 case XML_SCHEMA_TYPE_IDC_UNIQUE:
18068 case XML_SCHEMA_TYPE_IDC_KEYREF:
18069 xmlSchemaResolveIDCKeyRef((xmlSchemaIDCPtr) item, ctxt, NULL);
18070 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018071 default:
18072 break;
18073 }
18074 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018075 if (ctxt->nberrors != 0)
18076 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018077 /*
18078 * Circularity checks.
18079 */
18080 for (i = 0; i < nbItems; i++) {
18081 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018082 switch (item->type) {
18083 case XML_SCHEMA_TYPE_COMPLEX:
18084 case XML_SCHEMA_TYPE_SIMPLE:
18085 xmlSchemaCheckTypeDefCircular(
18086 (xmlSchemaTypePtr) item, ctxt, NULL);
18087 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018088 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018089 xmlSchemaCheckGroupDefCircular(
18090 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018091 break;
18092 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18093 xmlSchemaCheckAttributeGroupCircular(
18094 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18095 break;
18096 default:
18097 break;
18098 }
18099 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018100 if (ctxt->nberrors != 0)
18101 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018102 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018103 * Set the "term" of particles pointing to model group definitions
18104 * to the contained model group.
18105 */
18106 for (i = 0; i < nbItems; i++) {
18107 item = items[i];
18108 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18109 (((xmlSchemaParticlePtr) item)->children != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018110 (((xmlSchemaParticlePtr) item)->children->type ==
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018111 XML_SCHEMA_TYPE_GROUP)) {
18112 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18113 ctxt, NULL);
18114 }
18115 }
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018116 if (ctxt->nberrors != 0)
18117 return;
18118 for (i = 0; i < nbItems; i++) {
18119 item = items[i];
18120 switch (item->type) {
18121 case XML_SCHEMA_TYPE_ELEMENT:
18122 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
18123 NULL, NULL, NULL);
18124 break;
18125 default:
18126 break;
18127 }
18128 }
18129 if (ctxt->nberrors != 0)
18130 return;
18131
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018132 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018133 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018134 */
18135 for (i = 0; i < nbItems; i++) {
18136 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018137 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018138 case XML_SCHEMA_TYPE_SIMPLE:
18139 case XML_SCHEMA_TYPE_COMPLEX:
18140 xmlSchemaTypeFixup(item, ctxt, NULL);
18141 break;
18142 default:
18143 break;
18144 }
18145 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018146 if (ctxt->nberrors != 0)
18147 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018148 /*
18149 * Validate value contraint values.
18150 */
18151 for (i = 0; i < nbItems; i++) {
18152 item = items[i];
18153 switch (item->type) {
18154 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018155 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18156 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018157 break;
18158 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018159 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018160 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018161 break;
18162 default:
18163 break;
18164 }
18165 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018166 if (ctxt->nberrors != 0)
18167 return;
18168 /*
18169 * Build the content model for complex types.
18170 */
18171 for (i = 0; i < nbItems; i++) {
18172 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018173 switch (item->type) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018174 case XML_SCHEMA_TYPE_COMPLEX:
18175 xmlSchemaBuildContentModel(item, ctxt, NULL);
18176 break;
18177 default:
18178 break;
18179 }
18180 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018181}
18182
18183/**
18184 * xmlSchemaAssembleByLocation:
18185 * @pctxt: a schema parser context
18186 * @vctxt: a schema validation context
18187 * @schema: the existing schema
18188 * @node: the node that fired the assembling
18189 * @nsName: the namespace name of the new schema
18190 * @location: the location of the schema
18191 *
18192 * Expands an existing schema by an additional schema.
18193 *
18194 * Returns 0 if the new schema is correct, a positive error code
18195 * number otherwise and -1 in case of an internal or API error.
18196 */
18197static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018198xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018199 xmlSchemaPtr schema,
18200 xmlNodePtr node,
18201 const xmlChar *nsName,
18202 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018203{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018204 const xmlChar *targetNs, *oldtns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018205 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018206 int oldflags, ret = 0, oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018207 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018208 xmlSchemaParserCtxtPtr pctxt;
18209
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018210 /*
18211 * This should be used:
18212 * 1. on <import>(s)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018213 * 2. if requested by the validated instance
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018214 * 3. if requested via the API
18215 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018216 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018217 return (-1);
18218 /*
18219 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018220 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018221 if ((vctxt->pctxt == NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018222 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
18223 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018224 pctxt = vctxt->pctxt;
18225 /*
18226 * Set the counter to produce unique names for anonymous items.
18227 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018228 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018229 /*
18230 * Acquire the schema document.
18231 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018232 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
18233 node, nsName, location, &doc, &targetNs, 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018234 if (ret != 0) {
18235 if (doc != NULL)
18236 xmlFreeDoc(doc);
18237 } else if (doc != NULL) {
18238 docElem = xmlDocGetRootElement(doc);
18239 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018240 * Create new assemble info.
18241 */
18242 if (pctxt->assemble == NULL) {
18243 pctxt->assemble = xmlSchemaNewAssemble();
18244 if (pctxt->assemble == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018245 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018246 "Memory error: xmlSchemaAssembleByLocation, "
18247 "allocating assemble info", NULL);
18248 xmlFreeDoc(doc);
18249 return (-1);
18250 }
18251 }
18252 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018253 * Save and reset the context & schema.
18254 */
18255 oldflags = schema->flags;
18256 oldtns = schema->targetNamespace;
18257 olddoc = schema->doc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018258 oldIsS4S = vctxt->pctxt->isS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018259
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018260 xmlSchemaClearSchemaDefaults(schema);
18261 schema->targetNamespace = targetNs;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018262 if ((targetNs != NULL) &&
18263 xmlStrEqual(targetNs, xmlSchemaNs)) {
18264 /*
18265 * We are parsing the schema for schema!
18266 */
18267 vctxt->pctxt->isS4S = 1;
18268 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018269 /* schema->nbCurItems = 0; */
18270 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018271 pctxt->ctxtType = NULL;
18272 pctxt->parentItem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018273
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018274 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18275 if (pctxt->nberrors != 0) {
18276 vctxt->nberrors += pctxt->nberrors;
18277 goto finally;
18278 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018279 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018280 if (pctxt->nberrors != 0) {
18281 vctxt->nberrors += pctxt->nberrors;
18282 goto finally;
18283 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018284 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018285 if (pctxt->nberrors != 0)
18286 vctxt->nberrors += pctxt->nberrors;
18287finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018288 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018289 * Set the counter of items.
18290 */
18291 schema->counter = pctxt->counter;
18292 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018293 * Free the list of assembled components.
18294 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018295 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018296 /*
18297 * Restore the context & schema.
18298 */
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018299 vctxt->pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018300 schema->flags = oldflags;
18301 schema->targetNamespace = oldtns;
18302 schema->doc = olddoc;
18303 ret = pctxt->err;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018304 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018305 return (ret);
18306}
18307
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018308static xmlSchemaAttrInfoPtr
18309xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
18310 int metaType)
18311{
18312 if (vctxt->nbAttrInfos == 0)
18313 return (NULL);
18314 {
18315 int i;
18316 xmlSchemaAttrInfoPtr iattr;
18317
18318 for (i = 0; i < vctxt->nbAttrInfos; i++) {
18319 iattr = vctxt->attrInfos[i];
18320 if (iattr->metaType == metaType)
18321 return (iattr);
18322 }
18323
18324 }
18325 return (NULL);
18326}
18327
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018328/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018329 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018330 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018331 *
18332 * Expands an existing schema by an additional schema using
18333 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18334 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18335 * must be set to 1.
18336 *
18337 * Returns 0 if the new schema is correct, a positive error code
18338 * number otherwise and -1 in case of an internal or API error.
18339 */
18340static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018341xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018342{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018343 const xmlChar *cur, *end;
18344 const xmlChar *nsname = NULL, *location;
18345 int count = 0;
18346 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018347 xmlSchemaAttrInfoPtr iattr;
18348
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018349 /*
18350 * Parse the value; we will assume an even number of values
18351 * to be given (this is how Xerces and XSV work).
18352 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018353 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
18354 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
18355 if (iattr == NULL)
18356 xmlSchemaGetMetaAttrInfo(vctxt,
18357 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
18358 if (iattr == NULL)
18359 return (0);
18360 cur = iattr->value;
18361 do {
18362 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018363 /*
18364 * Get the namespace name.
18365 */
18366 while (IS_BLANK_CH(*cur))
18367 cur++;
18368 end = cur;
18369 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18370 end++;
18371 if (end == cur)
18372 break;
18373 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018374 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018375 cur = end;
18376 }
18377 /*
18378 * Get the URI.
18379 */
18380 while (IS_BLANK_CH(*cur))
18381 cur++;
18382 end = cur;
18383 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18384 end++;
18385 if (end == cur)
18386 break;
18387 count++;
18388 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018389 cur = end;
18390 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
18391 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018392 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018393 VERROR_INT("xmlSchemaAssembleByXSI",
18394 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018395 return (-1);
18396 }
18397 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018398 return (ret);
18399}
18400
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018401#define VAL_CREATE_DICT if (vctxt->dict == NULL) vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018402
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018403static const xmlChar *
18404xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
18405 const xmlChar *prefix)
18406{
18407 if (vctxt->sax != NULL) {
18408 int i, j;
18409 xmlSchemaNodeInfoPtr inode;
18410
18411 for (i = vctxt->depth; i >= 0; i--) {
18412 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
18413 inode = vctxt->elemInfos[i];
18414 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
18415 if (((prefix == NULL) &&
18416 (inode->nsBindings[j] == NULL)) ||
18417 ((prefix != NULL) && xmlStrEqual(prefix,
18418 inode->nsBindings[j]))) {
18419
18420 /*
18421 * Note that the namespace bindings are already
18422 * in a string dict.
18423 */
18424 return (inode->nsBindings[j+1]);
18425 }
18426 }
18427 }
18428 }
18429 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018430#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018431 } else if (vctxt->reader != NULL) {
18432 xmlChar *nsName;
18433
18434 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
18435 if (nsName != NULL) {
18436 const xmlChar *ret;
18437
18438 VAL_CREATE_DICT;
18439 ret = xmlDictLookup(vctxt->dict, nsName, -1);
18440 xmlFree(nsName);
18441 return (ret);
18442 } else
18443 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018444#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018445 } else {
18446 xmlNsPtr ns;
18447
18448 if ((vctxt->inode->node == NULL) ||
18449 (vctxt->inode->node->doc == NULL)) {
18450 VERROR_INT("xmlSchemaLookupNamespace",
18451 "no node or node's doc avaliable");
18452 return (NULL);
18453 }
18454 ns = xmlSearchNs(vctxt->inode->node->doc,
18455 vctxt->inode->node, prefix);
18456 if (ns != NULL)
18457 return (ns->href);
18458 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018459 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018460}
18461
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018462/*
18463* This one works on the schema of the validation context.
18464*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018465static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018466xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18467 xmlSchemaPtr schema,
18468 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018469 const xmlChar *value,
18470 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018471 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018472{
18473 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018474
18475 if (vctxt && (vctxt->schema == NULL)) {
18476 VERROR_INT("xmlSchemaValidateNotation",
18477 "a schema is needed on the validation context");
18478 return (-1);
18479 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018480 ret = xmlValidateQName(value, 1);
18481 if (ret != 0)
18482 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018483 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018484 xmlChar *localName = NULL;
18485 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018486
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018487 localName = xmlSplitQName2(value, &prefix);
18488 if (prefix != NULL) {
18489 const xmlChar *nsName = NULL;
18490
18491 if (vctxt != NULL)
18492 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
18493 else if (node != NULL) {
18494 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
18495 if (ns != NULL)
18496 nsName = ns->href;
18497 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018498 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018499 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018500 return (1);
18501 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018502 if (nsName == NULL) {
18503 xmlFree(prefix);
18504 xmlFree(localName);
18505 return (1);
18506 }
18507 if (xmlHashLookup2(schema->notaDecl, localName,
18508 nsName) != NULL) {
18509 if (valNeeded && (val != NULL)) {
18510 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
18511 BAD_CAST xmlStrdup(nsName));
18512 if (*val == NULL)
18513 ret = -1;
18514 }
18515 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018516 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018517 xmlFree(prefix);
18518 xmlFree(localName);
18519 } else {
18520 if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
18521 if (valNeeded && (val != NULL)) {
18522 (*val) = xmlSchemaNewNOTATIONValue(
18523 BAD_CAST xmlStrdup(value), NULL);
18524 if (*val == NULL)
18525 ret = -1;
18526 }
18527 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018528 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018529 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018530 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018531 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018532}
18533
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018534/************************************************************************
18535 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018536 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018537 * *
18538 ************************************************************************/
18539
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018540/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018541 * xmlSchemaAugmentIDC:
18542 * @idcDef: the IDC definition
18543 *
18544 * Creates an augmented IDC definition item.
18545 *
18546 * Returns the item, or NULL on internal errors.
18547 */
18548static void
18549xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18550 xmlSchemaValidCtxtPtr vctxt)
18551{
18552 xmlSchemaIDCAugPtr aidc;
18553
18554 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18555 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018556 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018557 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18558 NULL);
18559 return;
18560 }
18561 aidc->bubbleDepth = -1;
18562 aidc->def = idcDef;
18563 aidc->next = NULL;
18564 if (vctxt->aidcs == NULL)
18565 vctxt->aidcs = aidc;
18566 else {
18567 aidc->next = vctxt->aidcs;
18568 vctxt->aidcs = aidc;
18569 }
18570}
18571
18572/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018573 * xmlSchemaIDCNewBinding:
18574 * @idcDef: the IDC definition of this binding
18575 *
18576 * Creates a new IDC binding.
18577 *
18578 * Returns the new binding in case of succeeded, NULL on internal errors.
18579 */
18580static xmlSchemaPSVIIDCBindingPtr
18581xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18582{
18583 xmlSchemaPSVIIDCBindingPtr ret;
18584
18585 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18586 sizeof(xmlSchemaPSVIIDCBinding));
18587 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018588 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018589 "allocating a PSVI IDC binding item", NULL);
18590 return (NULL);
18591 }
18592 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18593 ret->definition = idcDef;
18594 return (ret);
18595}
18596
18597/**
18598 * xmlSchemaIDCStoreNodeTableItem:
18599 * @vctxt: the WXS validation context
18600 * @item: the IDC node table item
18601 *
18602 * The validation context is used to store an IDC node table items.
18603 * They are stored to avoid copying them if IDC node-tables are merged
18604 * with corresponding parent IDC node-tables (bubbling).
18605 *
18606 * Returns 0 if succeeded, -1 on internal errors.
18607 */
18608static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018609xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018610 xmlSchemaPSVIIDCNodePtr item)
18611{
18612 /*
18613 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018614 */
18615 if (vctxt->idcNodes == NULL) {
18616 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018617 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18618 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018619 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018620 "allocating the IDC node table item list", NULL);
18621 return (-1);
18622 }
18623 vctxt->sizeIdcNodes = 20;
18624 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18625 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018626 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18627 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018628 sizeof(xmlSchemaPSVIIDCNodePtr));
18629 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018630 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018631 "re-allocating the IDC node table item list", NULL);
18632 return (-1);
18633 }
18634 }
18635 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018636
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018637 return (0);
18638}
18639
18640/**
18641 * xmlSchemaIDCStoreKey:
18642 * @vctxt: the WXS validation context
18643 * @item: the IDC key
18644 *
18645 * The validation context is used to store an IDC key.
18646 *
18647 * Returns 0 if succeeded, -1 on internal errors.
18648 */
18649static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018650xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018651 xmlSchemaPSVIIDCKeyPtr key)
18652{
18653 /*
18654 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018655 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018656 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018657 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018658 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18659 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018660 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018661 "allocating the IDC key storage list", NULL);
18662 return (-1);
18663 }
18664 vctxt->sizeIdcKeys = 40;
18665 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18666 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018667 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18668 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018669 sizeof(xmlSchemaPSVIIDCKeyPtr));
18670 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018671 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018672 "re-allocating the IDC key storage list", NULL);
18673 return (-1);
18674 }
18675 }
18676 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018677
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018678 return (0);
18679}
18680
18681/**
18682 * xmlSchemaIDCAppendNodeTableItem:
18683 * @bind: the IDC binding
18684 * @ntItem: the node-table item
18685 *
18686 * Appends the IDC node-table item to the binding.
18687 *
18688 * Returns 0 on success and -1 on internal errors.
18689 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018690static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018691xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
18692 xmlSchemaPSVIIDCNodePtr ntItem)
18693{
18694 if (bind->nodeTable == NULL) {
18695 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018696 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018697 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
18698 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018699 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018700 "allocating an array of IDC node-table items", NULL);
18701 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018702 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018703 } else if (bind->sizeNodes <= bind->nbNodes) {
18704 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018705 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18706 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018707 sizeof(xmlSchemaPSVIIDCNodePtr));
18708 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018709 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018710 "re-allocating an array of IDC node-table items", NULL);
18711 return(-1);
18712 }
18713 }
18714 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018715 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018716}
18717
18718/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018719 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018720 * @vctxt: the WXS validation context
18721 * @matcher: the IDC matcher
18722 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018723 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018724 * of the given matcher. If none found, a new one is created
18725 * and added to the IDC table.
18726 *
18727 * Returns an IDC binding or NULL on internal errors.
18728 */
18729static xmlSchemaPSVIIDCBindingPtr
18730xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
18731 xmlSchemaIDCMatcherPtr matcher)
18732{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018733 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018734
18735 info = vctxt->elemInfos[matcher->depth];
18736
18737 if (info->idcTable == NULL) {
18738 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
18739 if (info->idcTable == NULL)
18740 return (NULL);
18741 return(info->idcTable);
18742 } else {
18743 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018744
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018745 bind = info->idcTable;
18746 do {
18747 if (bind->definition == matcher->aidc->def)
18748 return(bind);
18749 if (bind->next == NULL) {
18750 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
18751 if (bind->next == NULL)
18752 return (NULL);
18753 return(bind->next);
18754 }
18755 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018756 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018757 }
18758 return (NULL);
18759}
18760
18761/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018762 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018763 * @key: the IDC key
18764 *
18765 * Frees an IDC key together with its compiled value.
18766 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018767static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018768xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
18769{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018770 if (key->val != NULL)
18771 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018772 xmlFree(key);
18773}
18774
18775/**
18776 * xmlSchemaIDCFreeBinding:
18777 *
18778 * Frees an IDC binding. Note that the node table-items
18779 * are not freed.
18780 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018781static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018782xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
18783{
18784 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018785 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18786 int i;
18787 /*
18788 * Node-table items for keyrefs are not stored globally
18789 * to the validation context, since they are not bubbled.
18790 * We need to free them here.
18791 */
18792 for (i = 0; i < bind->nbNodes; i++) {
18793 xmlFree(bind->nodeTable[i]->keys);
18794 xmlFree(bind->nodeTable[i]);
18795 }
18796 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018797 xmlFree(bind->nodeTable);
18798 }
18799 xmlFree(bind);
18800}
18801
18802/**
18803 * xmlSchemaIDCFreeIDCTable:
18804 * @bind: the first IDC binding in the list
18805 *
18806 * Frees an IDC table, i.e. all the IDC bindings in the list.
18807 */
18808static void
18809xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
18810{
18811 xmlSchemaPSVIIDCBindingPtr prev;
18812
18813 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018814 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018815 bind = bind->next;
18816 xmlSchemaIDCFreeBinding(prev);
18817 }
18818}
18819
18820/**
18821 * xmlSchemaIDCFreeMatcherList:
18822 * @matcher: the first IDC matcher in the list
18823 *
18824 * Frees a list of IDC matchers.
18825 */
18826static void
18827xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
18828{
18829 xmlSchemaIDCMatcherPtr next;
18830
18831 while (matcher != NULL) {
18832 next = matcher->next;
18833 if (matcher->keySeqs != NULL) {
18834 int i;
18835 for (i = 0; i < matcher->sizeKeySeqs; i++)
18836 if (matcher->keySeqs[i] != NULL)
18837 xmlFree(matcher->keySeqs[i]);
18838 xmlFree(matcher->keySeqs);
18839 }
18840 xmlFree(matcher);
18841 matcher = next;
18842 }
18843}
18844
18845/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018846 * xmlSchemaIDCAddStateObject:
18847 * @vctxt: the WXS validation context
18848 * @matcher: the IDC matcher
18849 * @sel: the XPath information
18850 * @parent: the parent "selector" state object if any
18851 * @type: "selector" or "field"
18852 *
18853 * Creates/reuses and activates state objects for the given
18854 * XPath information; if the XPath expression consists of unions,
18855 * multiple state objects are created for every unioned expression.
18856 *
18857 * Returns 0 on success and -1 on internal errors.
18858 */
18859static int
18860xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
18861 xmlSchemaIDCMatcherPtr matcher,
18862 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018863 int type)
18864{
18865 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018866
18867 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018868 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018869 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018870 if (vctxt->xpathStatePool != NULL) {
18871 sto = vctxt->xpathStatePool;
18872 vctxt->xpathStatePool = sto->next;
18873 sto->next = NULL;
18874 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018875 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018876 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018877 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018878 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
18879 if (sto == NULL) {
18880 xmlSchemaVErrMemory(NULL,
18881 "allocating an IDC state object", NULL);
18882 return (-1);
18883 }
18884 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
18885 }
18886 /*
18887 * Add to global list.
18888 */
18889 if (vctxt->xpathStates != NULL)
18890 sto->next = vctxt->xpathStates;
18891 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018892
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018893 /*
18894 * Free the old xpath validation context.
18895 */
18896 if (sto->xpathCtxt != NULL)
18897 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
18898
18899 /*
18900 * Create a new XPath (pattern) validation context.
18901 */
18902 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
18903 (xmlPatternPtr) sel->xpathComp);
18904 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018905 VERROR_INT("xmlSchemaIDCAddStateObject",
18906 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018907 return (-1);
18908 }
18909 sto->type = type;
18910 sto->depth = vctxt->depth;
18911 sto->matcher = matcher;
18912 sto->sel = sel;
18913 sto->nbHistory = 0;
18914
18915#if DEBUG_IDC
18916 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
18917 sto->sel->xpath);
18918#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018919 return (0);
18920}
18921
18922/**
18923 * xmlSchemaXPathEvaluate:
18924 * @vctxt: the WXS validation context
18925 * @nodeType: the nodeType of the current node
18926 *
18927 * Evaluates all active XPath state objects.
18928 *
18929 * Returns the number of IC "field" state objects which resolved to
18930 * this node, 0 if none resolved and -1 on internal errors.
18931 */
18932static int
18933xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018934 xmlElementType nodeType)
18935{
18936 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018937 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018938
18939 if (vctxt->xpathStates == NULL)
18940 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018941
18942 if (nodeType == XML_ATTRIBUTE_NODE)
18943 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018944#if DEBUG_IDC
18945 {
18946 xmlChar *str = NULL;
18947 xmlGenericError(xmlGenericErrorContext,
18948 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018949 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
18950 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018951 FREE_AND_NULL(str)
18952 }
18953#endif
18954 /*
18955 * Process all active XPath state objects.
18956 */
18957 first = vctxt->xpathStates;
18958 sto = first;
18959 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018960#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018961 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018962 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
18963 sto->matcher->aidc->def->name, sto->sel->xpath);
18964 else
18965 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
18966 sto->matcher->aidc->def->name, sto->sel->xpath);
18967#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018968 if (nodeType == XML_ELEMENT_NODE)
18969 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018970 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018971 else
18972 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018973 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018974
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018975 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018976 VERROR_INT("xmlSchemaXPathEvaluate",
18977 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018978 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018979 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018980 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018981 goto next_sto;
18982 /*
18983 * Full match.
18984 */
18985#if DEBUG_IDC
18986 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018987 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018988#endif
18989 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018990 * Register a match in the state object history.
18991 */
18992 if (sto->history == NULL) {
18993 sto->history = (int *) xmlMalloc(5 * sizeof(int));
18994 if (sto->history == NULL) {
18995 xmlSchemaVErrMemory(NULL,
18996 "allocating the state object history", NULL);
18997 return(-1);
18998 }
18999 sto->sizeHistory = 10;
19000 } else if (sto->sizeHistory <= sto->nbHistory) {
19001 sto->sizeHistory *= 2;
19002 sto->history = (int *) xmlRealloc(sto->history,
19003 sto->sizeHistory * sizeof(int));
19004 if (sto->history == NULL) {
19005 xmlSchemaVErrMemory(NULL,
19006 "re-allocating the state object history", NULL);
19007 return(-1);
19008 }
19009 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019010 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019011
19012#ifdef DEBUG_IDC
19013 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
19014 vctxt->depth);
19015#endif
19016
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019017 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
19018 xmlSchemaIDCSelectPtr sel;
19019 /*
19020 * Activate state objects for the IDC fields of
19021 * the IDC selector.
19022 */
19023#if DEBUG_IDC
19024 xmlGenericError(xmlGenericErrorContext, "IDC: "
19025 "activating field states\n");
19026#endif
19027 sel = sto->matcher->aidc->def->fields;
19028 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019029 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
19030 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
19031 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019032 sel = sel->next;
19033 }
19034 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19035 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000019036 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019037 */
19038#if DEBUG_IDC
19039 xmlGenericError(xmlGenericErrorContext,
19040 "IDC: key found\n");
19041#endif
19042 /*
19043 * Notify that the character value of this node is
19044 * needed.
19045 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019046 if (resolved == 0) {
19047 if ((vctxt->inode->flags &
19048 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
19049 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
19050 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019051 resolved++;
19052 }
19053next_sto:
19054 if (sto->next == NULL) {
19055 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019056 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019057 */
19058 head = first;
19059 sto = vctxt->xpathStates;
19060 } else
19061 sto = sto->next;
19062 }
19063 return (resolved);
19064}
19065
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019066static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019067xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019068 xmlChar **buf,
19069 xmlSchemaPSVIIDCKeyPtr *seq,
19070 int count)
19071{
19072 int i, res;
19073 const xmlChar *value = NULL;
19074
19075 *buf = xmlStrdup(BAD_CAST "[");
19076 for (i = 0; i < count; i++) {
19077 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019078 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
19079 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019080 if (res == 0)
19081 *buf = xmlStrcat(*buf, value);
19082 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019083 VERROR_INT("xmlSchemaFormatIDCKeySequence",
19084 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019085 *buf = xmlStrcat(*buf, BAD_CAST "???");
19086 }
19087 if (i < count -1)
19088 *buf = xmlStrcat(*buf, BAD_CAST "', ");
19089 else
19090 *buf = xmlStrcat(*buf, BAD_CAST "'");
19091 if (value != NULL) {
19092 xmlFree((xmlChar *) value);
19093 value = NULL;
19094 }
19095 }
19096 *buf = xmlStrcat(*buf, BAD_CAST "]");
19097
19098 return (BAD_CAST *buf);
19099}
19100
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019101/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019102 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019103 * @vctxt: the WXS validation context
19104 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019105 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019106 *
19107 * Processes and pops the history items of the IDC state objects.
19108 * IDC key-sequences are validated/created on IDC bindings.
19109 *
19110 * Returns 0 on success and -1 on internal errors.
19111 */
19112static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019113xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019114 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019115{
19116 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019117 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019118 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019119 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019120
19121 if (vctxt->xpathStates == NULL)
19122 return (0);
19123 sto = vctxt->xpathStates;
19124
19125#if DEBUG_IDC
19126 {
19127 xmlChar *str = NULL;
19128 xmlGenericError(xmlGenericErrorContext,
19129 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019130 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19131 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019132 FREE_AND_NULL(str)
19133 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019134#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019135 /*
19136 * Evaluate the state objects.
19137 */
19138 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000019139 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19140 if (res == -1) {
19141 VERROR_INT("xmlSchemaXPathProcessHistory",
19142 "calling xmlStreamPop()");
19143 return (-1);
19144 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019145#if DEBUG_IDC
19146 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19147 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019148#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019149 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019150 goto deregister_check;
19151
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019152 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019153
19154 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019155 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019156 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019157 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019158 sto = sto->next;
19159 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019160 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019161 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19162 if (! IS_SIMPLE_TYPE(type)) {
19163 /*
19164 * Not qualified if the field resolves to a node of non
19165 * simple type.
19166 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019167 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19168 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019169 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19170 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019171 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019172
19173 sto->nbHistory--;
19174 goto deregister_check;
19175 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019176 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019177 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019178 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019179 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019180 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019181 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019182 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19183 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019184 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019185 sto->nbHistory--;
19186 goto deregister_check;
19187 } else {
19188 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19189 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019190 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019191
19192 /*
19193 * The key will be anchored on the matcher's list of
19194 * key-sequences. The position in this list is determined
19195 * by the target node's depth relative to the matcher's
19196 * depth of creation (i.e. the depth of the scope element).
19197 */
19198 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019199 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019200
19201 /*
19202 * Create/grow the array of key-sequences.
19203 */
19204 if (matcher->keySeqs == NULL) {
19205 if (pos > 9)
19206 matcher->sizeKeySeqs = pos * 2;
19207 else
19208 matcher->sizeKeySeqs = 10;
19209 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19210 xmlMalloc(matcher->sizeKeySeqs *
19211 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19212 if (matcher->keySeqs == NULL) {
19213 xmlSchemaVErrMemory(NULL,
19214 "allocating an array of key-sequences",
19215 NULL);
19216 return(-1);
19217 }
19218 memset(matcher->keySeqs, 0,
19219 matcher->sizeKeySeqs *
19220 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19221 } else if (pos >= matcher->sizeKeySeqs) {
19222 int i = matcher->sizeKeySeqs;
19223
19224 matcher->sizeKeySeqs *= 2;
19225 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19226 xmlRealloc(matcher->keySeqs,
19227 matcher->sizeKeySeqs *
19228 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019229 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019230 xmlSchemaVErrMemory(NULL,
19231 "reallocating an array of key-sequences",
19232 NULL);
19233 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019234 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019235 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019236 * The array needs to be NULLed.
19237 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019238 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019239 for (; i < matcher->sizeKeySeqs; i++)
19240 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019241 }
19242
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019243 /*
19244 * Get/create the key-sequence.
19245 */
19246 keySeq = matcher->keySeqs[pos];
19247 if (keySeq == NULL) {
19248 goto create_sequence;
19249 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019250 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019251 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019252 * cvc-identity-constraint:
19253 * 3 For each node in the ·target node set· all
19254 * of the {fields}, with that node as the context
19255 * node, evaluate to either an empty node-set or
19256 * a node-set with exactly one member, which must
19257 * have a simple type.
19258 *
19259 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019260 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019261 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19262 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019263 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019264 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019265 "with more than one member",
19266 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019267 sto->nbHistory--;
19268 goto deregister_check;
19269 } else {
19270 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019271 }
19272 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019273
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019274create_sequence:
19275 /*
19276 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019277 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019278 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19279 matcher->aidc->def->nbFields *
19280 sizeof(xmlSchemaPSVIIDCKeyPtr));
19281 if (keySeq == NULL) {
19282 xmlSchemaVErrMemory(NULL,
19283 "allocating an IDC key-sequence", NULL);
19284 return(-1);
19285 }
19286 memset(keySeq, 0, matcher->aidc->def->nbFields *
19287 sizeof(xmlSchemaPSVIIDCKeyPtr));
19288 matcher->keySeqs[pos] = keySeq;
19289create_key:
19290 /*
19291 * Created a key once per node only.
19292 */
19293 if (key == NULL) {
19294 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19295 sizeof(xmlSchemaPSVIIDCKey));
19296 if (key == NULL) {
19297 xmlSchemaVErrMemory(NULL,
19298 "allocating a IDC key", NULL);
19299 xmlFree(keySeq);
19300 matcher->keySeqs[pos] = NULL;
19301 return(-1);
19302 }
19303 /*
19304 * Consume the compiled value.
19305 */
19306 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019307 key->val = vctxt->inode->val;
19308 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019309 /*
19310 * Store the key in a global list.
19311 */
19312 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19313 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019314 return (-1);
19315 }
19316 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019317 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019318 }
19319 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019320
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019321 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19322 xmlSchemaPSVIIDCBindingPtr bind;
19323 xmlSchemaPSVIIDCNodePtr ntItem;
19324 xmlSchemaIDCMatcherPtr matcher;
19325 xmlSchemaIDCPtr idc;
19326 int pos, i, j, nbKeys;
19327 /*
19328 * Here we have the following scenario:
19329 * An IDC 'selector' state object resolved to a target node,
19330 * during the time this target node was in the
19331 * ancestor-or-self axis, the 'field' state object(s) looked
19332 * out for matching nodes to create a key-sequence for this
19333 * target node. Now we are back to this target node and need
19334 * to put the key-sequence, together with the target node
19335 * itself, into the node-table of the corresponding IDC
19336 * binding.
19337 */
19338 matcher = sto->matcher;
19339 idc = matcher->aidc->def;
19340 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019341 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019342 /*
19343 * Check if the matcher has any key-sequences at all, plus
19344 * if it has a key-sequence for the current target node.
19345 */
19346 if ((matcher->keySeqs == NULL) ||
19347 (matcher->sizeKeySeqs <= pos)) {
19348 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19349 goto selector_key_error;
19350 else
19351 goto selector_leave;
19352 }
19353
19354 keySeq = &(matcher->keySeqs[pos]);
19355 if (*keySeq == NULL) {
19356 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19357 goto selector_key_error;
19358 else
19359 goto selector_leave;
19360 }
19361
19362 for (i = 0; i < nbKeys; i++) {
19363 if ((*keySeq)[i] == NULL) {
19364 /*
19365 * Not qualified, if not all fields did resolve.
19366 */
19367 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19368 /*
19369 * All fields of a "key" IDC must resolve.
19370 */
19371 goto selector_key_error;
19372 }
19373 goto selector_leave;
19374 }
19375 }
19376 /*
19377 * All fields did resolve.
19378 */
19379
19380 /*
19381 * 4.1 If the {identity-constraint category} is unique(/key),
19382 * then no two members of the ·qualified node set· have
19383 * ·key-sequences· whose members are pairwise equal, as
19384 * defined by Equal in [XML Schemas: Datatypes].
19385 *
19386 * Get the IDC binding from the matcher and check for
19387 * duplicate key-sequences.
19388 */
19389 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19390 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19391 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019392 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019393
19394 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019395 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019396 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019397 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019398 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019399 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019400 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019401 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019402 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019403 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019404 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019405 if (res == -1) {
19406 return (-1);
19407 } else if (res == 0)
19408 break;
19409 }
19410 if (res == 1) {
19411 /*
19412 * Duplicate found.
19413 */
19414 break;
19415 }
19416 i++;
19417 } while (i < bind->nbNodes);
19418 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019419 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019420 /*
19421 * TODO: Try to report the key-sequence.
19422 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019423 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19424 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019425 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019426 "Duplicate key-sequence %s",
19427 xmlSchemaFormatIDCKeySequence(vctxt, &str,
19428 (*keySeq), nbKeys), NULL);
19429 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019430 goto selector_leave;
19431 }
19432 }
19433 /*
19434 * Add a node-table item to the IDC binding.
19435 */
19436 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19437 sizeof(xmlSchemaPSVIIDCNode));
19438 if (ntItem == NULL) {
19439 xmlSchemaVErrMemory(NULL,
19440 "allocating an IDC node-table item", NULL);
19441 xmlFree(*keySeq);
19442 *keySeq = NULL;
19443 return(-1);
19444 }
19445 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19446
19447 /*
19448 * Store the node-table item on global list.
19449 */
19450 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19451 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19452 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019453 xmlFree(*keySeq);
19454 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019455 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019456 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019457 }
19458 /*
19459 * Init the node-table item. Consume the key-sequence.
19460 */
19461 ntItem->node = vctxt->node;
19462 ntItem->keys = *keySeq;
19463 *keySeq = NULL;
19464 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19465 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19466 /*
19467 * Free the item, since keyref items won't be
19468 * put on a global list.
19469 */
19470 xmlFree(ntItem->keys);
19471 xmlFree(ntItem);
19472 }
19473 return (-1);
19474 }
19475
19476 goto selector_leave;
19477selector_key_error:
19478 /*
19479 * 4.2.1 (KEY) The ·target node set· and the
19480 * ·qualified node set· are equal, that is, every
19481 * member of the ·target node set· is also a member
19482 * of the ·qualified node set· and vice versa.
19483 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019484 VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
19485 "All 'key' fields must evaluate to a node");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019486selector_leave:
19487 /*
19488 * Free the key-sequence if not added to the IDC table.
19489 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019490 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019491 xmlFree(*keySeq);
19492 *keySeq = NULL;
19493 }
19494 } /* if selector */
19495
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019496 sto->nbHistory--;
19497
19498deregister_check:
19499 /*
19500 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019501 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019502 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019503#if DEBUG_IDC
19504 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19505 sto->sel->xpath);
19506#endif
19507 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019508 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019509 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019510 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019511 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019512 nextsto = sto->next;
19513 /*
19514 * Unlink from the list of active XPath state objects.
19515 */
19516 vctxt->xpathStates = sto->next;
19517 sto->next = vctxt->xpathStatePool;
19518 /*
19519 * Link it to the pool of reusable state objects.
19520 */
19521 vctxt->xpathStatePool = sto;
19522 sto = nextsto;
19523 } else
19524 sto = sto->next;
19525 } /* while (sto != NULL) */
19526 return (0);
19527}
19528
19529/**
19530 * xmlSchemaIDCRegisterMatchers:
19531 * @vctxt: the WXS validation context
19532 * @elemDecl: the element declaration
19533 *
19534 * Creates helper objects to evaluate IDC selectors/fields
19535 * successively.
19536 *
19537 * Returns 0 if OK and -1 on internal errors.
19538 */
19539static int
19540xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19541 xmlSchemaElementPtr elemDecl)
19542{
19543 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19544 xmlSchemaIDCPtr idc, refIdc;
19545 xmlSchemaIDCAugPtr aidc;
19546
19547 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19548 if (idc == NULL)
19549 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019550
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019551#if DEBUG_IDC
19552 {
19553 xmlChar *str = NULL;
19554 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019555 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019556 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19557 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019558 FREE_AND_NULL(str)
19559 }
19560#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019561 if (vctxt->inode->idcMatchers != NULL) {
19562 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19563 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019564 return (-1);
19565 }
19566 do {
19567 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19568 /*
19569 * Since IDCs bubbles are expensive we need to know the
19570 * depth at which the bubbles should stop; this will be
19571 * the depth of the top-most keyref IDC. If no keyref
19572 * references a key/unique IDC, the bubbleDepth will
19573 * be -1, indicating that no bubbles are needed.
19574 */
19575 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19576 if (refIdc != NULL) {
19577 /*
19578 * Lookup the augmented IDC.
19579 */
19580 aidc = vctxt->aidcs;
19581 while (aidc != NULL) {
19582 if (aidc->def == refIdc)
19583 break;
19584 aidc = aidc->next;
19585 }
19586 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019587 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019588 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019589 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019590 return (-1);
19591 }
19592 if ((aidc->bubbleDepth == -1) ||
19593 (vctxt->depth < aidc->bubbleDepth))
19594 aidc->bubbleDepth = vctxt->depth;
19595 }
19596 }
19597 /*
19598 * Lookup the augmented IDC item for the IDC definition.
19599 */
19600 aidc = vctxt->aidcs;
19601 while (aidc != NULL) {
19602 if (aidc->def == idc)
19603 break;
19604 aidc = aidc->next;
19605 }
19606 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019607 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19608 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019609 return (-1);
19610 }
19611 /*
19612 * Create an IDC matcher for every IDC definition.
19613 */
19614 matcher = (xmlSchemaIDCMatcherPtr)
19615 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
19616 if (matcher == NULL) {
19617 xmlSchemaVErrMemory(vctxt,
19618 "allocating an IDC matcher", NULL);
19619 return (-1);
19620 }
19621 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
19622 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019623 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019624 else
19625 last->next = matcher;
19626 last = matcher;
19627
19628 matcher->type = IDC_MATCHER;
19629 matcher->depth = vctxt->depth;
19630 matcher->aidc = aidc;
19631#if DEBUG_IDC
19632 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
19633#endif
19634 /*
19635 * Init the automaton state object.
19636 */
19637 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019638 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019639 return (-1);
19640
19641 idc = idc->next;
19642 } while (idc != NULL);
19643 return (0);
19644}
19645
19646/**
19647 * xmlSchemaBubbleIDCNodeTables:
19648 * @depth: the current tree depth
19649 *
19650 * Merges IDC bindings of an element at @depth into the corresponding IDC
19651 * bindings of its parent element. If a duplicate note-table entry is found,
19652 * both, the parent node-table entry and child entry are discarded from the
19653 * node-table of the parent.
19654 *
19655 * Returns 0 if OK and -1 on internal errors.
19656 */
19657static int
19658xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
19659{
19660 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019661 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
19662 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019663 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
19664 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019665 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019666 int duplTop;
19667
19668 /*
19669 * The node table has the following sections:
19670 *
19671 * O --> old node-table entries (first)
19672 * O
19673 * + --> new node-table entries
19674 * +
19675 * % --> new duplicate node-table entries
19676 * %
19677 * # --> old duplicate node-table entries
19678 * # (last)
19679 *
19680 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019681 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019682 if (bind == NULL) {
19683 /* Fine, no table, no bubbles. */
19684 return (0);
19685 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019686
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019687 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
19688 /*
19689 * Walk all bindings; create new or add to existing bindings.
19690 * Remove duplicate key-sequences.
19691 */
19692start_binding:
19693 while (bind != NULL) {
19694 /*
19695 * Skip keyref IDCs.
19696 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019697 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19698 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019699 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019700 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019701 /*
19702 * Check if the key/unique IDC table needs to be bubbled.
19703 */
19704 aidc = vctxt->aidcs;
19705 do {
19706 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019707 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019708 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019709 bind = bind->next;
19710 goto start_binding;
19711 }
19712 break;
19713 }
19714 aidc = aidc->next;
19715 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019716
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019717 if (parTable != NULL)
19718 parBind = *parTable;
19719 while (parBind != NULL) {
19720 /*
19721 * Search a matching parent binding for the
19722 * IDC definition.
19723 */
19724 if (parBind->definition == bind->definition) {
19725
19726 /*
19727 * Compare every node-table entry of the child node,
19728 * i.e. the key-sequence within, ...
19729 */
19730 oldNum = parBind->nbNodes; /* Skip newly added items. */
19731 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019732 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019733
19734 for (i = 0; i < bind->nbNodes; i++) {
19735 node = bind->nodeTable[i];
19736 if (node == NULL)
19737 continue;
19738 /*
19739 * ...with every key-sequence of the parent node, already
19740 * evaluated to be a duplicate key-sequence.
19741 */
19742 if (parBind->nbDupls != 0) {
19743 j = bind->nbNodes + newDupls;
19744 while (j < duplTop) {
19745 parNode = parBind->nodeTable[j];
19746 for (k = 0; k < bind->definition->nbFields; k++) {
19747 key = node->keys[k];
19748 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019749 ret = xmlSchemaAreValuesEqual(key->val,
19750 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019751 if (ret == -1) {
19752 /* TODO: Internal error */
19753 return(-1);
19754 } else if (ret == 0)
19755 break;
19756
19757 }
19758 if (ret == 1)
19759 /* Duplicate found. */
19760 break;
19761 j++;
19762 }
19763 if (j != duplTop) {
19764 /* Duplicate found. */
19765 continue;
19766 }
19767 }
19768 /*
19769 * ... and with every key-sequence of the parent node.
19770 */
19771 j = 0;
19772 while (j < oldNum) {
19773 parNode = parBind->nodeTable[j];
19774 /*
19775 * Compare key by key.
19776 */
19777 for (k = 0; k < parBind->definition->nbFields; k++) {
19778 key = node->keys[k];
19779 parKey = parNode->keys[k];
19780
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019781 ret = xmlSchemaAreValuesEqual(key->val,
19782 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019783 if (ret == -1) {
19784 /* TODO: Internal error */
19785 } else if (ret == 0)
19786 break;
19787
19788 }
19789 if (ret == 1)
19790 /*
19791 * The key-sequences are equal.
19792 */
19793 break;
19794 j++;
19795 }
19796 if (j != oldNum) {
19797 /*
19798 * Handle duplicates.
19799 */
19800 newDupls++;
19801 oldNum--;
19802 parBind->nbNodes--;
19803 /*
19804 * Move last old item to pos of duplicate.
19805 */
19806 parBind->nodeTable[j] =
19807 parBind->nodeTable[oldNum];
19808
19809 if (parBind->nbNodes != oldNum) {
19810 /*
19811 * If new items exist, move last new item to
19812 * last of old items.
19813 */
19814 parBind->nodeTable[oldNum] =
19815 parBind->nodeTable[parBind->nbNodes];
19816 }
19817 /*
19818 * Move duplicate to last pos of new/old items.
19819 */
19820 parBind->nodeTable[parBind->nbNodes] = parNode;
19821
19822 } else {
19823 /*
19824 * Add the node-table entry (node and key-sequence) of
19825 * the child node to the node table of the parent node.
19826 */
19827 if (parBind->nodeTable == NULL) {
19828 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019829 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019830 if (parBind->nodeTable == NULL) {
19831 xmlSchemaVErrMemory(NULL,
19832 "allocating IDC list of node-table items", NULL);
19833 return(-1);
19834 }
19835 parBind->sizeNodes = 1;
19836 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019837 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019838 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19839 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
19840 sizeof(xmlSchemaPSVIIDCNodePtr));
19841 if (parBind->nodeTable == NULL) {
19842 xmlSchemaVErrMemory(NULL,
19843 "re-allocating IDC list of node-table items", NULL);
19844 return(-1);
19845 }
19846 }
19847
19848 /*
19849 * Move first old duplicate to last position
19850 * of old duplicates +1.
19851 */
19852 if (parBind->nbDupls != 0) {
19853 parBind->nodeTable[duplTop] =
19854 parBind->nodeTable[parBind->nbNodes + newDupls];
19855 }
19856 /*
19857 * Move first new duplicate to last position of
19858 * new duplicates +1.
19859 */
19860 if (newDupls != 0) {
19861 parBind->nodeTable[parBind->nbNodes + newDupls] =
19862 parBind->nodeTable[parBind->nbNodes];
19863 }
19864 /*
19865 * Append the new node-table entry to the 'new node-table
19866 * entries' section.
19867 */
19868 parBind->nodeTable[parBind->nbNodes] = node;
19869 parBind->nbNodes++;
19870 duplTop++;
19871 }
19872 }
19873 parBind->nbDupls += newDupls;
19874 break;
19875 }
19876 if (parBind->next == NULL)
19877 lastParBind = parBind;
19878 parBind = parBind->next;
19879 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019880 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019881 /*
19882 * No binding for the IDC was found: create a new one and
19883 * copy all node-tables.
19884 */
19885 parBind = xmlSchemaIDCNewBinding(bind->definition);
19886 if (parBind == NULL)
19887 return(-1);
19888
19889 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19890 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
19891 if (parBind->nodeTable == NULL) {
19892 xmlSchemaVErrMemory(NULL,
19893 "allocating an array of IDC node-table items", NULL);
19894 xmlSchemaIDCFreeBinding(parBind);
19895 return(-1);
19896 }
19897 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019898 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019899 memcpy(parBind->nodeTable, bind->nodeTable,
19900 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019901 if (*parTable == NULL)
19902 *parTable = parBind;
19903 else
19904 lastParBind->next = parBind;
19905 }
19906 bind = bind->next;
19907 }
19908 return (0);
19909}
19910
19911/**
19912 * xmlSchemaCheckCVCIDCKeyRef:
19913 * @vctxt: the WXS validation context
19914 * @elemDecl: the element declaration
19915 *
19916 * Check the cvc-idc-keyref constraints.
19917 */
19918static int
19919xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
19920{
19921 xmlSchemaPSVIIDCBindingPtr refbind, bind;
19922
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019923 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019924 /*
19925 * Find a keyref.
19926 */
19927 while (refbind != NULL) {
19928 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19929 int i, j, k, res;
19930 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
19931 xmlSchemaPSVIIDCKeyPtr refKey, key;
19932
19933 /*
19934 * Find the referred key/unique.
19935 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019936 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019937 do {
19938 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
19939 bind->definition)
19940 break;
19941 bind = bind->next;
19942 } while (bind != NULL);
19943
19944 /*
19945 * Search for a matching key-sequences.
19946 */
19947 for (i = 0; i < refbind->nbNodes; i++) {
19948 res = 0;
19949 if (bind != NULL) {
19950 refKeys = refbind->nodeTable[i]->keys;
19951 for (j = 0; j < bind->nbNodes; j++) {
19952 keys = bind->nodeTable[j]->keys;
19953 for (k = 0; k < bind->definition->nbFields; k++) {
19954 refKey = refKeys[k];
19955 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019956 res = xmlSchemaAreValuesEqual(key->val,
19957 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019958 if (res == 0)
19959 break;
19960 else if (res == -1) {
19961 return (-1);
19962 }
19963 }
19964 if (res == 1) {
19965 /*
19966 * Match found.
19967 */
19968 break;
19969 }
19970 }
19971 }
19972 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019973 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019974 /* TODO: Report the key-sequence. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019975 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19976 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019977 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019978 "No match found for key-sequence %s of key "
19979 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019980 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019981 refbind->nodeTable[i]->keys,
19982 refbind->definition->nbFields),
19983 xmlSchemaFormatQName(&strB,
19984 refbind->definition->targetNamespace,
19985 refbind->definition->name));
19986 FREE_AND_NULL(str);
19987 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019988 }
19989 }
19990 }
19991 refbind = refbind->next;
19992 }
19993 return (0);
19994}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019995
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019996/************************************************************************
19997 * *
19998 * XML Reader validation code *
19999 * *
20000 ************************************************************************/
20001
20002static xmlSchemaAttrInfoPtr
20003xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020004{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020005 xmlSchemaAttrInfoPtr iattr;
20006 /*
20007 * Grow/create list of attribute infos.
20008 */
20009 if (vctxt->attrInfos == NULL) {
20010 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20011 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
20012 vctxt->sizeAttrInfos = 1;
20013 if (vctxt->attrInfos == NULL) {
20014 xmlSchemaVErrMemory(vctxt,
20015 "allocating attribute info list", NULL);
20016 return (NULL);
20017 }
20018 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
20019 vctxt->sizeAttrInfos++;
20020 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20021 xmlRealloc(vctxt->attrInfos,
20022 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
20023 if (vctxt->attrInfos == NULL) {
20024 xmlSchemaVErrMemory(vctxt,
20025 "re-allocating attribute info list", NULL);
20026 return (NULL);
20027 }
20028 } else {
20029 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
20030 if (iattr->localName != NULL) {
20031 VERROR_INT("xmlSchemaGetFreshAttrInfo",
20032 "attr info not cleared");
20033 return (NULL);
20034 }
20035 iattr->nodeType = XML_ATTRIBUTE_NODE;
20036 return (iattr);
20037 }
20038 /*
20039 * Create an attribute info.
20040 */
20041 iattr = (xmlSchemaAttrInfoPtr)
20042 xmlMalloc(sizeof(xmlSchemaAttrInfo));
20043 if (iattr == NULL) {
20044 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
20045 return (NULL);
20046 }
20047 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
20048 iattr->nodeType = XML_ATTRIBUTE_NODE;
20049 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
20050
20051 return (iattr);
20052}
20053
20054static int
20055xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
20056 xmlNodePtr attrNode,
20057 const xmlChar *localName,
20058 const xmlChar *nsName,
20059 int ownedNames,
20060 xmlChar *value,
20061 int ownedValue)
20062{
20063 xmlSchemaAttrInfoPtr attr;
20064
20065 attr = xmlSchemaGetFreshAttrInfo(vctxt);
20066 if (attr == NULL) {
20067 VERROR_INT("xmlSchemaPushAttribute",
20068 "calling xmlSchemaGetFreshAttrInfo()");
20069 return (-1);
20070 }
20071 attr->node = attrNode;
20072 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
20073 attr->localName = localName;
20074 attr->nsName = nsName;
20075 if (ownedNames)
20076 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
20077 /*
20078 * Evaluate if it's an XSI attribute.
20079 */
20080 if (nsName != NULL) {
20081 if (xmlStrEqual(localName, BAD_CAST "nil")) {
20082 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20083 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
20084 }
20085 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
20086 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20087 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
20088 }
20089 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
20090 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20091 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
20092 }
20093 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
20094 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20095 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
20096 }
20097 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
20098 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
20099 }
20100 }
20101 attr->value = value;
20102 if (ownedValue)
20103 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
20104 if (attr->metaType != 0)
20105 attr->state = XML_SCHEMAS_ATTR_META;
20106 return (0);
20107}
20108
20109static void
20110xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
20111{
20112 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
20113 FREE_AND_NULL(ielem->localName);
20114 FREE_AND_NULL(ielem->nsName);
20115 } else {
20116 ielem->localName = NULL;
20117 ielem->nsName = NULL;
20118 }
20119 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
20120 FREE_AND_NULL(ielem->value);
20121 } else {
20122 ielem->value = NULL;
20123 }
20124 if (ielem->val != NULL) {
20125 xmlSchemaFreeValue(ielem->val);
20126 ielem->val = NULL;
20127 }
20128 if (ielem->idcMatchers != NULL) {
20129 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
20130 ielem->idcMatchers = NULL;
20131 }
20132 if (ielem->idcTable != NULL) {
20133 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
20134 ielem->idcTable = NULL;
20135 }
20136 if (ielem->regexCtxt != NULL) {
20137 xmlRegFreeExecCtxt(ielem->regexCtxt);
20138 ielem->regexCtxt = NULL;
20139 }
20140 if (ielem->nsBindings != NULL) {
20141 xmlFree((xmlChar **)ielem->nsBindings);
20142 ielem->nsBindings = NULL;
20143 ielem->nbNsBindings = 0;
20144 ielem->sizeNsBindings = 0;
20145 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020146}
20147
20148/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020149 * xmlSchemaGetFreshElemInfo:
20150 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020151 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020152 * Creates/reuses and initializes the element info item for
20153 * the currect tree depth.
20154 *
20155 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020156 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020157static xmlSchemaNodeInfoPtr
20158xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020159{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020160 xmlSchemaNodeInfoPtr info = NULL;
20161
20162 if (vctxt->depth > vctxt->sizeElemInfos) {
20163 VERROR_INT("xmlSchemaGetFreshElemInfo",
20164 "inconsistent depth encountered");
20165 return (NULL);
20166 }
20167 if (vctxt->elemInfos == NULL) {
20168 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20169 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
20170 if (vctxt->elemInfos == NULL) {
20171 xmlSchemaVErrMemory(vctxt,
20172 "allocating the element info array", NULL);
20173 return (NULL);
20174 }
20175 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
20176 vctxt->sizeElemInfos = 10;
20177 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
20178 int i = vctxt->sizeElemInfos;
20179
20180 vctxt->sizeElemInfos *= 2;
20181 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20182 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
20183 sizeof(xmlSchemaNodeInfoPtr));
20184 if (vctxt->elemInfos == NULL) {
20185 xmlSchemaVErrMemory(vctxt,
20186 "re-allocating the element info array", NULL);
20187 return (NULL);
20188 }
20189 /*
20190 * We need the new memory to be NULLed.
20191 * TODO: Use memset instead?
20192 */
20193 for (; i < vctxt->sizeElemInfos; i++)
20194 vctxt->elemInfos[i] = NULL;
20195 } else
20196 info = vctxt->elemInfos[vctxt->depth];
20197
20198 if (info == NULL) {
20199 info = (xmlSchemaNodeInfoPtr)
20200 xmlMalloc(sizeof(xmlSchemaNodeInfo));
20201 if (info == NULL) {
20202 xmlSchemaVErrMemory(vctxt,
20203 "allocating an element info", NULL);
20204 return (NULL);
20205 }
20206 vctxt->elemInfos[vctxt->depth] = info;
20207 } else {
20208 if (info->localName != NULL) {
20209 VERROR_INT("xmlSchemaGetFreshElemInfo",
20210 "elem info has not been cleared");
20211 return (NULL);
20212 }
20213 }
20214 memset(info, 0, sizeof(xmlSchemaNodeInfo));
20215 info->nodeType = XML_ELEMENT_NODE;
20216 info->depth = vctxt->depth;
20217
20218 return (info);
20219}
20220
20221#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
20222#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
20223#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
20224
20225static int
20226xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
20227 xmlNodePtr node,
20228 xmlSchemaTypePtr type,
20229 xmlSchemaValType valType,
20230 const xmlChar * value,
20231 xmlSchemaValPtr val,
20232 unsigned long length,
20233 int fireErrors)
20234{
20235 int ret, error = 0;
20236
20237 xmlSchemaTypePtr tmpType;
20238 xmlSchemaFacetLinkPtr facetLink;
20239 xmlSchemaFacetPtr facet;
20240 unsigned long len = 0;
20241 xmlSchemaWhitespaceValueType ws;
20242
20243 /*
20244 * In Libxml2, derived built-in types have currently no explicit facets.
20245 */
20246 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020247 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020248
20249 /*
20250 * NOTE: Do not jump away, if the facetSet of the given type is
20251 * empty: until now, "pattern" and "enumeration" facets of the
20252 * *base types* need to be checked as well.
20253 */
20254 if (type->facetSet == NULL)
20255 goto pattern_and_enum;
20256
20257 if (! VARIETY_ATOMIC(type)) {
20258 if (VARIETY_LIST(type))
20259 goto variety_list;
20260 else
20261 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020262 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020263 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020264 * Whitespace handling is only of importance for string-based
20265 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020266 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020267 tmpType = xmlSchemaGetPrimitiveType(type);
20268 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
20269 IS_ANY_SIMPLE_TYPE(tmpType)) {
20270 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20271 } else
20272 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
20273 /*
20274 * If the value was not computed (for string or
20275 * anySimpleType based types), then use the provided
20276 * type.
20277 */
20278 if (val == NULL)
20279 valType = valType;
20280 else
20281 valType = xmlSchemaGetValType(val);
20282
20283 ret = 0;
20284 for (facetLink = type->facetSet; facetLink != NULL;
20285 facetLink = facetLink->next) {
20286 /*
20287 * Skip the pattern "whiteSpace": it is used to
20288 * format the character content beforehand.
20289 */
20290 switch (facetLink->facet->type) {
20291 case XML_SCHEMA_FACET_WHITESPACE:
20292 case XML_SCHEMA_FACET_PATTERN:
20293 case XML_SCHEMA_FACET_ENUMERATION:
20294 continue;
20295 case XML_SCHEMA_FACET_LENGTH:
20296 case XML_SCHEMA_FACET_MINLENGTH:
20297 case XML_SCHEMA_FACET_MAXLENGTH:
20298 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
20299 valType, value, val, &len, ws);
20300 break;
20301 default:
20302 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
20303 valType, value, val, ws);
20304 break;
20305 }
20306 if (ret < 0) {
20307 AERROR_INT("xmlSchemaValidateFacets",
20308 "validating against a atomic type facet");
20309 return (-1);
20310 } else if (ret > 0) {
20311 if (fireErrors)
20312 xmlSchemaFacetErr(actxt, ret, node,
20313 value, len, type, facetLink->facet, NULL, NULL, NULL);
20314 else
20315 return (ret);
20316 if (error == 0)
20317 error = ret;
20318 }
20319 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020320 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020321
20322variety_list:
20323 if (! VARIETY_LIST(type))
20324 goto pattern_and_enum;
20325 /*
20326 * "length", "minLength" and "maxLength" of list types.
20327 */
20328 ret = 0;
20329 for (facetLink = type->facetSet; facetLink != NULL;
20330 facetLink = facetLink->next) {
20331
20332 switch (facetLink->facet->type) {
20333 case XML_SCHEMA_FACET_LENGTH:
20334 case XML_SCHEMA_FACET_MINLENGTH:
20335 case XML_SCHEMA_FACET_MAXLENGTH:
20336 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
20337 value, length, NULL);
20338 break;
20339 default:
20340 continue;
20341 }
20342 if (ret < 0) {
20343 AERROR_INT("xmlSchemaValidateFacets",
20344 "validating against a list type facet");
20345 return (-1);
20346 } else if (ret > 0) {
20347 if (fireErrors)
20348 xmlSchemaFacetErr(actxt, ret, node,
20349 value, length, type, facetLink->facet, NULL, NULL, NULL);
20350 else
20351 return (ret);
20352 if (error == 0)
20353 error = ret;
20354 }
20355 ret = 0;
20356 }
20357
20358pattern_and_enum:
20359 if (error >= 0) {
20360 int found = 0;
20361 /*
20362 * Process enumerations. Facet values are in the value space
20363 * of the defining type's base type. This seems to be a bug in the
20364 * XML Schema 1.0 spec. Use the whitespace type of the base type.
20365 * Only the first set of enumerations in the ancestor-or-self axis
20366 * is used for validation.
20367 */
20368 ret = 0;
20369 tmpType = type;
20370 do {
20371 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
20372 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
20373 continue;
20374 found = 1;
20375 ret = xmlSchemaAreValuesEqual(facet->val, val);
20376 if (ret == 1)
20377 break;
20378 else if (ret < 0) {
20379 AERROR_INT("xmlSchemaValidateFacets",
20380 "validating against an enumeration facet");
20381 return (-1);
20382 }
20383 }
20384 if (ret != 0)
20385 break;
20386 tmpType = tmpType->baseType;
20387 } while ((tmpType != NULL) &&
20388 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20389 if (found && (ret == 0)) {
20390 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
20391 if (fireErrors) {
20392 xmlSchemaFacetErr(actxt, ret, node,
20393 value, 0, type, NULL, NULL, NULL, NULL);
20394 } else
20395 return (ret);
20396 if (error == 0)
20397 error = ret;
20398 }
20399 }
20400
20401 if (error >= 0) {
20402 int found;
20403 /*
20404 * Process patters. Pattern facets are ORed at type level
20405 * and ANDed if derived. Walk the base type axis.
20406 */
20407 tmpType = type;
20408 facet = NULL;
20409 do {
20410 found = 0;
20411 for (facetLink = tmpType->facetSet; facetLink != NULL;
20412 facetLink = facetLink->next) {
20413 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
20414 continue;
20415 found = 1;
20416 /*
20417 * NOTE that for patterns, @value needs to be the
20418 * normalized vaule.
20419 */
20420 ret = xmlRegexpExec(facetLink->facet->regexp, value);
20421 if (ret == 1)
20422 break;
20423 else if (ret < 0) {
20424 AERROR_INT("xmlSchemaValidateFacets",
20425 "validating against a pattern facet");
20426 return (-1);
20427 } else {
20428 /*
20429 * Save the last non-validating facet.
20430 */
20431 facet = facetLink->facet;
20432 }
20433 }
20434 if (found && (ret != 1)) {
20435 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
20436 if (fireErrors) {
20437 xmlSchemaFacetErr(actxt, ret, node,
20438 value, 0, type, facet, NULL, NULL, NULL);
20439 } else
20440 return (ret);
20441 if (error == 0)
20442 error = ret;
20443 break;
20444 }
20445 tmpType = tmpType->baseType;
20446 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20447 }
20448
20449 return (error);
20450}
20451
20452static xmlChar *
20453xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
20454 const xmlChar *value)
20455{
20456 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
20457 case XML_SCHEMA_WHITESPACE_COLLAPSE:
20458 return (xmlSchemaCollapseString(value));
20459 case XML_SCHEMA_WHITESPACE_REPLACE:
20460 return (xmlSchemaWhiteSpaceReplace(value));
20461 default:
20462 return (NULL);
20463 }
20464}
20465
20466static int
20467xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
20468 const xmlChar *value,
20469 xmlSchemaValPtr *val,
20470 int valNeeded)
20471{
20472 int ret;
20473 const xmlChar *nsName;
20474 xmlChar *local, *prefix = NULL;
20475
20476 ret = xmlValidateQName(value, 1);
20477 if (ret != 0) {
20478 if (ret == -1) {
20479 VERROR_INT("xmlSchemaValidateQName",
20480 "calling xmlValidateQName()");
20481 return (-1);
20482 }
20483 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
20484 }
20485 /*
20486 * NOTE: xmlSplitQName2 will always return a duplicated
20487 * strings.
20488 */
20489 local = xmlSplitQName2(value, &prefix);
20490 if (local == NULL)
20491 local = xmlStrdup(value);
20492 /*
20493 * OPTIMIZE TODO: Use flags for:
20494 * - is there any namespace binding?
20495 * - is there a default namespace?
20496 */
20497 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20498
20499 if (prefix != NULL) {
20500 xmlFree(prefix);
20501 /*
20502 * A namespace must be found if the prefix is
20503 * NOT NULL.
20504 */
20505 if (nsName == NULL) {
20506 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20507 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
20508 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20509 "The QName value '%s' has no "
20510 "corresponding namespace declaration in "
20511 "scope", value, NULL);
20512 if (local != NULL)
20513 xmlFree(local);
20514 return (ret);
20515 }
20516 }
20517 if (valNeeded && val) {
20518 if (nsName != NULL)
20519 *val = xmlSchemaNewQNameValue(
20520 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
20521 else
20522 *val = xmlSchemaNewQNameValue(NULL,
20523 BAD_CAST local);
20524 } else
20525 xmlFree(local);
20526 return (0);
20527}
20528
20529/*
20530* cvc-simple-type
20531*/
20532static int
20533xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
20534 xmlNodePtr node,
20535 xmlSchemaTypePtr type,
20536 const xmlChar *value,
20537 xmlSchemaValPtr *retVal,
20538 int fireErrors,
20539 int normalize,
20540 int isNormalized)
20541{
20542 int ret = 0, valNeeded = (retVal) ? 1 : 0;
20543 xmlSchemaValPtr val = NULL;
20544 xmlSchemaWhitespaceValueType ws;
20545 xmlChar *normValue = NULL;
20546
20547#define NORMALIZE(atype) \
20548 if ((! isNormalized) && \
20549 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
20550 normValue = xmlSchemaNormalizeValue(atype, value); \
20551 if (normValue != NULL) \
20552 value = normValue; \
20553 isNormalized = 1; \
20554 }
20555
20556 if ((retVal != NULL) && (*retVal != NULL)) {
20557 xmlSchemaFreeValue(*retVal);
20558 *retVal = NULL;
20559 }
20560 /*
20561 * 3.14.4 Simple Type Definition Validation Rules
20562 * Validation Rule: String Valid
20563 */
20564 /*
20565 * 1 It is schema-valid with respect to that definition as defined
20566 * by Datatype Valid in [XML Schemas: Datatypes].
20567 */
20568 /*
20569 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
20570 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
20571 * the string must be a ·declared entity name·.
20572 */
20573 /*
20574 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
20575 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
20576 * then every whitespace-delimited substring of the string must be a ·declared
20577 * entity name·.
20578 */
20579 /*
20580 * 2.3 otherwise no further condition applies.
20581 */
20582 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
20583 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020584 if (value == NULL)
20585 value = BAD_CAST "";
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020586 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
20587 xmlSchemaTypePtr biType; /* The built-in type. */
20588 /*
20589 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
20590 * a literal in the ·lexical space· of {base type definition}"
20591 */
20592 /*
20593 * Whitespace-normalize.
20594 */
20595 NORMALIZE(type);
20596 if (type->type != XML_SCHEMA_TYPE_BASIC) {
20597 /*
20598 * Get the built-in type.
20599 */
20600 biType = type->baseType;
20601 while ((biType != NULL) &&
20602 (biType->type != XML_SCHEMA_TYPE_BASIC))
20603 biType = biType->baseType;
20604
20605 if (biType == NULL) {
20606 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20607 "could not get the built-in type");
20608 goto internal_error;
20609 }
20610 } else
20611 biType = type;
20612 /*
20613 * NOTATIONs need to be processed here, since they need
20614 * to lookup in the hashtable of NOTATION declarations of the schema.
20615 */
20616 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
20617 switch (biType->builtInType) {
20618 case XML_SCHEMAS_NOTATION:
20619 ret = xmlSchemaValidateNotation(
20620 (xmlSchemaValidCtxtPtr) actxt,
20621 ((xmlSchemaValidCtxtPtr) actxt)->schema,
20622 NULL, value, &val, valNeeded);
20623 break;
20624 case XML_SCHEMAS_QNAME:
20625 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
20626 value, &val, valNeeded);
20627 break;
20628 default:
20629 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20630 if (valNeeded)
20631 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20632 value, &val, NULL);
20633 else
20634 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20635 value, NULL, NULL);
20636 break;
20637 }
20638 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
20639 switch (biType->builtInType) {
20640 case XML_SCHEMAS_NOTATION:
20641 ret = xmlSchemaValidateNotation(NULL,
20642 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
20643 value, &val, valNeeded);
20644 break;
20645 default:
20646 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20647 if (valNeeded)
20648 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20649 value, &val, node);
20650 else
20651 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20652 value, NULL, node);
20653 break;
20654 }
20655 } else {
20656 /*
20657 * Validation via a public API is not implemented yet.
20658 */
20659 TODO
20660 goto internal_error;
20661 }
20662 if (ret != 0) {
20663 if (ret < 0) {
20664 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20665 "validating against a built-in type");
20666 goto internal_error;
20667 }
20668 if (VARIETY_LIST(type))
20669 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20670 else
20671 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20672 }
20673 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20674 /*
20675 * Check facets.
20676 */
20677 ret = xmlSchemaValidateFacets(actxt, node, type,
20678 (xmlSchemaValType) biType->builtInType, value, val,
20679 0, fireErrors);
20680 if (ret != 0) {
20681 if (ret < 0) {
20682 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20683 "validating facets of atomic simple type");
20684 goto internal_error;
20685 }
20686 if (VARIETY_LIST(type))
20687 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20688 else
20689 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20690 }
20691 }
20692 if (fireErrors && (ret > 0))
20693 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20694 } else if (VARIETY_LIST(type)) {
20695
20696 xmlSchemaTypePtr itemType;
20697 const xmlChar *cur, *end;
20698 xmlChar *tmpValue = NULL;
20699 unsigned long len = 0;
20700 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
20701 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
20702 * of white space separated tokens, each of which ·match·es a literal
20703 * in the ·lexical space· of {item type definition}
20704 */
20705 /*
20706 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
20707 * the list type has an enum or pattern facet.
20708 */
20709 NORMALIZE(type);
20710 /*
20711 * VAL TODO: Optimize validation of empty values.
20712 * VAL TODO: We do not have computed values for lists.
20713 */
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020714 itemType = GET_LIST_ITEM_TYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020715 cur = value;
20716 do {
20717 while (IS_BLANK_CH(*cur))
20718 cur++;
20719 end = cur;
20720 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
20721 end++;
20722 if (end == cur)
20723 break;
20724 tmpValue = xmlStrndup(cur, end - cur);
20725 len++;
20726
20727 if (valNeeded)
20728 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20729 tmpValue, &curVal, fireErrors, 0, 1);
20730 else
20731 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20732 tmpValue, NULL, fireErrors, 0, 1);
20733 FREE_AND_NULL(tmpValue);
20734 if (curVal != NULL) {
20735 /*
20736 * Add to list of computed values.
20737 */
20738 if (val == NULL)
20739 val = curVal;
20740 else
20741 xmlSchemaValueAppend(prevVal, curVal);
20742 prevVal = curVal;
20743 curVal = NULL;
20744 }
20745 if (ret != 0) {
20746 if (ret < 0) {
20747 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20748 "validating an item of list simple type");
20749 goto internal_error;
20750 }
20751 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20752 break;
20753 }
20754 cur = end;
20755 } while (*cur != 0);
20756 FREE_AND_NULL(tmpValue);
20757 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20758 /*
20759 * Apply facets (pattern, enumeration).
20760 */
20761 ret = xmlSchemaValidateFacets(actxt, node, type,
20762 XML_SCHEMAS_UNKNOWN, value, val,
20763 len, fireErrors);
20764 if (ret != 0) {
20765 if (ret < 0) {
20766 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20767 "validating facets of list simple type");
20768 goto internal_error;
20769 }
20770 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20771 }
20772 }
20773 if (fireErrors && (ret > 0)) {
20774 /*
20775 * Report the normalized value.
20776 */
20777 normalize = 1;
20778 NORMALIZE(type);
20779 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20780 }
20781 } else if (VARIETY_UNION(type)) {
20782 xmlSchemaTypeLinkPtr memberLink;
20783 /*
20784 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
20785 * not apply directly; however, the normalization behavior of ·union·
20786 * types is controlled by the value of whiteSpace on that one of the
20787 * ·memberTypes· against which the ·union· is successfully validated.
20788 *
20789 * This means that the value is normalized by the first validating
20790 * member type, then the facets of the union type are applied. This
20791 * needs changing of the value!
20792 */
20793
20794 /*
20795 * 1.2.3 if {variety} is ·union· then the string must ·match· a
20796 * literal in the ·lexical space· of at least one member of
20797 * {member type definitions}
20798 */
20799 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
20800 if (memberLink == NULL) {
20801 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20802 "union simple type has no member types");
20803 goto internal_error;
20804 }
20805 /*
20806 * Always normalize union type values, since we currently
20807 * cannot store the whitespace information with the value
20808 * itself; otherwise a later value-comparison would be
20809 * not possible.
20810 */
20811 while (memberLink != NULL) {
20812 if (valNeeded)
20813 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20814 memberLink->type, value, &val, 0, 1, 0);
20815 else
20816 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20817 memberLink->type, value, NULL, 0, 1, 0);
20818 if (ret <= 0)
20819 break;
20820 memberLink = memberLink->next;
20821 }
20822 if (ret != 0) {
20823 if (ret < 0) {
20824 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20825 "validating members of union simple type");
20826 goto internal_error;
20827 }
20828 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20829 }
20830 /*
20831 * Apply facets (pattern, enumeration).
20832 */
20833 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20834 /*
20835 * The normalization behavior of ·union· types is controlled by
20836 * the value of whiteSpace on that one of the ·memberTypes·
20837 * against which the ·union· is successfully validated.
20838 */
20839 NORMALIZE(memberLink->type);
20840 ret = xmlSchemaValidateFacets(actxt, node, type,
20841 XML_SCHEMAS_UNKNOWN, value, val,
20842 0, fireErrors);
20843 if (ret != 0) {
20844 if (ret < 0) {
20845 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20846 "validating facets of union simple type");
20847 goto internal_error;
20848 }
20849 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20850 }
20851 }
20852 if (fireErrors && (ret > 0))
20853 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20854 }
20855
20856 if (normValue != NULL)
20857 xmlFree(normValue);
20858 if (ret == 0) {
20859 if (retVal != NULL)
20860 *retVal = val;
20861 else if (val != NULL)
20862 xmlSchemaFreeValue(val);
20863 } else if (val != NULL)
20864 xmlSchemaFreeValue(val);
20865 return (ret);
20866internal_error:
20867 if (normValue != NULL)
20868 xmlFree(normValue);
20869 if (val != NULL)
20870 xmlSchemaFreeValue(val);
20871 return (-1);
20872}
20873
20874static int
20875xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
20876 const xmlChar *value,
20877 const xmlChar **nsName,
20878 const xmlChar **localName)
20879{
20880 int ret = 0;
20881
20882 if ((nsName == NULL) || (localName == NULL))
20883 return (-1);
20884 *nsName = NULL;
20885 *localName = NULL;
20886
20887 ret = xmlValidateQName(value, 1);
20888 if (ret == -1)
20889 return (-1);
20890 if (ret > 0) {
20891 xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
20892 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20893 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
20894 return (1);
20895 }
20896 {
20897 xmlChar *local = NULL;
20898 xmlChar *prefix;
20899
20900 /*
20901 * NOTE: xmlSplitQName2 will return a duplicated
20902 * string.
20903 */
20904 local = xmlSplitQName2(value, &prefix);
20905 VAL_CREATE_DICT;
20906 if (local == NULL)
20907 *localName = xmlDictLookup(vctxt->dict, value, -1);
20908 else {
20909 *localName = xmlDictLookup(vctxt->dict, local, -1);
20910 xmlFree(local);
20911 }
20912
20913 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20914
20915 if (prefix != NULL) {
20916 xmlFree(prefix);
20917 /*
20918 * A namespace must be found if the prefix is NOT NULL.
20919 */
20920 if (*nsName == NULL) {
20921 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20922 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20923 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20924 "The QName value '%s' has no "
20925 "corresponding namespace declaration in scope",
20926 value, NULL);
20927 return (2);
20928 }
20929 }
20930 }
20931 return (0);
20932}
20933
20934static int
20935xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
20936 xmlSchemaAttrInfoPtr iattr,
20937 xmlSchemaTypePtr *localType,
20938 xmlSchemaElementPtr elemDecl)
20939{
20940 int ret = 0;
20941 /*
20942 * cvc-elt (3.3.4) : (4)
20943 * AND
20944 * Schema-Validity Assessment (Element) (cvc-assess-elt)
20945 * (1.2.1.2.1) - (1.2.1.2.4)
20946 * Handle 'xsi:type'.
20947 */
20948 if (localType == NULL)
20949 return (-1);
20950 *localType = NULL;
20951 if (iattr == NULL)
20952 return (0);
20953 else {
20954 const xmlChar *nsName = NULL, *local = NULL;
20955 /*
20956 * TODO: We should report a *warning* that the type was overriden
20957 * by the instance.
20958 */
20959 ACTIVATE_ATTRIBUTE(iattr);
20960 /*
20961 * (cvc-elt) (3.3.4) : (4.1)
20962 * (cvc-assess-elt) (1.2.1.2.2)
20963 */
20964 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
20965 &nsName, &local);
20966 if (ret != 0) {
20967 if (ret < 0) {
20968 VERROR_INT("xmlSchemaValidateElementByDeclaration",
20969 "calling xmlSchemaQNameExpand() to validate the "
20970 "attribute 'xsi:type'");
20971 goto internal_error;
20972 }
20973 goto exit;
20974 }
20975 /*
20976 * (cvc-elt) (3.3.4) : (4.2)
20977 * (cvc-assess-elt) (1.2.1.2.3)
20978 */
20979 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
20980 if (*localType == NULL) {
20981 xmlChar *str = NULL;
20982
20983 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20984 XML_SCHEMAV_CVC_ELT_4_2, NULL,
20985 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20986 "The QName value '%s' of the xsi:type attribute does not "
20987 "resolve to a type definition",
20988 xmlSchemaFormatQName(&str, nsName, local), NULL);
20989 FREE_AND_NULL(str);
20990 ret = vctxt->err;
20991 goto exit;
20992 }
20993 if (elemDecl != NULL) {
20994 int set = 0;
20995
20996 /*
20997 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
20998 * "The ·local type definition· must be validly
20999 * derived from the {type definition} given the union of
21000 * the {disallowed substitutions} and the {type definition}'s
21001 * {prohibited substitutions}, as defined in
21002 * Type Derivation OK (Complex) (§3.4.6)
21003 * (if it is a complex type definition),
21004 * or given {disallowed substitutions} as defined in Type
21005 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
21006 * definition)."
21007 *
21008 * {disallowed substitutions}: the "block" on the element decl.
21009 * {prohibited substitutions}: the "block" on the type def.
21010 */
21011 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
21012 (elemDecl->subtypes->flags &
21013 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
21014 set |= SUBSET_EXTENSION;
21015
21016 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
21017 (elemDecl->subtypes->flags &
21018 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
21019 set |= SUBSET_RESTRICTION;
21020
21021 if (xmlSchemaCheckCOSDerivedOK(*localType,
21022 elemDecl->subtypes, set) != 0) {
21023 xmlChar *str = NULL;
21024
21025 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21026 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
21027 "The type definition '%s', specified by xsi:type, is "
21028 "blocked or not validly derived from the type definition "
21029 "of the element declaration",
21030 xmlSchemaFormatQName(&str,
21031 (*localType)->targetNamespace,
21032 (*localType)->name),
21033 NULL);
21034 FREE_AND_NULL(str);
21035 ret = vctxt->err;
21036 *localType = NULL;
21037 }
21038 }
21039 }
21040exit:
21041 ACTIVATE_ELEM;
21042 return (ret);
21043internal_error:
21044 ACTIVATE_ELEM;
21045 return (-1);
21046}
21047
21048static int
21049xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
21050{
21051 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
21052 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
21053
21054 /*
21055 * cvc-elt (3.3.4) : 1
21056 */
21057 if (elemDecl == NULL) {
21058 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
21059 "No matching declaration available");
21060 return (vctxt->err);
21061 }
21062 /*
21063 * cvc-elt (3.3.4) : 2
21064 */
21065 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
21066 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
21067 "The element declaration is abstract");
21068 return (vctxt->err);
21069 }
21070 if (actualType == NULL) {
21071 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21072 "The type definition is absent");
21073 return (XML_SCHEMAV_CVC_TYPE_1);
21074 }
21075 if (vctxt->nbAttrInfos != 0) {
21076 int ret;
21077 xmlSchemaAttrInfoPtr iattr;
21078 /*
21079 * cvc-elt (3.3.4) : 3
21080 * Handle 'xsi:nil'.
21081 */
21082 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21083 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
21084 if (iattr) {
21085 ACTIVATE_ATTRIBUTE(iattr);
21086 /*
21087 * Validate the value.
21088 */
21089 ret = xmlSchemaVCheckCVCSimpleType(
21090 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21091 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
21092 iattr->value, &(iattr->val), 1, 0, 0);
21093 ACTIVATE_ELEM;
21094 if (ret < 0) {
21095 VERROR_INT("xmlSchemaValidateElemDecl",
21096 "calling xmlSchemaVCheckCVCSimpleType() to "
21097 "validate the attribute 'xsi:nil'");
21098 return (-1);
21099 }
21100 if (ret == 0) {
21101 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
21102 /*
21103 * cvc-elt (3.3.4) : 3.1
21104 */
21105 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
21106 "The element is not 'nillable'");
21107 /* Does not return an error on purpose. */
21108 } else {
21109 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
21110 /*
21111 * cvc-elt (3.3.4) : 3.2.2
21112 */
21113 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21114 (elemDecl->value != NULL)) {
21115 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
21116 "The element cannot be 'nilled' because "
21117 "there is a fixed value constraint defined "
21118 "for it");
21119 /* Does not return an error on purpose. */
21120 } else
21121 vctxt->inode->flags |=
21122 XML_SCHEMA_ELEM_INFO_NILLED;
21123 }
21124 }
21125 }
21126 }
21127 /*
21128 * cvc-elt (3.3.4) : 4
21129 * Handle 'xsi:type'.
21130 */
21131 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21132 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21133 if (iattr) {
21134 xmlSchemaTypePtr localType = NULL;
21135
21136 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
21137 elemDecl);
21138 if (ret != 0) {
21139 if (ret == -1) {
21140 VERROR_INT("xmlSchemaValidateElemDecl",
21141 "calling xmlSchemaProcessXSIType() to "
21142 "process the attribute 'xsi:type'");
21143 return (-1);
21144 }
21145 /* Does not return an error on purpose. */
21146 }
21147 if (localType != NULL) {
21148 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
21149 actualType = localType;
21150 }
21151 }
21152 }
21153 /*
21154 * IDC: Register identity-constraint XPath matchers.
21155 */
21156 if ((elemDecl->idcs != NULL) &&
21157 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
21158 return (-1);
21159 /*
21160 * No actual type definition.
21161 */
21162 if (actualType == NULL) {
21163 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21164 "The type definition is absent");
21165 return (XML_SCHEMAV_CVC_TYPE_1);
21166 }
21167 /*
21168 * Remember the actual type definition.
21169 */
21170 vctxt->inode->typeDef = actualType;
21171
21172 return (0);
21173}
21174
21175static int
21176xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
21177{
21178 xmlSchemaAttrInfoPtr iattr;
21179 int ret = 0, i;
21180
21181 /*
21182 * SPEC cvc-type (3.1.1)
21183 * "The attributes of must be empty, excepting those whose namespace
21184 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
21185 * whose local name is one of type, nil, schemaLocation or
21186 * noNamespaceSchemaLocation."
21187 */
21188 if (vctxt->nbAttrInfos == 0)
21189 return (0);
21190 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21191 iattr = vctxt->attrInfos[i];
21192 if (! iattr->metaType) {
21193 ACTIVATE_ATTRIBUTE(iattr)
21194 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21195 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
21196 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
21197 }
21198 }
21199 ACTIVATE_ELEM
21200 return (ret);
21201}
21202
21203/*
21204* Cleanup currently used attribute infos.
21205*/
21206static void
21207xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
21208{
21209 int i;
21210 xmlSchemaAttrInfoPtr attr;
21211
21212 if (vctxt->nbAttrInfos == 0)
21213 return;
21214 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21215 attr = vctxt->attrInfos[i];
21216 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21217 if (attr->localName != NULL)
21218 xmlFree((xmlChar *) attr->localName);
21219 if (attr->nsName != NULL)
21220 xmlFree((xmlChar *) attr->nsName);
21221 }
21222 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21223 if (attr->value != NULL)
21224 xmlFree((xmlChar *) attr->value);
21225 }
21226 if (attr->val != NULL) {
21227 xmlSchemaFreeValue(attr->val);
21228 attr->val = NULL;
21229 }
21230 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
21231 }
21232 vctxt->nbAttrInfos = 0;
21233}
21234
21235/*
21236* 3.4.4 Complex Type Definition Validation Rules
21237* Element Locally Valid (Complex Type) (cvc-complex-type)
21238* 3.2.4 Attribute Declaration Validation Rules
21239* Validation Rule: Attribute Locally Valid (cvc-attribute)
21240* Attribute Locally Valid (Use) (cvc-au)
21241*
21242* Only "assessed" attribute information items will be visible to
21243* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
21244*/
21245static int
21246xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
21247{
21248 xmlSchemaTypePtr type = vctxt->inode->typeDef;
21249 xmlSchemaAttributeLinkPtr attrUseLink;
21250 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
21251 xmlSchemaAttrInfoPtr attr, tmpAttr;
21252 int i, found, nbAttrs;
21253 int xpathRes = 0, res, wildIDs = 0, fixed;
21254
21255 /*
21256 * SPEC (cvc-attribute)
21257 * (1) "The declaration must not be ·absent· (see Missing
21258 * Sub-components (§5.3) for how this can fail to be
21259 * the case)."
21260 * (2) "Its {type definition} must not be absent."
21261 *
21262 * NOTE (1) + (2): This is not handled here, since we currently do not
21263 * allow validation against schemas which have missing sub-components.
21264 *
21265 * SPEC (cvc-complex-type)
21266 * (3) "For each attribute information item in the element information
21267 * item's [attributes] excepting those whose [namespace name] is
21268 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
21269 * [local name] is one of type, nil, schemaLocation or
21270 * noNamespaceSchemaLocation, the appropriate case among the following
21271 * must be true:
21272 *
21273 */
21274 nbAttrs = vctxt->nbAttrInfos;
21275 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
21276 attrUseLink = attrUseLink->next) {
21277
21278 found = 0;
21279 attrUse = attrUseLink->attr;
21280 /*
21281 * VAL TODO: Implement a real "attribute use" component.
21282 */
21283 if (attrUse->refDecl != NULL)
21284 attrDecl = attrUse->refDecl;
21285 else
21286 attrDecl = attrUse;
21287 for (i = 0; i < nbAttrs; i++) {
21288 attr = vctxt->attrInfos[i];
21289 /*
21290 * SPEC (cvc-complex-type) (3)
21291 * Skip meta attributes.
21292 */
21293 if (attr->metaType)
21294 continue;
21295 if (attr->localName[0] != attrDecl->name[0])
21296 continue;
21297 if (!xmlStrEqual(attr->localName, attrDecl->name))
21298 continue;
21299 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
21300 continue;
21301 found = 1;
21302 /*
21303 * SPEC (cvc-complex-type)
21304 * (3.1) "If there is among the {attribute uses} an attribute
21305 * use with an {attribute declaration} whose {name} matches
21306 * the attribute information item's [local name] and whose
21307 * {target namespace} is identical to the attribute information
21308 * item's [namespace name] (where an ·absent· {target namespace}
21309 * is taken to be identical to a [namespace name] with no value),
21310 * then the attribute information must be ·valid· with respect
21311 * to that attribute use as per Attribute Locally Valid (Use)
21312 * (§3.5.4). In this case the {attribute declaration} of that
21313 * attribute use is the ·context-determined declaration· for the
21314 * attribute information item with respect to Schema-Validity
21315 * Assessment (Attribute) (§3.2.4) and
21316 * Assessment Outcome (Attribute) (§3.2.5).
21317 */
21318 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21319 attr->use = attrUse;
21320 /*
21321 * Context-determined declaration.
21322 */
21323 attr->decl = attrDecl;
21324 attr->typeDef = attrDecl->subtypes;
21325 break;
21326 }
21327
21328 if (found)
21329 continue;
21330
21331 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21332 /*
21333 * Handle non-existent, required attributes.
21334 *
21335 * SPEC (cvc-complex-type)
21336 * (4) "The {attribute declaration} of each attribute use in
21337 * the {attribute uses} whose {required} is true matches one
21338 * of the attribute information items in the element information
21339 * item's [attributes] as per clause 3.1 above."
21340 */
21341 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21342 if (tmpAttr == NULL) {
21343 VERROR_INT(
21344 "xmlSchemaVAttributesComplex",
21345 "calling xmlSchemaGetFreshAttrInfo()");
21346 return (-1);
21347 }
21348 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
21349 tmpAttr->use = attrUse;
21350 tmpAttr->decl = attrDecl;
21351 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21352 ((attrUse->defValue != NULL) ||
21353 (attrDecl->defValue != NULL))) {
21354 /*
21355 * Handle non-existent, optional, default/fixed attributes.
21356 */
21357 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21358 if (tmpAttr == NULL) {
21359 VERROR_INT(
21360 "xmlSchemaVAttributesComplex",
21361 "calling xmlSchemaGetFreshAttrInfo()");
21362 return (-1);
21363 }
21364 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
21365 tmpAttr->use = attrUse;
21366 tmpAttr->decl = attrDecl;
21367 tmpAttr->typeDef = attrDecl->subtypes;
21368 tmpAttr->localName = attrDecl->name;
21369 tmpAttr->nsName = attrDecl->targetNamespace;
21370 }
21371 }
21372 if (vctxt->nbAttrInfos == 0)
21373 return (0);
21374 /*
21375 * Validate against the wildcard.
21376 */
21377 if (type->attributeWildcard != NULL) {
21378 /*
21379 * SPEC (cvc-complex-type)
21380 * (3.2.1) "There must be an {attribute wildcard}."
21381 */
21382 for (i = 0; i < nbAttrs; i++) {
21383 attr = vctxt->attrInfos[i];
21384 /*
21385 * SPEC (cvc-complex-type) (3)
21386 * Skip meta attributes.
21387 */
21388 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
21389 continue;
21390 /*
21391 * SPEC (cvc-complex-type)
21392 * (3.2.2) "The attribute information item must be ·valid· with
21393 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
21394 *
21395 * SPEC Item Valid (Wildcard) (cvc-wildcard)
21396 * "... its [namespace name] must be ·valid· with respect to
21397 * the wildcard constraint, as defined in Wildcard allows
21398 * Namespace Name (§3.10.4)."
21399 */
21400 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
21401 attr->nsName)) {
21402 /*
21403 * Handle processContents.
21404 *
21405 * SPEC (cvc-wildcard):
21406 * processContents | context-determined declaration:
21407 * "strict" "mustFind"
21408 * "lax" "none"
21409 * "skip" "skip"
21410 */
21411 if (type->attributeWildcard->processContents ==
21412 XML_SCHEMAS_ANY_SKIP) {
21413 /*
21414 * context-determined declaration = "skip"
21415 *
21416 * SPEC PSVI Assessment Outcome (Attribute)
21417 * [validity] = "notKnown"
21418 * [validation attempted] = "none"
21419 */
21420 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
21421 continue;
21422 }
21423 /*
21424 * Find an attribute declaration.
21425 */
21426 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
21427 attr->localName, attr->nsName);
21428 if (attr->decl != NULL) {
21429 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21430 /*
21431 * SPEC (cvc-complex-type)
21432 * (5) "Let [Definition:] the wild IDs be the set of
21433 * all attribute information item to which clause 3.2
21434 * applied and whose ·validation· resulted in a
21435 * ·context-determined declaration· of mustFind or no
21436 * ·context-determined declaration· at all, and whose
21437 * [local name] and [namespace name] resolve (as
21438 * defined by QName resolution (Instance) (§3.15.4)) to
21439 * an attribute declaration whose {type definition} is
21440 * or is derived from ID. Then all of the following
21441 * must be true:"
21442 */
21443 attr->typeDef = attr->decl->subtypes;
21444 if (xmlSchemaIsDerivedFromBuiltInType(
21445 attr->typeDef, XML_SCHEMAS_ID)) {
21446 /*
21447 * SPEC (5.1) "There must be no more than one
21448 * item in ·wild IDs·."
21449 */
21450 if (wildIDs != 0) {
21451 /* VAL TODO */
21452 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
21453 TODO
21454 continue;
21455 }
21456 wildIDs++;
21457 /*
21458 * SPEC (cvc-complex-type)
21459 * (5.2) "If ·wild IDs· is non-empty, there must not
21460 * be any attribute uses among the {attribute uses}
21461 * whose {attribute declaration}'s {type definition}
21462 * is or is derived from ID."
21463 */
21464 for (attrUseLink = type->attributeUses;
21465 attrUseLink != NULL;
21466 attrUseLink = attrUseLink->next) {
21467 if (xmlSchemaIsDerivedFromBuiltInType(
21468 attrUseLink->attr->subtypes,
21469 XML_SCHEMAS_ID)) {
21470 /* VAL TODO */
21471 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
21472 TODO
21473 }
21474 }
21475 }
21476 } else if (type->attributeWildcard->processContents ==
21477 XML_SCHEMAS_ANY_LAX) {
21478 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
21479 /*
21480 * SPEC PSVI Assessment Outcome (Attribute)
21481 * [validity] = "notKnown"
21482 * [validation attempted] = "none"
21483 */
21484 } else {
21485 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
21486 }
21487 }
21488 }
21489 }
21490
21491
21492 if (vctxt->nbAttrInfos == 0)
21493 return (0);
21494
21495 /*
21496 * Validate values, create default attributes, evaluate IDCs.
21497 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021498 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21499 attr = vctxt->attrInfos[i];
21500 /*
21501 * VAL TODO: Note that we won't try to resolve IDCs to
21502 * "lax" and "skip" validated attributes. Check what to
21503 * do in this case.
21504 */
21505 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
21506 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
21507 continue;
21508 /*
21509 * VAL TODO: What to do if the type definition is missing?
21510 */
21511 if (attr->typeDef == NULL) {
21512 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
21513 continue;
21514 }
21515
21516 ACTIVATE_ATTRIBUTE(attr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021517 fixed = 0;
21518 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021519
21520 if (vctxt->xpathStates != NULL) {
21521 /*
21522 * Evaluate IDCs.
21523 */
21524 xpathRes = xmlSchemaXPathEvaluate(vctxt,
21525 XML_ATTRIBUTE_NODE);
21526 if (xpathRes == -1) {
21527 VERROR_INT("xmlSchemaVAttributesComplex",
21528 "calling xmlSchemaXPathEvaluate()");
21529 goto internal_error;
21530 }
21531 }
21532
21533 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
21534 /*
21535 * Default/fixed attributes.
21536 */
21537 if (xpathRes) {
21538 if (attr->use->defValue == NULL) {
21539 attr->value = (xmlChar *) attr->use->defValue;
21540 attr->val = attr->use->defVal;
21541 } else {
21542 attr->value = (xmlChar *) attr->decl->defValue;
21543 attr->val = attr->decl->defVal;
21544 }
21545 /*
21546 * IDCs will consume the precomputed default value,
21547 * so we need to clone it.
21548 */
21549 if (attr->val == NULL) {
21550 VERROR_INT("xmlSchemaVAttributesComplex",
21551 "default/fixed value on an attribute use was "
21552 "not precomputed");
21553 goto internal_error;
21554 }
21555 attr->val = xmlSchemaCopyValue(attr->val);
21556 if (attr->val == NULL) {
21557 VERROR_INT("xmlSchemaVAttributesComplex",
21558 "calling xmlSchemaCopyValue()");
21559 goto internal_error;
21560 }
21561 }
21562 /*
21563 * PSVI: Add the default attribute to the current element.
21564 * VAL TODO: Should we use the *normalized* value? This currently
21565 * uses the *initial* value.
21566 */
21567 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
21568 (attr->node != NULL) && (attr->node->doc != NULL)) {
21569 xmlChar *normValue;
21570 const xmlChar *value;
21571
21572 value = attr->value;
21573 /*
21574 * Normalize the value.
21575 */
21576 normValue = xmlSchemaNormalizeValue(attr->typeDef,
21577 attr->value);
21578 if (normValue != NULL)
21579 value = BAD_CAST normValue;
21580
21581 if (attr->nsName == NULL) {
21582 if (xmlNewProp(attr->node->parent,
21583 attr->localName, value) == NULL) {
21584 VERROR_INT("xmlSchemaVAttributesComplex",
21585 "callling xmlNewProp()");
21586 if (normValue != NULL)
21587 xmlFree(normValue);
21588 goto internal_error;
21589 }
21590 } else {
21591 xmlNsPtr ns;
21592
21593 ns = xmlSearchNsByHref(attr->node->doc,
21594 attr->node->parent, attr->nsName);
21595 if (ns == NULL) {
21596 xmlChar prefix[12];
21597 int counter = 0;
21598
21599 /*
21600 * Create a namespace declaration on the validation
21601 * root node if no namespace declaration is in scope.
21602 */
21603 do {
21604 snprintf((char *) prefix, 12, "p%d", counter++);
21605 ns = xmlSearchNs(attr->node->doc,
21606 attr->node->parent, BAD_CAST prefix);
21607 if (counter > 1000) {
21608 VERROR_INT(
21609 "xmlSchemaVAttributesComplex",
21610 "could not compute a ns prefix for a "
21611 "default/fixed attribute");
21612 if (normValue != NULL)
21613 xmlFree(normValue);
21614 goto internal_error;
21615 }
21616 } while (ns != NULL);
21617 ns = xmlNewNs(vctxt->validationRoot,
21618 attr->nsName, BAD_CAST prefix);
21619 }
21620 xmlNewNsProp(attr->node->parent, ns,
21621 attr->localName, value);
21622 }
21623 if (normValue != NULL)
21624 xmlFree(normValue);
21625 }
21626 /*
21627 * Go directly to IDC evaluation.
21628 */
21629 goto eval_idcs;
21630 }
21631 /*
21632 * Validate the value.
21633 */
21634 if (vctxt->value != NULL) {
21635 /*
21636 * Free last computed value; just for safety reasons.
21637 */
21638 xmlSchemaFreeValue(vctxt->value);
21639 vctxt->value = NULL;
21640 }
21641 /*
21642 * Note that the attribute *use* can be unavailable, if
21643 * the attribute was a wild attribute.
21644 */
21645 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
21646 ((attr->use != NULL) &&
21647 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
21648 fixed = 1;
21649 else
21650 fixed = 0;
21651 /*
21652 * SPEC (cvc-attribute)
21653 * (3) "The item's ·normalized value· must be locally ·valid·
21654 * with respect to that {type definition} as per
21655 * String Valid (§3.14.4)."
21656 *
21657 * VAL TODO: Do we already have the
21658 * "normalized attribute value" here?
21659 */
21660 if (xpathRes || fixed) {
21661 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
21662 /*
21663 * Request a computed value.
21664 */
21665 res = xmlSchemaVCheckCVCSimpleType(
21666 (xmlSchemaAbstractCtxtPtr) vctxt,
21667 attr->node, attr->typeDef, attr->value, &(attr->val),
21668 1, 1, 0);
21669 } else {
21670 res = xmlSchemaVCheckCVCSimpleType(
21671 (xmlSchemaAbstractCtxtPtr) vctxt,
21672 attr->node, attr->typeDef, attr->value, NULL,
21673 1, 0, 0);
21674 }
21675
21676 if (res != 0) {
21677 if (res == -1) {
21678 VERROR_INT("xmlSchemaVAttributesComplex",
21679 "calling xmlSchemaStreamValidateSimpleTypeValue()");
21680 goto internal_error;
21681 }
21682 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21683 /*
21684 * SPEC PSVI Assessment Outcome (Attribute)
21685 * [validity] = "invalid"
21686 */
21687 goto eval_idcs;
21688 }
21689
21690 if (fixed) {
21691 int ws;
21692 /*
21693 * SPEC Attribute Locally Valid (Use) (cvc-au)
21694 * "For an attribute information item to be·valid·
21695 * with respect to an attribute use its *normalized*
21696 * value· must match the *canonical* lexical
21697 * representation of the attribute use's {value
21698 * constraint}value, if it is present and fixed."
21699 *
21700 * VAL TODO: The requirement for the *canonical* value
21701 * will be removed in XML Schema 1.1.
21702 */
21703 /*
21704 * SPEC Attribute Locally Valid (cvc-attribute)
21705 * (4) "The item's *actual* value· must match the *value* of
21706 * the {value constraint}, if it is present and fixed."
21707 */
21708 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
21709 if (attr->val == NULL) {
21710 /* VAL TODO: A value was not precomputed. */
21711 TODO
21712 goto eval_idcs;
21713 }
21714 if ((attr->use != NULL) &&
21715 (attr->use->defValue != NULL)) {
21716 if (attr->use->defVal == NULL) {
21717 /* VAL TODO: A default value was not precomputed. */
21718 TODO
21719 goto eval_idcs;
21720 }
21721 attr->vcValue = attr->use->defValue;
21722 /*
21723 if (xmlSchemaCompareValuesWhtsp(attr->val,
21724 (xmlSchemaWhitespaceValueType) ws,
21725 attr->use->defVal,
21726 (xmlSchemaWhitespaceValueType) ws) != 0) {
21727 */
21728 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
21729 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21730 } else {
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021731 if (attr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021732 /* VAL TODO: A default value was not precomputed. */
21733 TODO
21734 goto eval_idcs;
21735 }
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021736 attr->vcValue = attr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021737 /*
21738 if (xmlSchemaCompareValuesWhtsp(attr->val,
21739 (xmlSchemaWhitespaceValueType) ws,
21740 attrDecl->defVal,
21741 (xmlSchemaWhitespaceValueType) ws) != 0) {
21742 */
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021743 if (! xmlSchemaAreValuesEqual(attr->val, attr->decl->defVal))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021744 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21745 }
21746 /*
21747 * [validity] = "valid"
21748 */
21749 }
21750eval_idcs:
21751 /*
21752 * Evaluate IDCs.
21753 */
21754 if (xpathRes) {
21755 if (xmlSchemaXPathProcessHistory(vctxt,
21756 vctxt->depth +1) == -1) {
21757 VERROR_INT("xmlSchemaVAttributesComplex",
21758 "calling xmlSchemaXPathEvaluate()");
21759 goto internal_error;
21760 }
21761 }
21762 }
21763
21764 /*
21765 * Report errors.
21766 */
21767 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21768 attr = vctxt->attrInfos[i];
21769 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
21770 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
21771 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
21772 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
21773 continue;
21774 ACTIVATE_ATTRIBUTE(attr);
21775 switch (attr->state) {
21776 case XML_SCHEMAS_ATTR_ERR_MISSING: {
21777 xmlChar *str = NULL;
21778 ACTIVATE_ELEM;
21779 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21780 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
21781 "The attribute '%s' is required but missing",
21782 xmlSchemaFormatQName(&str,
21783 attr->decl->targetNamespace,
21784 attr->decl->name),
21785 NULL);
21786 FREE_AND_NULL(str)
21787 break;
21788 }
21789 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
21790 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
21791 "The type definition is absent");
21792 break;
21793 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
21794 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21795 XML_SCHEMAV_CVC_AU, NULL, NULL,
21796 "The value '%s' does not match the fixed "
21797 "value constraint '%s'",
21798 attr->value, attr->vcValue);
21799 break;
21800 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
21801 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
21802 "No matching global attribute declaration available, but "
21803 "demanded by the strict wildcard");
21804 break;
21805 case XML_SCHEMAS_ATTR_UNKNOWN:
21806 if (attr->metaType)
21807 break;
21808 /*
21809 * MAYBE VAL TODO: One might report different error messages
21810 * for the following errors.
21811 */
21812 if (type->attributeWildcard == NULL) {
21813 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21814 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
21815 } else {
21816 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21817 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
21818 }
21819 break;
21820 default:
21821 break;
21822 }
21823 }
21824
21825 ACTIVATE_ELEM;
21826 return (0);
21827internal_error:
21828 ACTIVATE_ELEM;
21829 return (-1);
21830}
21831
21832static int
21833xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
21834 int *skip)
21835{
21836 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
21837 /*
21838 * The namespace of the element was already identified to be
21839 * matching the wildcard.
21840 */
21841 if ((skip == NULL) || (wild == NULL) ||
21842 (wild->type != XML_SCHEMA_TYPE_ANY)) {
21843 VERROR_INT("xmlSchemaValidateElemWildcard",
21844 "bad arguments");
21845 return (-1);
21846 }
21847 *skip = 0;
21848 if (wild->negNsSet != NULL) {
21849 /*
21850 * URGENT VAL TODO: Fix the content model to reject
21851 * "##other" wildcards.
21852 */
21853 if (xmlSchemaCheckCVCWildcardNamespace(wild,
21854 vctxt->inode->nsName) != 0) {
21855 if ((wild->minOccurs == 1) && (wild->maxOccurs == 1)) {
21856 xmlSchemaNodeInfoPtr pinode = vctxt->elemInfos[vctxt->depth -1];
21857 /*
21858 * VAL TODO: Workaround possible *only* if minOccurs and
21859 * maxOccurs are 1.
21860 */
21861 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
21862 /* VAL TODO: error code? */
21863 XML_SCHEMAV_ELEMENT_CONTENT, NULL,
21864 (xmlSchemaTypePtr) wild,
21865 "This element is not accepted by the wildcard",
21866 0, 0, NULL);
21867 vctxt->skipDepth = vctxt->depth;
21868 if ((pinode->flags &
21869 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0)
21870 pinode->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
21871 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
21872 return (XML_SCHEMAV_ELEMENT_CONTENT);
21873 }
21874 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21875 *skip = 1;
21876 return (0);
21877 }
21878 vctxt->inode->typeDef =
21879 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21880 return (0);
21881 }
21882 }
21883 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21884 /*
21885 * URGENT VAL TODO: Either we need to position the stream to the
21886 * next sibling, or walk the whole subtree.
21887 */
21888 *skip = 1;
21889 return (0);
21890 }
21891 {
21892 xmlSchemaElementPtr decl = NULL;
21893
21894 decl = xmlHashLookup3(vctxt->schema->elemDecl,
21895 vctxt->inode->localName, vctxt->inode->nsName,
21896 NULL);
21897 if (decl != NULL) {
21898 vctxt->inode->decl = decl;
21899 return (0);
21900 }
21901 }
21902 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21903 /* VAL TODO: Change to proper error code. */
21904 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
21905 "No matching global element declaration available, but "
21906 "demanded by the strict wildcard");
21907 return (vctxt->err);
21908 }
21909 if (vctxt->nbAttrInfos != 0) {
21910 xmlSchemaAttrInfoPtr iattr;
21911 /*
21912 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21913 * (1.2.1.2.1) - (1.2.1.2.3 )
21914 *
21915 * Use the xsi:type attribute for the type definition.
21916 */
21917 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21918 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21919 if (iattr != NULL) {
21920 if (xmlSchemaProcessXSIType(vctxt, iattr,
21921 &(vctxt->inode->typeDef), NULL) == -1) {
21922 VERROR_INT("xmlSchemaValidateElemWildcard",
21923 "calling xmlSchemaProcessXSIType() to "
21924 "process the attribute 'xsi:nil'");
21925 return (-1);
21926 }
21927 /*
21928 * Don't return an error on purpose.
21929 */
21930 return (0);
21931 }
21932 }
21933 /*
21934 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21935 *
21936 * Fallback to "anyType".
21937 */
21938 vctxt->inode->typeDef =
21939 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21940 return (0);
21941}
21942
21943/*
21944* xmlSchemaCheckCOSValidDefault:
21945*
21946* This will be called if: not nilled, no content and a default/fixed
21947* value is provided.
21948*/
21949
21950static int
21951xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
21952 const xmlChar *value,
21953 xmlSchemaValPtr *val)
21954{
21955 int ret = 0;
21956 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21957
21958 /*
21959 * cos-valid-default:
21960 * Schema Component Constraint: Element Default Valid (Immediate)
21961 * For a string to be a valid default with respect to a type
21962 * definition the appropriate case among the following must be true:
21963 */
21964 if IS_COMPLEX_TYPE(inode->typeDef) {
21965 /*
21966 * Complex type.
21967 *
21968 * SPEC (2.1) "its {content type} must be a simple type definition
21969 * or mixed."
21970 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
21971 * type}'s particle must be ·emptiable· as defined by
21972 * Particle Emptiable (§3.9.6)."
21973 */
21974 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
21975 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
21976 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
21977 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
21978 /* NOTE that this covers (2.2.2) as well. */
21979 VERROR(ret, NULL,
21980 "For a string to be a valid default, the type definition "
21981 "must be a simple type or a complex type with simple content "
21982 "or mixed content and a particle emptiable");
21983 return(ret);
21984 }
21985 }
21986 /*
21987 * 1 If the type definition is a simple type definition, then the string
21988 * must be ·valid· with respect to that definition as defined by String
21989 * Valid (§3.14.4).
21990 *
21991 * AND
21992 *
21993 * 2.2.1 If the {content type} is a simple type definition, then the
21994 * string must be ·valid· with respect to that simple type definition
21995 * as defined by String Valid (§3.14.4).
21996 */
21997 if (IS_SIMPLE_TYPE(inode->typeDef)) {
21998
21999 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22000 NULL, inode->typeDef, value, val, 1, 1, 0);
22001
22002 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22003
22004 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22005 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
22006 }
22007 if (ret < 0) {
22008 VERROR_INT("xmlSchemaCheckCOSValidDefault",
22009 "calling xmlSchemaVCheckCVCSimpleType()");
22010 }
22011 return (ret);
22012}
22013
22014static void
22015xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22016 const xmlChar * name ATTRIBUTE_UNUSED,
22017 xmlSchemaElementPtr item,
22018 xmlSchemaNodeInfoPtr inode)
22019{
22020 inode->decl = item;
22021#ifdef DEBUG_CONTENT
22022 {
22023 xmlChar *str = NULL;
22024
22025 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
22026 xmlGenericError(xmlGenericErrorContext,
22027 "AUTOMATON callback for '%s' [declaration]\n",
22028 xmlSchemaFormatQName(&str,
22029 inode->localName, inode->nsName));
22030 } else {
22031 xmlGenericError(xmlGenericErrorContext,
22032 "AUTOMATON callback for '%s' [wildcard]\n",
22033 xmlSchemaFormatQName(&str,
22034 inode->localName, inode->nsName));
22035
22036 }
22037 FREE_AND_NULL(str)
22038 }
22039#endif
22040}
22041
22042static int
22043xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022044{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022045 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
22046 if (vctxt->inode == NULL) {
22047 VERROR_INT("xmlSchemaValidatorPushElem",
22048 "calling xmlSchemaGetFreshElemInfo()");
22049 return (-1);
22050 }
22051 vctxt->nbAttrInfos = 0;
22052 return (0);
22053}
22054
22055static int
22056xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
22057 xmlSchemaNodeInfoPtr inode,
22058 xmlSchemaTypePtr type,
22059 const xmlChar *value)
22060{
22061 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
22062 return (xmlSchemaVCheckCVCSimpleType(
22063 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22064 type, value, &(inode->val), 1, 1, 0));
22065 else
22066 return (xmlSchemaVCheckCVCSimpleType(
22067 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22068 type, value, NULL, 1, 0, 0));
22069}
22070
22071
22072
22073/*
22074* Process END of element.
22075*/
22076static int
22077xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
22078{
22079 int ret = 0;
22080 xmlSchemaNodeInfoPtr inode = vctxt->inode;
22081
22082 if (vctxt->nbAttrInfos != 0)
22083 xmlSchemaClearAttrInfos(vctxt);
22084 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
22085 /*
22086 * This element was not expected;
22087 * we will not validate child elements of broken parents.
22088 * Skip validation of all content of the parent.
22089 */
22090 vctxt->skipDepth = vctxt->depth -1;
22091 goto end_elem;
22092 }
22093 if ((inode->typeDef == NULL) ||
22094 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
22095 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022096 * 1. the type definition might be missing if the element was
22097 * error prone
22098 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022099 */
22100 goto end_elem;
22101 }
22102 /*
22103 * Check the content model.
22104 */
22105 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
22106 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
22107
22108 /*
22109 * Workaround for "anyType".
22110 */
22111 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
22112 goto character_content;
22113
22114 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
22115 xmlChar *values[10];
22116 int terminal, nbval = 10, nbneg;
22117
22118 if (inode->regexCtxt == NULL) {
22119 /*
22120 * Create the regex context.
22121 */
22122 inode->regexCtxt =
22123 xmlRegNewExecCtxt(inode->typeDef->contModel,
22124 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22125 vctxt);
22126 if (inode->regexCtxt == NULL) {
22127 VERROR_INT("xmlSchemaValidatorPopElem",
22128 "failed to create a regex context");
22129 goto internal_error;
22130 }
22131#ifdef DEBUG_AUTOMATA
22132 xmlGenericError(xmlGenericErrorContext,
22133 "AUTOMATON create on '%s'\n", inode->localName);
22134#endif
22135 }
22136 /*
22137 * Get hold of the still expected content, since a further
22138 * call to xmlRegExecPushString() will loose this information.
22139 */
22140 xmlRegExecNextValues(inode->regexCtxt,
22141 &nbval, &nbneg, &values[0], &terminal);
22142 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
22143 if (ret <= 0) {
22144 /*
22145 * Still missing something.
22146 */
22147 ret = 1;
22148 inode->flags |=
22149 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22150 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22151 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
22152 "Missing child element(s)",
22153 nbval, nbneg, values);
22154#ifdef DEBUG_AUTOMATA
22155 xmlGenericError(xmlGenericErrorContext,
22156 "AUTOMATON missing ERROR on '%s'\n",
22157 inode->localName);
22158#endif
22159 } else {
22160 /*
22161 * Content model is satisfied.
22162 */
22163 ret = 0;
22164#ifdef DEBUG_AUTOMATA
22165 xmlGenericError(xmlGenericErrorContext,
22166 "AUTOMATON succeeded on '%s'\n",
22167 inode->localName);
22168#endif
22169 }
22170
22171 }
22172 }
22173 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
22174 goto end_elem;
22175
22176character_content:
22177
22178 if (vctxt->value != NULL) {
22179 xmlSchemaFreeValue(vctxt->value);
22180 vctxt->value = NULL;
22181 }
22182 /*
22183 * Check character content.
22184 */
22185 if (inode->decl == NULL) {
22186 /*
22187 * Speedup if no declaration exists.
22188 */
22189 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22190 ret = xmlSchemaVCheckINodeDataType(vctxt,
22191 inode, inode->typeDef, inode->value);
22192 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22193 ret = xmlSchemaVCheckINodeDataType(vctxt,
22194 inode, inode->typeDef->contentTypeDef,
22195 inode->value);
22196 }
22197 if (ret < 0) {
22198 VERROR_INT("xmlSchemaValidatorPopElem",
22199 "calling xmlSchemaVCheckCVCSimpleType()");
22200 goto internal_error;
22201 }
22202 goto end_elem;
22203 }
22204 /*
22205 * cvc-elt (3.3.4) : 5
22206 * The appropriate case among the following must be true:
22207 */
22208 /*
22209 * cvc-elt (3.3.4) : 5.1
22210 * If the declaration has a {value constraint},
22211 * the item has neither element nor character [children] and
22212 * clause 3.2 has not applied, then all of the following must be true:
22213 */
22214 if ((inode->decl->value != NULL) &&
22215 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
22216 (! INODE_NILLED(inode))) {
22217 /*
22218 * cvc-elt (3.3.4) : 5.1.1
22219 * If the ·actual type definition· is a ·local type definition·
22220 * then the canonical lexical representation of the {value constraint}
22221 * value must be a valid default for the ·actual type definition· as
22222 * defined in Element Default Valid (Immediate) (§3.3.6).
22223 */
22224 /*
22225 * NOTE: 'local' above means types aquired by xsi:type.
22226 * NOTE: Although the *canonical* value is stated, it is not
22227 * relevant if canonical or not. Additionally XML Schema 1.1
22228 * will removed this requirement as well.
22229 */
22230 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
22231
22232 ret = xmlSchemaCheckCOSValidDefault(vctxt,
22233 inode->decl->value, &(inode->val));
22234 if (ret != 0) {
22235 if (ret < 0) {
22236 VERROR_INT("xmlSchemaValidatorPopElem",
22237 "calling xmlSchemaCheckCOSValidDefault()");
22238 goto internal_error;
22239 }
22240 goto end_elem;
22241 }
22242 /*
22243 * Stop here, to avoid redundant validation of the value
22244 * (see following).
22245 */
22246 goto default_psvi;
22247 }
22248 /*
22249 * cvc-elt (3.3.4) : 5.1.2
22250 * The element information item with the canonical lexical
22251 * representation of the {value constraint} value used as its
22252 * ·normalized value· must be ·valid· with respect to the
22253 * ·actual type definition· as defined by Element Locally Valid (Type)
22254 * (§3.3.4).
22255 */
22256 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22257 ret = xmlSchemaVCheckINodeDataType(vctxt,
22258 inode, inode->typeDef, inode->decl->value);
22259 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22260 ret = xmlSchemaVCheckINodeDataType(vctxt,
22261 inode, inode->typeDef->contentTypeDef,
22262 inode->decl->value);
22263 }
22264 if (ret != 0) {
22265 if (ret < 0) {
22266 VERROR_INT("xmlSchemaValidatorPopElem",
22267 "calling xmlSchemaVCheckCVCSimpleType()");
22268 goto internal_error;
22269 }
22270 goto end_elem;
22271 }
22272
22273default_psvi:
22274 /*
22275 * PSVI: Create a text node on the instance element.
22276 */
22277 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22278 (inode->node != NULL)) {
22279 xmlNodePtr textChild;
22280 xmlChar *normValue;
22281 /*
22282 * VAL TODO: Normalize the value.
22283 */
22284 normValue = xmlSchemaNormalizeValue(inode->typeDef,
22285 inode->decl->value);
22286 if (normValue != NULL) {
22287 textChild = xmlNewText(BAD_CAST normValue);
22288 xmlFree(normValue);
22289 } else
22290 textChild = xmlNewText(inode->decl->value);
22291 if (textChild == NULL) {
22292 VERROR_INT("xmlSchemaValidatorPopElem",
22293 "calling xmlNewText()");
22294 goto internal_error;
22295 } else
22296 xmlAddChild(inode->node, textChild);
22297 }
22298
22299 } else if (! INODE_NILLED(inode)) {
22300 /*
22301 * 5.2.1 The element information item must be ·valid· with respect
22302 * to the ·actual type definition· as defined by Element Locally
22303 * Valid (Type) (§3.3.4).
22304 */
22305 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22306 /*
22307 * SPEC (cvc-type) (3.1)
22308 * "If the type definition is a simple type definition, ..."
22309 * (3.1.3) "If clause 3.2 of Element Locally Valid
22310 * (Element) (§3.3.4) did not apply, then the ·normalized value·
22311 * must be ·valid· with respect to the type definition as defined
22312 * by String Valid (§3.14.4).
22313 */
22314 ret = xmlSchemaVCheckINodeDataType(vctxt,
22315 inode, inode->typeDef, inode->value);
22316 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22317 /*
22318 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
22319 * definition, then the element information item must be
22320 * ·valid· with respect to the type definition as per
22321 * Element Locally Valid (Complex Type) (§3.4.4);"
22322 *
22323 * SPEC (cvc-complex-type) (2.2)
22324 * "If the {content type} is a simple type definition, ...
22325 * the ·normalized value· of the element information item is
22326 * ·valid· with respect to that simple type definition as
22327 * defined by String Valid (§3.14.4)."
22328 */
22329 ret = xmlSchemaVCheckINodeDataType(vctxt,
22330 inode, inode->typeDef->contentTypeDef, inode->value);
22331 }
22332 if (ret != 0) {
22333 if (ret < 0) {
22334 VERROR_INT("xmlSchemaValidatorPopElem",
22335 "calling xmlSchemaVCheckCVCSimpleType()");
22336 goto internal_error;
22337 }
22338 goto end_elem;
22339 }
22340 /*
22341 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
22342 * not applied, all of the following must be true:
22343 */
22344 if ((inode->decl->value != NULL) &&
22345 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
22346
22347 /*
22348 * TODO: We will need a computed value, when comparison is
22349 * done on computed values.
22350 */
22351 /*
22352 * 5.2.2.1 The element information item must have no element
22353 * information item [children].
22354 */
22355 if (inode->flags &
22356 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
22357 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
22358 VERROR(ret, NULL,
22359 "The content must not containt element nodes since "
22360 "there is a fixed value constraint");
22361 goto end_elem;
22362 } else {
22363 /*
22364 * 5.2.2.2 The appropriate case among the following must
22365 * be true:
22366 */
22367 if (HAS_MIXED_CONTENT(inode->typeDef)) {
22368 /*
22369 * 5.2.2.2.1 If the {content type} of the ·actual type
22370 * definition· is mixed, then the *initial value* of the
22371 * item must match the canonical lexical representation
22372 * of the {value constraint} value.
22373 *
22374 * ... the *initial value* of an element information
22375 * item is the string composed of, in order, the
22376 * [character code] of each character information item in
22377 * the [children] of that element information item.
22378 */
22379 if (! xmlStrEqual(inode->value, inode->decl->value)){
22380 /*
22381 * VAL TODO: Report invalid & expected values as well.
22382 * VAL TODO: Implement the canonical stuff.
22383 */
22384 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
22385 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22386 ret, NULL, NULL,
22387 "The initial value '%s' does not match the fixed "
22388 "value constraint '%s'",
22389 inode->value, inode->decl->value);
22390 goto end_elem;
22391 }
22392 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22393 /*
22394 * 5.2.2.2.2 If the {content type} of the ·actual type
22395 * definition· is a simple type definition, then the
22396 * *actual value* of the item must match the canonical
22397 * lexical representation of the {value constraint} value.
22398 */
22399 /*
22400 * VAL TODO: *actual value* is the normalized value, impl.
22401 * this.
22402 * VAL TODO: Report invalid & expected values as well.
22403 * VAL TODO: Implement a comparison with the computed values.
22404 */
22405 if (! xmlStrEqual(inode->value,
22406 inode->decl->value)) {
22407 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
22408 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22409 ret, NULL, NULL,
22410 "The actual value '%s' does not match the fixed "
22411 "value constraint '%s'",
22412 inode->value,
22413 inode->decl->value);
22414 goto end_elem;
22415 }
22416 }
22417 }
22418 }
22419 }
22420
22421end_elem:
22422 if (vctxt->depth < 0) {
22423 /* TODO: raise error? */
22424 return (0);
22425 }
22426 if (vctxt->depth == vctxt->skipDepth)
22427 vctxt->skipDepth = -1;
22428 /*
22429 * Evaluate the history of XPath state objects.
22430 */
22431 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
22432 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022433 /*
22434 * TODO: 6 The element information item must be ·valid· with respect to each of
22435 * the {identity-constraint definitions} as per Identity-constraint
22436 * Satisfied (§3.11.4).
22437 */
22438 /*
22439 * Validate IDC keyrefs.
22440 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022441 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
22442 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022443 /*
22444 * Merge/free the IDC table.
22445 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022446 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022447#ifdef DEBUG_IDC
22448 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022449 inode->nsName,
22450 inode->localName,
22451 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022452#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022453 if (vctxt->depth > 0) {
22454 /*
22455 * Merge the IDC node table with the table of the parent node.
22456 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022457 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
22458 goto internal_error;
22459 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022460 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022461 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022462 * Clear the current ielem.
22463 * VAL TODO: Don't free the PSVI IDC tables if they are
22464 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022465 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022466 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022467 /*
22468 * Skip further processing if we are on the validation root.
22469 */
22470 if (vctxt->depth == 0) {
22471 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022472 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022473 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022474 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022475 /*
22476 * Reset the bubbleDepth if needed.
22477 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022478 if (vctxt->aidcs != NULL) {
22479 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
22480 do {
22481 if (aidc->bubbleDepth == vctxt->depth) {
22482 /*
22483 * A bubbleDepth of a key/unique IDC matches the current
22484 * depth, this means that we are leaving the scope of the
22485 * top-most keyref IDC.
22486 */
22487 aidc->bubbleDepth = -1;
22488 }
22489 aidc = aidc->next;
22490 } while (aidc != NULL);
22491 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022492 vctxt->depth--;
22493 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022494 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022495 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022496 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
22497 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022498 return (ret);
22499
22500internal_error:
22501 vctxt->err = -1;
22502 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022503}
22504
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022505/*
22506* 3.4.4 Complex Type Definition Validation Rules
22507* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
22508*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000022509static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022510xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000022511{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022512 xmlSchemaNodeInfoPtr pielem;
22513 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022514 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022515
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022516 if (vctxt->depth <= 0) {
22517 VERROR_INT("xmlSchemaValidateChildElem",
22518 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022519 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022520 }
22521 pielem = vctxt->elemInfos[vctxt->depth -1];
22522 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
22523 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022524 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022525 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022526 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022527 if (INODE_NILLED(pielem)) {
22528 /*
22529 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
22530 */
22531 ACTIVATE_PARENT_ELEM;
22532 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
22533 VERROR(ret, NULL,
22534 "Neither character nor element content is allowed, "
22535 "because the element was 'nilled'");
22536 ACTIVATE_ELEM;
22537 goto unexpected_elem;
22538 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022539
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022540 ptype = pielem->typeDef;
22541
22542 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
22543 /*
22544 * Workaround for "anyType": we have currently no content model
22545 * assigned for "anyType", so handle it explicitely.
22546 * "anyType" has an unbounded, lax "any" wildcard.
22547 */
22548 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22549 vctxt->inode->localName,
22550 vctxt->inode->nsName);
22551
22552 if (vctxt->inode->decl == NULL) {
22553 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022554 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022555 * Process "xsi:type".
22556 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022557 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022558 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22559 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22560 if (iattr != NULL) {
22561 ret = xmlSchemaProcessXSIType(vctxt, iattr,
22562 &(vctxt->inode->typeDef), NULL);
22563 if (ret != 0) {
22564 if (ret == -1) {
22565 VERROR_INT("xmlSchemaValidateChildElem",
22566 "calling xmlSchemaProcessXSIType() to "
22567 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022568 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022569 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022570 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000022571 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022572 } else {
22573 /*
22574 * Fallback to "anyType".
22575 *
22576 * SPEC (cvc-assess-elt)
22577 * "If the item cannot be ·strictly assessed·, [...]
22578 * an element information item's schema validity may be laxly
22579 * assessed if its ·context-determined declaration· is not
22580 * skip by ·validating· with respect to the ·ur-type
22581 * definition· as per Element Locally Valid (Type) (§3.3.4)."
22582 */
22583 vctxt->inode->typeDef =
22584 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022585 }
22586 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022587 return (0);
22588 }
22589
22590 switch (ptype->contentType) {
22591 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022592 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022593 * SPEC (2.1) "If the {content type} is empty, then the
22594 * element information item has no character or element
22595 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022596 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022597 ACTIVATE_PARENT_ELEM
22598 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
22599 VERROR(ret, NULL,
22600 "Element content is not allowed, "
22601 "because the content type is empty");
22602 ACTIVATE_ELEM
22603 goto unexpected_elem;
22604 break;
22605
22606 case XML_SCHEMA_CONTENT_MIXED:
22607 case XML_SCHEMA_CONTENT_ELEMENTS: {
22608 xmlRegExecCtxtPtr regexCtxt;
22609 xmlChar *values[10];
22610 int terminal, nbval = 10, nbneg;
22611
22612 /* VAL TODO: Optimized "anyType" validation.*/
22613
22614 if (ptype->contModel == NULL) {
22615 VERROR_INT("xmlSchemaValidateChildElem",
22616 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022617 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022618 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022619 /*
22620 * Safety belf for evaluation if the cont. model was already
22621 * examined to be invalid.
22622 */
22623 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
22624 VERROR_INT("xmlSchemaValidateChildElem",
22625 "validating elem, but elem content is already invalid");
22626 return (-1);
22627 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022628
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022629 regexCtxt = pielem->regexCtxt;
22630 if (regexCtxt == NULL) {
22631 /*
22632 * Create the regex context.
22633 */
22634 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
22635 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22636 vctxt);
22637 if (regexCtxt == NULL) {
22638 VERROR_INT("xmlSchemaValidateChildElem",
22639 "failed to create a regex context");
22640 return (-1);
22641 }
22642 pielem->regexCtxt = regexCtxt;
22643#ifdef DEBUG_AUTOMATA
22644 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
22645 pielem->localName);
22646#endif
22647 }
22648
22649 /*
22650 * SPEC (2.4) "If the {content type} is element-only or mixed,
22651 * then the sequence of the element information item's
22652 * element information item [children], if any, taken in
22653 * order, is ·valid· with respect to the {content type}'s
22654 * particle, as defined in Element Sequence Locally Valid
22655 * (Particle) (§3.9.4)."
22656 */
22657 ret = xmlRegExecPushString2(regexCtxt,
22658 vctxt->inode->localName,
22659 vctxt->inode->nsName,
22660 vctxt->inode);
22661#ifdef DEBUG_AUTOMATA
22662 if (ret < 0)
22663 xmlGenericError(xmlGenericErrorContext,
22664 "AUTOMATON push ERROR for '%s' on '%s'\n",
22665 vctxt->inode->localName, pielem->localName);
22666 else
22667 xmlGenericError(xmlGenericErrorContext,
22668 "AUTOMATON push OK for '%s' on '%s'\n",
22669 vctxt->inode->localName, pielem->localName);
22670#endif
22671 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
22672 VERROR_INT("xmlSchemaValidateChildElem",
22673 "calling xmlRegExecPushString2()");
22674 return (-1);
22675 }
22676 if (ret < 0) {
22677 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
22678 &values[0], &terminal);
22679 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22680 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
22681 "This element is not expected",
22682 nbval, nbneg, values);
22683 ret = vctxt->err;
22684 goto unexpected_elem;
22685 } else
22686 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022687 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022688 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022689 case XML_SCHEMA_CONTENT_SIMPLE:
22690 case XML_SCHEMA_CONTENT_BASIC:
22691 ACTIVATE_PARENT_ELEM
22692 if (IS_COMPLEX_TYPE(ptype)) {
22693 /*
22694 * SPEC (cvc-complex-type) (2.2)
22695 * "If the {content type} is a simple type definition, then
22696 * the element information item has no element information
22697 * item [children], ..."
22698 */
22699 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22700 VERROR(ret, NULL, "Element content is not allowed, "
22701 "because the content type is a simple type definition");
22702 } else {
22703 /*
22704 * SPEC (cvc-type) (3.1.2) "The element information item must
22705 * have no element information item [children]."
22706 */
22707 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
22708 VERROR(ret, NULL, "Element content is not allowed, "
22709 "because the type definition is simple");
22710 }
22711 ACTIVATE_ELEM
22712 ret = vctxt->err;
22713 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022714 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022715
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022716 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022717 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022718 }
22719 return (ret);
22720unexpected_elem:
22721 /*
22722 * Pop this element and set the skipDepth to skip
22723 * all further content of the parent element.
22724 */
22725 vctxt->skipDepth = vctxt->depth;
22726 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
22727 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22728 return (ret);
22729}
22730
22731#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
22732#define XML_SCHEMA_PUSH_TEXT_CREATED 2
22733#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
22734
22735static int
22736xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
22737 int nodeType, const xmlChar *value, int len,
22738 int mode, int *consumed)
22739{
22740 /*
22741 * Unfortunately we have to duplicate the text sometimes.
22742 * OPTIMIZE: Maybe we could skip it, if:
22743 * 1. content type is simple
22744 * 2. whitespace is "collapse"
22745 * 3. it consists of whitespace only
22746 *
22747 * Process character content.
22748 */
22749 if (consumed != NULL)
22750 *consumed = 0;
22751 if (INODE_NILLED(vctxt->inode)) {
22752 /*
22753 * SPEC cvc-elt (3.3.4 - 3.2.1)
22754 * "The element information item must have no character or
22755 * element information item [children]."
22756 */
22757 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
22758 "Neither character nor element content is allowed "
22759 "because the element is 'nilled'");
22760 return (vctxt->err);
22761 }
22762 /*
22763 * SPEC (2.1) "If the {content type} is empty, then the
22764 * element information item has no character or element
22765 * information item [children]."
22766 */
22767 if (vctxt->inode->typeDef->contentType ==
22768 XML_SCHEMA_CONTENT_EMPTY) {
22769 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
22770 "Character content is not allowed, "
22771 "because the content type is empty");
22772 return (vctxt->err);
22773 }
22774
22775 if (vctxt->inode->typeDef->contentType ==
22776 XML_SCHEMA_CONTENT_ELEMENTS) {
22777 if ((nodeType != XML_TEXT_NODE) ||
22778 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
22779 /*
22780 * SPEC cvc-complex-type (2.3)
22781 * "If the {content type} is element-only, then the
22782 * element information item has no character information
22783 * item [children] other than those whose [character
22784 * code] is defined as a white space in [XML 1.0 (Second
22785 * Edition)]."
22786 */
22787 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
22788 "Character content other than whitespace is not allowed "
22789 "because the content type is 'element-only'");
22790 return (vctxt->err);
22791 }
22792 return (0);
22793 }
22794
22795 if ((value == NULL) || (value[0] == 0))
22796 return (0);
22797 /*
22798 * Save the value.
22799 * NOTE that even if the content type is *mixed*, we need the
22800 * *initial value* for default/fixed value constraints.
22801 */
22802 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
22803 ((vctxt->inode->decl == NULL) ||
22804 (vctxt->inode->decl->value == NULL)))
22805 return (0);
22806
22807 if (vctxt->inode->value == NULL) {
22808 /*
22809 * Set the value.
22810 */
22811 switch (mode) {
22812 case XML_SCHEMA_PUSH_TEXT_PERSIST:
22813 /*
22814 * When working on a tree.
22815 */
22816 vctxt->inode->value = value;
22817 break;
22818 case XML_SCHEMA_PUSH_TEXT_CREATED:
22819 /*
22820 * When working with the reader.
22821 * The value will be freed by the element info.
22822 */
22823 vctxt->inode->value = value;
22824 if (consumed != NULL)
22825 *consumed = 1;
22826 vctxt->inode->flags |=
22827 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22828 break;
22829 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
22830 /*
22831 * When working with SAX.
22832 * The value will be freed by the element info.
22833 */
22834 if (len != -1)
22835 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
22836 else
22837 vctxt->inode->value = BAD_CAST xmlStrdup(value);
22838 vctxt->inode->flags |=
22839 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22840 break;
22841 default:
22842 break;
22843 }
22844 } else {
22845 /*
22846 * Concat the value.
22847 */
22848 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000022849 vctxt->inode->value = BAD_CAST xmlStrncat(
22850 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022851 } else {
22852 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022853 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022854 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22855 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022856 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022857
22858 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022859}
22860
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022861static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022862xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022863{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022864 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022865
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022866 if ((vctxt->skipDepth != -1) &&
22867 (vctxt->depth >= vctxt->skipDepth)) {
22868 VERROR_INT("xmlSchemaValidateElem",
22869 "in skip-state");
22870 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022871 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022872 if (vctxt->xsiAssemble) {
22873 if (xmlSchemaAssembleByXSI(vctxt) == -1)
22874 goto internal_error;
22875 }
22876 if (vctxt->depth > 0) {
22877 /*
22878 * Validate this element against the content model
22879 * of the parent.
22880 */
22881 ret = xmlSchemaValidateChildElem(vctxt);
22882 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022883 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022884 VERROR_INT("xmlSchemaValidateElem",
22885 "calling xmlSchemaStreamValidateChildElement()");
22886 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022887 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022888 goto exit;
22889 }
22890 if (vctxt->depth == vctxt->skipDepth)
22891 goto exit;
22892 if ((vctxt->inode->decl == NULL) &&
22893 (vctxt->inode->typeDef == NULL)) {
22894 VERROR_INT("xmlSchemaValidateElem",
22895 "the child element was valid but neither the "
22896 "declaration nor the type was set");
22897 goto internal_error;
22898 }
22899 } else {
22900 /*
22901 * Get the declaration of the validation root.
22902 */
22903 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22904 vctxt->inode->localName,
22905 vctxt->inode->nsName);
22906 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022907 ret = XML_SCHEMAV_CVC_ELT_1;
22908 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022909 "No matching global declaration available "
22910 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022911 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022912 }
22913 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022914
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022915 if (vctxt->inode->decl == NULL)
22916 goto type_validation;
22917
22918 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
22919 int skip;
22920 /*
22921 * Wildcards.
22922 */
22923 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
22924 if (ret != 0) {
22925 if (ret < 0) {
22926 VERROR_INT("xmlSchemaValidateElem",
22927 "calling xmlSchemaValidateElemWildcard()");
22928 goto internal_error;
22929 }
22930 goto exit;
22931 }
22932 if (skip) {
22933 vctxt->skipDepth = vctxt->depth;
22934 goto exit;
22935 }
22936 /*
22937 * The declaration might be set by the wildcard validation,
22938 * when the processContents is "lax" or "strict".
22939 */
22940 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
22941 /*
22942 * Clear the "decl" field to not confuse further processing.
22943 */
22944 vctxt->inode->decl = NULL;
22945 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022946 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022947 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022948 /*
22949 * Validate against the declaration.
22950 */
22951 ret = xmlSchemaValidateElemDecl(vctxt);
22952 if (ret != 0) {
22953 if (ret < 0) {
22954 VERROR_INT("xmlSchemaValidateElem",
22955 "calling xmlSchemaValidateElemDecl()");
22956 goto internal_error;
22957 }
22958 goto exit;
22959 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022960 /*
22961 * Validate against the type definition.
22962 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022963type_validation:
22964
22965 if (vctxt->inode->typeDef == NULL) {
22966 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22967 ret = XML_SCHEMAV_CVC_TYPE_1;
22968 VERROR(ret, NULL,
22969 "The type definition is absent");
22970 goto exit;
22971 }
22972 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
22973 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22974 ret = XML_SCHEMAV_CVC_TYPE_2;
22975 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022976 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022977 goto exit;
22978 }
22979 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022980 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022981 * during validation against the declaration. This must be done
22982 * _before_ attribute validation.
22983 */
22984 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
22985 if (ret == -1) {
22986 VERROR_INT("xmlSchemaValidateElem",
22987 "calling xmlSchemaXPathEvaluate()");
22988 goto internal_error;
22989 }
22990 /*
22991 * Validate attributes.
22992 */
22993 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
22994 if ((vctxt->nbAttrInfos != 0) ||
22995 (vctxt->inode->typeDef->attributeUses != NULL)) {
22996
22997 ret = xmlSchemaVAttributesComplex(vctxt);
22998 }
22999 } else if (vctxt->nbAttrInfos != 0) {
23000
23001 ret = xmlSchemaVAttributesSimple(vctxt);
23002 }
23003 /*
23004 * Clear registered attributes.
23005 */
23006 if (vctxt->nbAttrInfos != 0)
23007 xmlSchemaClearAttrInfos(vctxt);
23008 if (ret == -1) {
23009 VERROR_INT("xmlSchemaValidateElem",
23010 "calling attributes validation");
23011 goto internal_error;
23012 }
23013 /*
23014 * Don't return an error if attributes are invalid on purpose.
23015 */
23016 ret = 0;
23017
23018exit:
23019 if (ret != 0)
23020 vctxt->skipDepth = vctxt->depth;
23021 return (ret);
23022internal_error:
23023 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023024}
23025
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023026#ifdef XML_SCHEMA_READER_ENABLED
23027static int
23028xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023029{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023030 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
23031 int depth, nodeType, ret = 0, consumed;
23032 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023033
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023034 vctxt->depth = -1;
23035 ret = xmlTextReaderRead(vctxt->reader);
23036 /*
23037 * Move to the document element.
23038 */
23039 while (ret == 1) {
23040 nodeType = xmlTextReaderNodeType(vctxt->reader);
23041 if (nodeType == XML_ELEMENT_NODE)
23042 goto root_found;
23043 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023044 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023045 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023046
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023047root_found:
23048
23049 do {
23050 depth = xmlTextReaderDepth(vctxt->reader);
23051 nodeType = xmlTextReaderNodeType(vctxt->reader);
23052
23053 if (nodeType == XML_ELEMENT_NODE) {
23054
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023055 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023056 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23057 VERROR_INT("xmlSchemaVReaderWalk",
23058 "calling xmlSchemaValidatorPushElem()");
23059 goto internal_error;
23060 }
23061 ielem = vctxt->inode;
23062 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
23063 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
23064 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23065 /*
23066 * Is the element empty?
23067 */
23068 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
23069 if (ret == -1) {
23070 VERROR_INT("xmlSchemaVReaderWalk",
23071 "calling xmlTextReaderIsEmptyElement()");
23072 goto internal_error;
23073 }
23074 if (ret) {
23075 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23076 }
23077 /*
23078 * Register attributes.
23079 */
23080 vctxt->nbAttrInfos = 0;
23081 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
23082 if (ret == -1) {
23083 VERROR_INT("xmlSchemaVReaderWalk",
23084 "calling xmlTextReaderMoveToFirstAttribute()");
23085 goto internal_error;
23086 }
23087 if (ret == 1) {
23088 do {
23089 /*
23090 * VAL TODO: How do we know that the reader works on a
23091 * node tree, to be able to pass a node here?
23092 */
23093 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
23094 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
23095 xmlTextReaderNamespaceUri(vctxt->reader), 1,
23096 xmlTextReaderValue(vctxt->reader), 1) == -1) {
23097
23098 VERROR_INT("xmlSchemaVReaderWalk",
23099 "calling xmlSchemaValidatorPushAttribute()");
23100 goto internal_error;
23101 }
23102 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
23103 if (ret == -1) {
23104 VERROR_INT("xmlSchemaVReaderWalk",
23105 "calling xmlTextReaderMoveToFirstAttribute()");
23106 goto internal_error;
23107 }
23108 } while (ret == 1);
23109 /*
23110 * Back to element position.
23111 */
23112 ret = xmlTextReaderMoveToElement(vctxt->reader);
23113 if (ret == -1) {
23114 VERROR_INT("xmlSchemaVReaderWalk",
23115 "calling xmlTextReaderMoveToElement()");
23116 goto internal_error;
23117 }
23118 }
23119 /*
23120 * Validate the element.
23121 */
23122 ret= xmlSchemaValidateElem(vctxt);
23123 if (ret != 0) {
23124 if (ret == -1) {
23125 VERROR_INT("xmlSchemaVReaderWalk",
23126 "calling xmlSchemaValidateElem()");
23127 goto internal_error;
23128 }
23129 goto exit;
23130 }
23131 if (vctxt->depth == vctxt->skipDepth) {
23132 int curDepth;
23133 /*
23134 * Skip all content.
23135 */
23136 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
23137 ret = xmlTextReaderRead(vctxt->reader);
23138 curDepth = xmlTextReaderDepth(vctxt->reader);
23139 while ((ret == 1) && (curDepth != depth)) {
23140 ret = xmlTextReaderRead(vctxt->reader);
23141 curDepth = xmlTextReaderDepth(vctxt->reader);
23142 }
23143 if (ret < 0) {
23144 /*
23145 * VAL TODO: A reader error occured; what to do here?
23146 */
23147 ret = 1;
23148 goto exit;
23149 }
23150 }
23151 goto leave_elem;
23152 }
23153 /*
23154 * READER VAL TODO: Is an END_ELEM really never called
23155 * if the elem is empty?
23156 */
23157 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23158 goto leave_elem;
23159 } else if (nodeType == END_ELEM) {
23160 /*
23161 * Process END of element.
23162 */
23163leave_elem:
23164 ret = xmlSchemaValidatorPopElem(vctxt);
23165 if (ret != 0) {
23166 if (ret < 0) {
23167 VERROR_INT("xmlSchemaVReaderWalk",
23168 "calling xmlSchemaValidatorPopElem()");
23169 goto internal_error;
23170 }
23171 goto exit;
23172 }
23173 if (vctxt->depth >= 0)
23174 ielem = vctxt->inode;
23175 else
23176 ielem = NULL;
23177 } else if ((nodeType == XML_TEXT_NODE) ||
23178 (nodeType == XML_CDATA_SECTION_NODE) ||
23179 (nodeType == WHTSP) ||
23180 (nodeType == SIGN_WHTSP)) {
23181 /*
23182 * Process character content.
23183 */
23184 xmlChar *value;
23185
23186 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
23187 nodeType = XML_TEXT_NODE;
23188
23189 value = xmlTextReaderValue(vctxt->reader);
23190 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
23191 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
23192 if (! consumed)
23193 xmlFree(value);
23194 if (ret == -1) {
23195 VERROR_INT("xmlSchemaVReaderWalk",
23196 "calling xmlSchemaVPushText()");
23197 goto internal_error;
23198 }
23199 } else if ((nodeType == XML_ENTITY_NODE) ||
23200 (nodeType == XML_ENTITY_REF_NODE)) {
23201 /*
23202 * VAL TODO: What to do with entities?
23203 */
23204 TODO
23205 }
23206 /*
23207 * Read next node.
23208 */
23209 ret = xmlTextReaderRead(vctxt->reader);
23210 } while (ret == 1);
23211
23212exit:
23213 return (ret);
23214internal_error:
23215 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023216}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023217#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000023218
23219/************************************************************************
23220 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023221 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000023222 * *
23223 ************************************************************************/
23224
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023225#ifdef XML_SCHEMA_SAX_ENABLED
23226/*
23227* Process text content.
23228*/
23229static void
23230xmlSchemaSAXHandleText(void *ctx,
23231 const xmlChar * ch,
23232 int len)
23233{
23234 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23235
23236 if (vctxt->depth < 0)
23237 return;
23238 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23239 return;
23240 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23241 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23242 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
23243 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23244 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23245 "calling xmlSchemaVPushText()");
23246 vctxt->err = -1;
23247 xmlStopParser(vctxt->parserCtxt);
23248 }
23249}
23250
23251/*
23252* Process CDATA content.
23253*/
23254static void
23255xmlSchemaSAXHandleCDataSection(void *ctx,
23256 const xmlChar * ch,
23257 int len)
23258{
23259 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23260
23261 if (vctxt->depth < 0)
23262 return;
23263 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23264 return;
23265 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23266 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23267 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
23268 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23269 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23270 "calling xmlSchemaVPushText()");
23271 vctxt->err = -1;
23272 xmlStopParser(vctxt->parserCtxt);
23273 }
23274}
23275
23276static void
23277xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
23278 const xmlChar * name ATTRIBUTE_UNUSED)
23279{
23280 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23281
23282 if (vctxt->depth < 0)
23283 return;
23284 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23285 return;
23286 /* SAX VAL TODO: What to do here? */
23287 TODO
23288}
23289
23290static void
23291xmlSchemaSAXHandleStartElementNs(void *ctx,
23292 const xmlChar * localname,
23293 const xmlChar * prefix ATTRIBUTE_UNUSED,
23294 const xmlChar * URI,
23295 int nb_namespaces,
23296 const xmlChar ** namespaces,
23297 int nb_attributes,
23298 int nb_defaulted ATTRIBUTE_UNUSED,
23299 const xmlChar ** attributes)
23300{
23301 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23302 int ret;
23303 xmlSchemaNodeInfoPtr ielem;
23304 int i, j;
23305
23306 /*
23307 * SAX VAL TODO: What to do with nb_defaulted?
23308 */
23309 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023310 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023311 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023312 vctxt->depth++;
23313 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023314 return;
23315 /*
23316 * Push the element.
23317 */
23318 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23319 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23320 "calling xmlSchemaValidatorPushElem()");
23321 goto internal_error;
23322 }
23323 ielem = vctxt->inode;
23324 ielem->localName = localname;
23325 ielem->nsName = URI;
23326 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23327 /*
23328 * Register namespaces on the elem info.
23329 */
23330 if (nb_namespaces != 0) {
23331 /*
23332 * Although the parser builds its own namespace list,
23333 * we have no access to it, so we'll use an own one.
23334 */
23335 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
23336 /*
23337 * Store prefix and namespace name.
23338 */
23339 if (ielem->nsBindings == NULL) {
23340 ielem->nsBindings =
23341 (const xmlChar **) xmlMalloc(10 *
23342 sizeof(const xmlChar *));
23343 if (ielem->nsBindings == NULL) {
23344 xmlSchemaVErrMemory(vctxt,
23345 "allocating namespace bindings for SAX validation",
23346 NULL);
23347 goto internal_error;
23348 }
23349 ielem->nbNsBindings = 0;
23350 ielem->sizeNsBindings = 5;
23351 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
23352 ielem->sizeNsBindings *= 2;
23353 ielem->nsBindings =
23354 (const xmlChar **) xmlRealloc(
23355 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023356 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023357 if (ielem->nsBindings == NULL) {
23358 xmlSchemaVErrMemory(vctxt,
23359 "re-allocating namespace bindings for SAX validation",
23360 NULL);
23361 goto internal_error;
23362 }
23363 }
23364
23365 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
23366 if (namespaces[j+1][0] == 0) {
23367 /*
23368 * Handle xmlns="".
23369 */
23370 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
23371 } else
23372 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
23373 namespaces[j+1];
23374 ielem->nbNsBindings++;
23375 }
23376 }
23377 /*
23378 * Register attributes.
23379 * SAX VAL TODO: We are not adding namespace declaration
23380 * attributes yet.
23381 */
23382 if (nb_attributes != 0) {
23383 xmlChar *value;
23384
23385 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
23386 /*
23387 * Duplicate the value.
23388 */
23389 value = xmlStrndup(attributes[j+3],
23390 attributes[j+4] - attributes[j+3]);
23391 ret = xmlSchemaValidatorPushAttribute(vctxt,
23392 NULL, attributes[j], attributes[j+2], 0,
23393 value, 1);
23394 if (ret == -1) {
23395 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23396 "calling xmlSchemaValidatorPushAttribute()");
23397 goto internal_error;
23398 }
23399 }
23400 }
23401 /*
23402 * Validate the element.
23403 */
23404 ret = xmlSchemaValidateElem(vctxt);
23405 if (ret != 0) {
23406 if (ret == -1) {
23407 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23408 "calling xmlSchemaValidateElem()");
23409 goto internal_error;
23410 }
23411 goto exit;
23412 }
23413
23414exit:
23415 return;
23416internal_error:
23417 vctxt->err = -1;
23418 xmlStopParser(vctxt->parserCtxt);
23419 return;
23420}
23421
23422static void
23423xmlSchemaSAXHandleEndElementNs(void *ctx,
23424 const xmlChar * localname ATTRIBUTE_UNUSED,
23425 const xmlChar * prefix ATTRIBUTE_UNUSED,
23426 const xmlChar * URI ATTRIBUTE_UNUSED)
23427{
23428 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23429 int res;
23430
23431 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023432 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023433 */
23434 if (vctxt->skipDepth != -1) {
23435 if (vctxt->depth > vctxt->skipDepth) {
23436 vctxt->depth--;
23437 return;
23438 } else
23439 vctxt->skipDepth = -1;
23440 }
23441 /*
23442 * SAX VAL TODO: Just a temporary check.
23443 */
23444 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
23445 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
23446 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23447 "elem pop mismatch");
23448 }
23449 res = xmlSchemaValidatorPopElem(vctxt);
23450 if (res != 0) {
23451 if (res < 0) {
23452 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23453 "calling xmlSchemaValidatorPopElem()");
23454 goto internal_error;
23455 }
23456 goto exit;
23457 }
23458exit:
23459 return;
23460internal_error:
23461 vctxt->err = -1;
23462 xmlStopParser(vctxt->parserCtxt);
23463 return;
23464}
23465#endif
23466
Daniel Veillard4255d502002-04-16 15:50:10 +000023467/************************************************************************
23468 * *
23469 * Validation interfaces *
23470 * *
23471 ************************************************************************/
23472
23473/**
23474 * xmlSchemaNewValidCtxt:
23475 * @schema: a precompiled XML Schemas
23476 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023477 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023478 *
23479 * Returns the validation context or NULL in case of error
23480 */
23481xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023482xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23483{
Daniel Veillard4255d502002-04-16 15:50:10 +000023484 xmlSchemaValidCtxtPtr ret;
23485
23486 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23487 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023488 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023489 return (NULL);
23490 }
23491 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023492 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
23493 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023494 return (ret);
23495}
23496
23497/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023498 * xmlSchemaClearValidCtxt:
23499 * @ctxt: the schema validation context
23500 *
23501 * Free the resources associated to the schema validation context;
23502 * leaves some fields alive intended for reuse of the context.
23503 */
23504static void
23505xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23506{
23507 if (vctxt == NULL)
23508 return;
23509
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023510 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023511 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023512 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023513#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023514 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023515#endif
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023516 if (vctxt->value != NULL) {
23517 xmlSchemaFreeValue(vctxt->value);
23518 vctxt->value = NULL;
23519 }
23520 /*
23521 * Augmented IDC information.
23522 */
23523 if (vctxt->aidcs != NULL) {
23524 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23525 do {
23526 next = cur->next;
23527 xmlFree(cur);
23528 cur = next;
23529 } while (cur != NULL);
23530 vctxt->aidcs = NULL;
23531 }
23532 if (vctxt->idcNodes != NULL) {
23533 int i;
23534 xmlSchemaPSVIIDCNodePtr item;
23535
23536 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023537 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023538 xmlFree(item->keys);
23539 xmlFree(item);
23540 }
23541 xmlFree(vctxt->idcNodes);
23542 vctxt->idcNodes = NULL;
23543 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023544 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023545 * Note that we won't delete the XPath state pool here.
23546 */
23547 if (vctxt->xpathStates != NULL) {
23548 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23549 vctxt->xpathStates = NULL;
23550 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023551 /*
23552 * Attribute info.
23553 */
23554 if (vctxt->nbAttrInfos != 0) {
23555 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023556 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023557 /*
23558 * Element info.
23559 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023560 if (vctxt->elemInfos != NULL) {
23561 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023562 xmlSchemaNodeInfoPtr ei;
23563
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023564 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023565 ei = vctxt->elemInfos[i];
23566 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023567 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023568 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023569 }
23570 }
23571}
23572
23573/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023574 * xmlSchemaFreeValidCtxt:
23575 * @ctxt: the schema validation context
23576 *
23577 * Free the resources associated to the schema validation context
23578 */
23579void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023580xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23581{
Daniel Veillard4255d502002-04-16 15:50:10 +000023582 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023583 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000023584 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023585 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023586 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023587 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023588 if (ctxt->idcNodes != NULL) {
23589 int i;
23590 xmlSchemaPSVIIDCNodePtr item;
23591
23592 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023593 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023594 xmlFree(item->keys);
23595 xmlFree(item);
23596 }
23597 xmlFree(ctxt->idcNodes);
23598 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023599 if (ctxt->idcKeys != NULL) {
23600 int i;
23601 for (i = 0; i < ctxt->nbIdcKeys; i++)
23602 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
23603 xmlFree(ctxt->idcKeys);
23604 }
23605
23606 if (ctxt->xpathStates != NULL)
23607 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
23608 if (ctxt->xpathStatePool != NULL)
23609 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
23610
23611 /*
23612 * Augmented IDC information.
23613 */
23614 if (ctxt->aidcs != NULL) {
23615 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
23616 do {
23617 next = cur->next;
23618 xmlFree(cur);
23619 cur = next;
23620 } while (cur != NULL);
23621 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023622 if (ctxt->attrInfos != NULL) {
23623 int i;
23624 xmlSchemaAttrInfoPtr attr;
23625
23626 /* Just a paranoid call to the cleanup. */
23627 if (ctxt->nbAttrInfos != 0)
23628 xmlSchemaClearAttrInfos(ctxt);
23629 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
23630 attr = ctxt->attrInfos[i];
23631 xmlFree(attr);
23632 }
23633 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023634 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023635 if (ctxt->elemInfos != NULL) {
23636 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023637 xmlSchemaNodeInfoPtr ei;
23638
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023639 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023640 ei = ctxt->elemInfos[i];
23641 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023642 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023643 xmlSchemaClearElemInfo(ei);
23644 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023645 }
23646 xmlFree(ctxt->elemInfos);
23647 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023648 if (ctxt->dict != NULL)
23649 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000023650 xmlFree(ctxt);
23651}
23652
23653/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000023654 * xmlSchemaIsValid:
23655 * @ctxt: the schema validation context
23656 *
23657 * Check if any error was detected during validation.
23658 *
23659 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
23660 * of internal error.
23661 */
23662int
23663xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
23664{
23665 if (ctxt == NULL)
23666 return(-1);
23667 return(ctxt->err == 0);
23668}
23669
23670/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023671 * xmlSchemaSetValidErrors:
23672 * @ctxt: a schema validation context
23673 * @err: the error function
23674 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023675 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023676 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023677 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023678 */
23679void
23680xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023681 xmlSchemaValidityErrorFunc err,
23682 xmlSchemaValidityWarningFunc warn, void *ctx)
23683{
Daniel Veillard4255d502002-04-16 15:50:10 +000023684 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023685 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023686 ctxt->error = err;
23687 ctxt->warning = warn;
23688 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023689 if (ctxt->pctxt != NULL)
23690 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023691}
23692
23693/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000023694 * xmlSchemaSetValidStructuredErrors:
23695 * @ctxt: a schema validation context
23696 * @serror: the structured error function
23697 * @ctx: the functions context
23698 *
23699 * Set the structured error callback
23700 */
23701void
23702xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
23703 xmlStructuredErrorFunc serror, void *ctx)
23704{
23705 if (ctxt == NULL)
23706 return;
23707 ctxt->serror = serror;
23708 ctxt->error = NULL;
23709 ctxt->warning = NULL;
23710 ctxt->userData = ctx;
23711}
23712
23713/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023714 * xmlSchemaGetValidErrors:
23715 * @ctxt: a XML-Schema validation context
23716 * @err: the error function result
23717 * @warn: the warning function result
23718 * @ctx: the functions context result
23719 *
23720 * Get the error and warning callback informations
23721 *
23722 * Returns -1 in case of error and 0 otherwise
23723 */
23724int
23725xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23726 xmlSchemaValidityErrorFunc * err,
23727 xmlSchemaValidityWarningFunc * warn, void **ctx)
23728{
23729 if (ctxt == NULL)
23730 return (-1);
23731 if (err != NULL)
23732 *err = ctxt->error;
23733 if (warn != NULL)
23734 *warn = ctxt->warning;
23735 if (ctx != NULL)
23736 *ctx = ctxt->userData;
23737 return (0);
23738}
23739
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023740
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023741/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023742 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023743 * @ctxt: a schema validation context
23744 * @options: a combination of xmlSchemaValidOption
23745 *
23746 * Sets the options to be used during the validation.
23747 *
23748 * Returns 0 in case of success, -1 in case of an
23749 * API error.
23750 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023751int
23752xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23753 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023754
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023755{
23756 int i;
23757
23758 if (ctxt == NULL)
23759 return (-1);
23760 /*
23761 * WARNING: Change the start value if adding to the
23762 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023763 * TODO: Is there an other, more easy to maintain,
23764 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023765 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023766 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023767 if (options & 1<<i)
23768 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023769 }
23770 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023771 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023772}
23773
23774/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023775 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023776 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023777 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023778 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023779 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023780 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023781 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023782int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023783xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023784
23785{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023786 if (ctxt == NULL)
23787 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023788 else
23789 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023790}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023791
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023792static int
23793xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
23794{
23795 xmlAttrPtr attr;
23796 int ret = 0;
23797 xmlSchemaNodeInfoPtr ielem = NULL;
23798 xmlNodePtr node, valRoot;
23799 const xmlChar *nsName;
23800
23801 /* DOC VAL TODO: Move this to the start function. */
23802 valRoot = xmlDocGetRootElement(vctxt->doc);
23803 if (valRoot == NULL) {
23804 /* VAL TODO: Error code? */
23805 VERROR(1, NULL, "The document has no document element");
23806 return (1);
23807 }
23808 vctxt->depth = -1;
23809 vctxt->validationRoot = valRoot;
23810 node = valRoot;
23811 while (node != NULL) {
23812 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23813 goto next_sibling;
23814 if (node->type == XML_ELEMENT_NODE) {
23815
23816 /*
23817 * Init the node-info.
23818 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023819 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023820 if (xmlSchemaValidatorPushElem(vctxt) == -1)
23821 goto internal_error;
23822 ielem = vctxt->inode;
23823 ielem->node = node;
23824 ielem->localName = node->name;
23825 if (node->ns != NULL)
23826 ielem->nsName = node->ns->href;
23827 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23828 /*
23829 * Register attributes.
23830 * DOC VAL TODO: We do not register namespace declaration
23831 * attributes yet.
23832 */
23833 vctxt->nbAttrInfos = 0;
23834 if (node->properties != NULL) {
23835 attr = node->properties;
23836 do {
23837 if (attr->ns != NULL)
23838 nsName = attr->ns->href;
23839 else
23840 nsName = NULL;
23841 ret = xmlSchemaValidatorPushAttribute(vctxt,
23842 (xmlNodePtr) attr,
23843 attr->name, nsName, 0,
23844 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
23845 if (ret == -1) {
23846 VERROR_INT("xmlSchemaDocWalk",
23847 "calling xmlSchemaValidatorPushAttribute()");
23848 goto internal_error;
23849 }
23850 attr = attr->next;
23851 } while (attr);
23852 }
23853 /*
23854 * Validate the element.
23855 */
23856 ret = xmlSchemaValidateElem(vctxt);
23857 if (ret != 0) {
23858 if (ret == -1) {
23859 VERROR_INT("xmlSchemaDocWalk",
23860 "calling xmlSchemaValidateElem()");
23861 goto internal_error;
23862 }
23863 /*
23864 * Don't stop validation; just skip the content
23865 * of this element.
23866 */
23867 goto leave_node;
23868 }
23869 if ((vctxt->skipDepth != -1) &&
23870 (vctxt->depth >= vctxt->skipDepth))
23871 goto leave_node;
23872 } else if ((node->type == XML_TEXT_NODE) ||
23873 (node->type == XML_CDATA_SECTION_NODE)) {
23874 /*
23875 * Process character content.
23876 */
23877 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23878 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23879 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
23880 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
23881 if (ret < 0) {
23882 VERROR_INT("xmlSchemaVDocWalk",
23883 "calling xmlSchemaVPushText()");
23884 goto internal_error;
23885 }
23886 /*
23887 * DOC VAL TODO: Should we skip further validation of the
23888 * element content here?
23889 */
23890 } else if ((node->type == XML_ENTITY_NODE) ||
23891 (node->type == XML_ENTITY_REF_NODE)) {
23892 /*
23893 * DOC VAL TODO: What to do with entities?
23894 */
23895 TODO
23896 } else {
23897 goto leave_node;
23898 /*
23899 * DOC VAL TODO: XInclude nodes, etc.
23900 */
23901 }
23902 /*
23903 * Walk the doc.
23904 */
23905 if (node->children != NULL) {
23906 node = node->children;
23907 continue;
23908 }
23909leave_node:
23910 if (node->type == XML_ELEMENT_NODE) {
23911 /*
23912 * Leaving the scope of an element.
23913 */
23914 if (node != vctxt->inode->node) {
23915 VERROR_INT("xmlSchemaVDocWalk",
23916 "element position mismatch");
23917 goto internal_error;
23918 }
23919 ret = xmlSchemaValidatorPopElem(vctxt);
23920 if (ret != 0) {
23921 if (ret < 0) {
23922 VERROR_INT("xmlSchemaVDocWalk",
23923 "calling xmlSchemaValidatorPopElem()");
23924 goto internal_error;
23925 }
23926 }
23927 if (node == valRoot)
23928 goto exit;
23929 }
23930next_sibling:
23931 if (node->next != NULL)
23932 node = node->next;
23933 else {
23934 node = node->parent;
23935 goto leave_node;
23936 }
23937 }
23938
23939exit:
23940 return (ret);
23941internal_error:
23942 return (-1);
23943}
23944
23945static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000023946xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023947 /*
23948 * Some initialization.
23949 */
23950 vctxt->err = 0;
23951 vctxt->nberrors = 0;
23952 vctxt->depth = -1;
23953 vctxt->skipDepth = -1;
23954 /*
23955 * Create a schema + parser if necessary.
23956 */
23957 if (vctxt->schema == NULL) {
23958
23959 if ((vctxt->pctxt == NULL) &&
23960 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
23961 return (-1);
23962
23963 vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
23964 if (vctxt->schema == NULL) {
23965 VERROR_INT("xmlSchemaVStartValidation",
23966 "creating a schema");
23967 return (-1);
23968 }
23969 vctxt->xsiAssemble = 1;
23970 } else
23971 vctxt->xsiAssemble = 0;
23972 /*
23973 * Augment the IDC definitions.
23974 */
23975 if (vctxt->schema->idcDef != NULL) {
23976 xmlHashScan(vctxt->schema->idcDef,
23977 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
23978 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000023979 return(0);
23980}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023981
Daniel Veillardf10ae122005-07-10 19:03:16 +000023982static void
23983xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023984 if (vctxt->xsiAssemble) {
23985 if (vctxt->schema != NULL) {
23986 xmlSchemaFree(vctxt->schema);
23987 vctxt->schema = NULL;
23988 }
23989 }
23990 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000023991}
23992
23993static int
23994xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
23995{
23996 int ret = 0;
23997
23998 if (xmlSchemaPreRun(vctxt) < 0)
23999 return(-1);
24000
24001 if (vctxt->doc != NULL) {
24002 /*
24003 * Tree validation.
24004 */
24005 ret = xmlSchemaVDocWalk(vctxt);
24006#ifdef LIBXML_READER_ENABLED
24007 } else if (vctxt->reader != NULL) {
24008 /*
24009 * XML Reader validation.
24010 */
24011#ifdef XML_SCHEMA_READER_ENABLED
24012 ret = xmlSchemaVReaderWalk(vctxt);
24013#endif
24014#endif
24015 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
24016 /*
24017 * SAX validation.
24018 */
24019 ret = xmlParseDocument(vctxt->parserCtxt);
24020 } else {
24021 VERROR_INT("xmlSchemaVStartValidation",
24022 "no instance to validate");
24023 ret = -1;
24024 }
24025
24026 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024027 if (ret == 0)
24028 ret = vctxt->err;
24029 return (ret);
24030}
24031
24032/**
24033 * xmlSchemaValidateOneElement:
24034 * @ctxt: a schema validation context
24035 * @elem: an element node
24036 *
24037 * Validate a branch of a tree, starting with the given @elem.
24038 *
24039 * Returns 0 if the element and its subtree is valid, a positive error
24040 * code number otherwise and -1 in case of an internal or API error.
24041 */
24042int
24043xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
24044{
24045 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
24046 return (-1);
24047
24048 if (ctxt->schema == NULL)
24049 return (-1);
24050
24051 ctxt->doc = elem->doc;
24052 ctxt->node = elem;
24053 ctxt->validationRoot = elem;
24054 return(xmlSchemaVStart(ctxt));
24055}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024056
Daniel Veillard259f0df2004-08-18 09:13:18 +000024057/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024058 * xmlSchemaValidateDoc:
24059 * @ctxt: a schema validation context
24060 * @doc: a parsed document tree
24061 *
24062 * Validate a document tree in memory.
24063 *
24064 * Returns 0 if the document is schemas valid, a positive error code
24065 * number otherwise and -1 in case of internal or API error.
24066 */
24067int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024068xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
24069{
Daniel Veillard4255d502002-04-16 15:50:10 +000024070 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024071 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000024072
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024073 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024074 ctxt->node = xmlDocGetRootElement(doc);
24075 if (ctxt->node == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024076 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024077 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
24078 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024079 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024080 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024081 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024082 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024083 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000024084}
24085
Daniel Veillardcdc82732005-07-08 15:04:06 +000024086
24087/************************************************************************
24088 * *
24089 * Function and data for SAX streaming API *
24090 * *
24091 ************************************************************************/
24092typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
24093typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
24094
24095struct _xmlSchemaSplitSAXData {
24096 xmlSAXHandlerPtr user_sax;
24097 void *user_data;
24098 xmlSchemaValidCtxtPtr ctxt;
24099 xmlSAXHandlerPtr schemas_sax;
24100};
24101
Daniel Veillard971771e2005-07-09 17:32:57 +000024102#define XML_SAX_PLUG_MAGIC 0xdc43ba21
24103
24104struct _xmlSchemaSAXPlug {
24105 unsigned int magic;
24106
24107 /* the original callbacks informations */
24108 xmlSAXHandlerPtr *user_sax_ptr;
24109 xmlSAXHandlerPtr user_sax;
24110 void **user_data_ptr;
24111 void *user_data;
24112
24113 /* the block plugged back and validation informations */
24114 xmlSAXHandler schemas_sax;
24115 xmlSchemaValidCtxtPtr ctxt;
24116};
24117
Daniel Veillardcdc82732005-07-08 15:04:06 +000024118/* All those functions just bounces to the user provided SAX handlers */
24119static void
24120internalSubsetSplit(void *ctx, const xmlChar *name,
24121 const xmlChar *ExternalID, const xmlChar *SystemID)
24122{
Daniel Veillard971771e2005-07-09 17:32:57 +000024123 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024124 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24125 (ctxt->user_sax->internalSubset != NULL))
24126 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24127 SystemID);
24128}
24129
24130static int
24131isStandaloneSplit(void *ctx)
24132{
Daniel Veillard971771e2005-07-09 17:32:57 +000024133 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024134 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24135 (ctxt->user_sax->isStandalone != NULL))
24136 return(ctxt->user_sax->isStandalone(ctxt->user_data));
24137 return(0);
24138}
24139
24140static int
24141hasInternalSubsetSplit(void *ctx)
24142{
Daniel Veillard971771e2005-07-09 17:32:57 +000024143 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024144 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24145 (ctxt->user_sax->hasInternalSubset != NULL))
24146 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
24147 return(0);
24148}
24149
24150static int
24151hasExternalSubsetSplit(void *ctx)
24152{
Daniel Veillard971771e2005-07-09 17:32:57 +000024153 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024154 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24155 (ctxt->user_sax->hasExternalSubset != NULL))
24156 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
24157 return(0);
24158}
24159
24160static void
24161externalSubsetSplit(void *ctx, const xmlChar *name,
24162 const xmlChar *ExternalID, const xmlChar *SystemID)
24163{
Daniel Veillard971771e2005-07-09 17:32:57 +000024164 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024165 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24166 (ctxt->user_sax->internalSubset != NULL))
24167 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24168 SystemID);
24169}
24170
24171static xmlParserInputPtr
24172resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
24173{
Daniel Veillard971771e2005-07-09 17:32:57 +000024174 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024175 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24176 (ctxt->user_sax->resolveEntity != NULL))
24177 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
24178 systemId));
24179 return(NULL);
24180}
24181
24182static xmlEntityPtr
24183getEntitySplit(void *ctx, const xmlChar *name)
24184{
Daniel Veillard971771e2005-07-09 17:32:57 +000024185 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024186 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24187 (ctxt->user_sax->getEntity != NULL))
24188 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
24189 return(NULL);
24190}
24191
24192static xmlEntityPtr
24193getParameterEntitySplit(void *ctx, const xmlChar *name)
24194{
Daniel Veillard971771e2005-07-09 17:32:57 +000024195 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024196 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24197 (ctxt->user_sax->getParameterEntity != NULL))
24198 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
24199 return(NULL);
24200}
24201
24202
24203static void
24204entityDeclSplit(void *ctx, const xmlChar *name, int type,
24205 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
24206{
Daniel Veillard971771e2005-07-09 17:32:57 +000024207 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024208 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24209 (ctxt->user_sax->entityDecl != NULL))
24210 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
24211 systemId, content);
24212}
24213
24214static void
24215attributeDeclSplit(void *ctx, const xmlChar * elem,
24216 const xmlChar * name, int type, int def,
24217 const xmlChar * defaultValue, xmlEnumerationPtr tree)
24218{
Daniel Veillard971771e2005-07-09 17:32:57 +000024219 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024220 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24221 (ctxt->user_sax->attributeDecl != NULL)) {
24222 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
24223 def, defaultValue, tree);
24224 } else {
24225 xmlFreeEnumeration(tree);
24226 }
24227}
24228
24229static void
24230elementDeclSplit(void *ctx, const xmlChar *name, int type,
24231 xmlElementContentPtr content)
24232{
Daniel Veillard971771e2005-07-09 17:32:57 +000024233 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024234 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24235 (ctxt->user_sax->elementDecl != NULL))
24236 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
24237}
24238
24239static void
24240notationDeclSplit(void *ctx, const xmlChar *name,
24241 const xmlChar *publicId, const xmlChar *systemId)
24242{
Daniel Veillard971771e2005-07-09 17:32:57 +000024243 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024244 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24245 (ctxt->user_sax->notationDecl != NULL))
24246 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
24247 systemId);
24248}
24249
24250static void
24251unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
24252 const xmlChar *publicId, const xmlChar *systemId,
24253 const xmlChar *notationName)
24254{
Daniel Veillard971771e2005-07-09 17:32:57 +000024255 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024256 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24257 (ctxt->user_sax->unparsedEntityDecl != NULL))
24258 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
24259 systemId, notationName);
24260}
24261
24262static void
24263setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
24264{
Daniel Veillard971771e2005-07-09 17:32:57 +000024265 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024266 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24267 (ctxt->user_sax->setDocumentLocator != NULL))
24268 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
24269}
24270
24271static void
24272startDocumentSplit(void *ctx)
24273{
Daniel Veillard971771e2005-07-09 17:32:57 +000024274 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024275 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24276 (ctxt->user_sax->startDocument != NULL))
24277 ctxt->user_sax->startDocument(ctxt->user_data);
24278}
24279
24280static void
24281endDocumentSplit(void *ctx)
24282{
Daniel Veillard971771e2005-07-09 17:32:57 +000024283 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024284 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24285 (ctxt->user_sax->endDocument != NULL))
24286 ctxt->user_sax->endDocument(ctxt->user_data);
24287}
24288
24289static void
24290processingInstructionSplit(void *ctx, const xmlChar *target,
24291 const xmlChar *data)
24292{
Daniel Veillard971771e2005-07-09 17:32:57 +000024293 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024294 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24295 (ctxt->user_sax->processingInstruction != NULL))
24296 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
24297}
24298
24299static void
24300commentSplit(void *ctx, const xmlChar *value)
24301{
Daniel Veillard971771e2005-07-09 17:32:57 +000024302 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024303 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24304 (ctxt->user_sax->comment != NULL))
24305 ctxt->user_sax->comment(ctxt->user_data, value);
24306}
24307
24308/*
24309 * Varargs error callbacks to the user application, harder ...
24310 */
24311
24312static void
Daniel Veillardafc05b62005-07-17 06:11:19 +000024313warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024314 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024315 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24316 (ctxt->user_sax->warning != NULL)) {
24317 TODO
24318 }
24319}
24320static void
Daniel Veillardafc05b62005-07-17 06:11:19 +000024321errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024322 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024323 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24324 (ctxt->user_sax->error != NULL)) {
24325 TODO
24326 }
24327}
24328static void
Daniel Veillardafc05b62005-07-17 06:11:19 +000024329fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024330 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024331 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24332 (ctxt->user_sax->fatalError != NULL)) {
24333 TODO
24334 }
24335}
24336
24337/*
24338 * Those are function where both the user handler and the schemas handler
24339 * need to be called.
24340 */
24341static void
24342charactersSplit(void *ctx, const xmlChar *ch, int len)
24343{
Daniel Veillard971771e2005-07-09 17:32:57 +000024344 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024345 if (ctxt == NULL)
24346 return;
24347 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
24348 ctxt->user_sax->characters(ctxt->user_data, ch, len);
24349 if (ctxt->ctxt != NULL)
24350 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24351}
24352
24353static void
24354ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
24355{
Daniel Veillard971771e2005-07-09 17:32:57 +000024356 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024357 if (ctxt == NULL)
24358 return;
24359 if ((ctxt->user_sax != NULL) &&
24360 (ctxt->user_sax->ignorableWhitespace != NULL))
24361 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
24362 if (ctxt->ctxt != NULL)
24363 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24364}
24365
24366static void
24367cdataBlockSplit(void *ctx, const xmlChar *value, int len)
24368{
Daniel Veillard971771e2005-07-09 17:32:57 +000024369 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024370 if (ctxt == NULL)
24371 return;
24372 if ((ctxt->user_sax != NULL) &&
24373 (ctxt->user_sax->ignorableWhitespace != NULL))
24374 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
24375 if (ctxt->ctxt != NULL)
24376 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
24377}
24378
24379static void
24380referenceSplit(void *ctx, const xmlChar *name)
24381{
Daniel Veillard971771e2005-07-09 17:32:57 +000024382 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024383 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24384 (ctxt->user_sax->reference != NULL))
24385 ctxt->user_sax->reference(ctxt->user_data, name);
24386 if (ctxt->ctxt != NULL)
24387 xmlSchemaSAXHandleReference(ctxt->user_data, name);
24388}
24389
24390static void
24391startElementNsSplit(void *ctx, const xmlChar * localname,
24392 const xmlChar * prefix, const xmlChar * URI,
24393 int nb_namespaces, const xmlChar ** namespaces,
24394 int nb_attributes, int nb_defaulted,
24395 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024396 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024397 if (ctxt == NULL)
24398 return;
24399 if ((ctxt->user_sax != NULL) &&
24400 (ctxt->user_sax->startElementNs != NULL))
24401 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
24402 URI, nb_namespaces, namespaces,
24403 nb_attributes, nb_defaulted,
24404 attributes);
24405 if (ctxt->ctxt != NULL)
24406 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
24407 URI, nb_namespaces, namespaces,
24408 nb_attributes, nb_defaulted,
24409 attributes);
24410}
24411
24412static void
24413endElementNsSplit(void *ctx, const xmlChar * localname,
24414 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024415 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024416 if (ctxt == NULL)
24417 return;
24418 if ((ctxt->user_sax != NULL) &&
24419 (ctxt->user_sax->endElementNs != NULL))
24420 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
24421 if (ctxt->ctxt != NULL)
24422 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
24423}
24424
Daniel Veillard4255d502002-04-16 15:50:10 +000024425/**
Daniel Veillard971771e2005-07-09 17:32:57 +000024426 * xmlSchemaSAXPlug:
24427 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000024428 * @sax: a pointer to the original xmlSAXHandlerPtr
24429 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000024430 *
24431 * Plug a SAX based validation layer in a SAX parsing event flow.
24432 * The original @saxptr and @dataptr data are replaced by new pointers
24433 * but the calls to the original will be maintained.
24434 *
24435 * Returns a pointer to a data structure needed to unplug the validation layer
24436 * or NULL in case of errors.
24437 */
24438xmlSchemaSAXPlugPtr
24439xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
24440 xmlSAXHandlerPtr *sax, void **user_data)
24441{
24442 xmlSchemaSAXPlugPtr ret;
24443 xmlSAXHandlerPtr old_sax;
24444
24445 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
24446 return(NULL);
24447
24448 /*
24449 * We only allow to plug into SAX2 event streams
24450 */
24451 old_sax = *sax;
24452 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
24453 return(NULL);
24454 if ((old_sax != NULL) &&
24455 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
24456 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
24457 return(NULL);
24458
24459 /*
24460 * everything seems right allocate the local data needed for that layer
24461 */
24462 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
24463 if (ret == NULL) {
24464 return(NULL);
24465 }
24466 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
24467 ret->magic = XML_SAX_PLUG_MAGIC;
24468 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
24469 ret->ctxt = ctxt;
24470 ret->user_sax_ptr = sax;
24471 ret->user_sax = old_sax;
24472 if (old_sax == NULL) {
24473 /*
24474 * go direct, no need for the split block and functions.
24475 */
24476 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
24477 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
24478 /*
24479 * Note that we use the same text-function for both, to prevent
24480 * the parser from testing for ignorable whitespace.
24481 */
24482 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
24483 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
24484
24485 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
24486 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
24487
24488 ret->user_data = ctxt;
24489 *user_data = ctxt;
24490 } else {
24491 /*
24492 * for each callback unused by Schemas initialize it to the Split
24493 * routine only if non NULL in the user block, this can speed up
24494 * things at the SAX level.
24495 */
24496 if (old_sax->internalSubset != NULL)
24497 ret->schemas_sax.internalSubset = internalSubsetSplit;
24498 if (old_sax->isStandalone != NULL)
24499 ret->schemas_sax.isStandalone = isStandaloneSplit;
24500 if (old_sax->hasInternalSubset != NULL)
24501 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
24502 if (old_sax->hasExternalSubset != NULL)
24503 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
24504 if (old_sax->resolveEntity != NULL)
24505 ret->schemas_sax.resolveEntity = resolveEntitySplit;
24506 if (old_sax->getEntity != NULL)
24507 ret->schemas_sax.getEntity = getEntitySplit;
24508 if (old_sax->entityDecl != NULL)
24509 ret->schemas_sax.entityDecl = entityDeclSplit;
24510 if (old_sax->notationDecl != NULL)
24511 ret->schemas_sax.notationDecl = notationDeclSplit;
24512 if (old_sax->attributeDecl != NULL)
24513 ret->schemas_sax.attributeDecl = attributeDeclSplit;
24514 if (old_sax->elementDecl != NULL)
24515 ret->schemas_sax.elementDecl = elementDeclSplit;
24516 if (old_sax->unparsedEntityDecl != NULL)
24517 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
24518 if (old_sax->setDocumentLocator != NULL)
24519 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
24520 if (old_sax->startDocument != NULL)
24521 ret->schemas_sax.startDocument = startDocumentSplit;
24522 if (old_sax->endDocument != NULL)
24523 ret->schemas_sax.endDocument = endDocumentSplit;
24524 if (old_sax->processingInstruction != NULL)
24525 ret->schemas_sax.processingInstruction = processingInstructionSplit;
24526 if (old_sax->comment != NULL)
24527 ret->schemas_sax.comment = commentSplit;
24528 if (old_sax->warning != NULL)
24529 ret->schemas_sax.warning = warningSplit;
24530 if (old_sax->error != NULL)
24531 ret->schemas_sax.error = errorSplit;
24532 if (old_sax->fatalError != NULL)
24533 ret->schemas_sax.fatalError = fatalErrorSplit;
24534 if (old_sax->getParameterEntity != NULL)
24535 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
24536 if (old_sax->externalSubset != NULL)
24537 ret->schemas_sax.externalSubset = externalSubsetSplit;
24538
24539 /*
24540 * the 6 schemas callback have to go to the splitter functions
24541 * Note that we use the same text-function for ignorableWhitespace
24542 * if possible, to prevent the parser from testing for ignorable
24543 * whitespace.
24544 */
24545 ret->schemas_sax.characters = charactersSplit;
24546 if ((old_sax->ignorableWhitespace != NULL) &&
24547 (old_sax->ignorableWhitespace != old_sax->characters))
24548 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
24549 else
24550 ret->schemas_sax.ignorableWhitespace = charactersSplit;
24551 ret->schemas_sax.cdataBlock = cdataBlockSplit;
24552 ret->schemas_sax.reference = referenceSplit;
24553 ret->schemas_sax.startElementNs = startElementNsSplit;
24554 ret->schemas_sax.endElementNs = endElementNsSplit;
24555
24556 ret->user_data_ptr = user_data;
24557 ret->user_data = *user_data;
24558 *user_data = ret;
24559 }
24560
24561 /*
24562 * plug the pointers back.
24563 */
24564 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000024565 ctxt->sax = *sax;
24566 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24567 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024568 return(ret);
24569}
24570
24571/**
24572 * xmlSchemaSAXUnplug:
24573 * @plug: a data structure returned by xmlSchemaSAXPlug
24574 *
24575 * Unplug a SAX based validation layer in a SAX parsing event flow.
24576 * The original pointers used in the call are restored.
24577 *
24578 * Returns 0 in case of success and -1 in case of failure.
24579 */
24580int
24581xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
24582{
24583 xmlSAXHandlerPtr *sax;
24584 void **user_data;
24585
24586 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
24587 return(-1);
24588 plug->magic = 0;
24589
Daniel Veillardf10ae122005-07-10 19:03:16 +000024590 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024591 /* restore the data */
24592 sax = plug->user_sax_ptr;
24593 *sax = plug->user_sax;
24594 if (plug->user_sax != NULL) {
24595 user_data = plug->user_data_ptr;
24596 *user_data = plug->user_data;
24597 }
24598
24599 /* free and return */
24600 xmlFree(plug);
24601 return(0);
24602}
24603
24604/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024605 * xmlSchemaValidateStream:
24606 * @ctxt: a schema validation context
24607 * @input: the input to use for reading the data
24608 * @enc: an optional encoding information
24609 * @sax: a SAX handler for the resulting events
24610 * @user_data: the context to provide to the SAX handler.
24611 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000024612 * Validate an input based on a flow of SAX event from the parser
24613 * and forward the events to the @sax handler with the provided @user_data
24614 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000024615 *
24616 * Returns 0 if the document is schemas valid, a positive error code
24617 * number otherwise and -1 in case of internal or API error.
24618 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024619int
Daniel Veillard4255d502002-04-16 15:50:10 +000024620xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024621 xmlParserInputBufferPtr input, xmlCharEncoding enc,
24622 xmlSAXHandlerPtr sax, void *user_data)
24623{
Daniel Veillard971771e2005-07-09 17:32:57 +000024624 xmlSchemaSAXPlugPtr plug = NULL;
24625 xmlSAXHandlerPtr old_sax = NULL;
24626 xmlParserCtxtPtr pctxt = NULL;
24627 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024628 int ret;
24629
Daniel Veillard4255d502002-04-16 15:50:10 +000024630 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024631 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000024632
Daniel Veillardcdc82732005-07-08 15:04:06 +000024633 /*
24634 * prepare the parser
24635 */
24636 pctxt = xmlNewParserCtxt();
24637 if (pctxt == NULL)
24638 return (-1);
24639 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000024640 pctxt->sax = sax;
24641 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024642#if 0
24643 if (options)
24644 xmlCtxtUseOptions(pctxt, options);
24645#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000024646 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024647
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000024648 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024649 if (inputStream == NULL) {
24650 ret = -1;
24651 goto done;
24652 }
24653 inputPush(pctxt, inputStream);
24654 ctxt->parserCtxt = pctxt;
24655 ctxt->input = input;
24656
24657 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000024658 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000024659 */
Daniel Veillard971771e2005-07-09 17:32:57 +000024660 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
24661 if (plug == NULL) {
24662 ret = -1;
24663 goto done;
24664 }
24665 ctxt->input = input;
24666 ctxt->enc = enc;
24667 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024668 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24669 ret = xmlSchemaVStart(ctxt);
24670
24671 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
24672 ret = ctxt->parserCtxt->errNo;
24673 if (ret == 0)
24674 ret = 1;
24675 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024676
24677done:
Daniel Veillard971771e2005-07-09 17:32:57 +000024678 ctxt->parserCtxt = NULL;
24679 ctxt->sax = NULL;
24680 ctxt->input = NULL;
24681 if (plug != NULL) {
24682 xmlSchemaSAXUnplug(plug);
24683 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024684 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000024685 if (pctxt != NULL) {
24686 pctxt->sax = old_sax;
24687 xmlFreeParserCtxt(pctxt);
24688 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024689 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000024690}
24691
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024692/**
24693 * xmlSchemaValidateFile:
24694 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000024695 * @filename: the URI of the instance
24696 * @options: a future set of options, currently unused
24697 *
24698 * Do a schemas validation of the given resource, it will use the
24699 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024700 *
24701 * Returns 0 if the document is valid, a positive error code
24702 * number otherwise and -1 in case of an internal or API error.
24703 */
24704int
24705xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024706 const char * filename,
24707 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024708{
Daniel Veillard81562d22005-06-15 13:27:56 +000024709#ifdef XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024710 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024711 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024712
24713 if ((ctxt == NULL) || (filename == NULL))
24714 return (-1);
24715
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024716 input = xmlParserInputBufferCreateFilename(filename,
24717 XML_CHAR_ENCODING_NONE);
24718 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024719 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024720 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
24721 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024722 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000024723#else
24724 return (-1);
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024725#endif /* XML_SCHEMA_SAX_ENABLED */
Daniel Veillard81562d22005-06-15 13:27:56 +000024726}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024727
Daniel Veillard5d4644e2005-04-01 13:11:58 +000024728#define bottom_xmlschemas
24729#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000024730#endif /* LIBXML_SCHEMAS_ENABLED */