blob: 7d45996e5f31fca0cbce3aacb7b4e61c9c580308 [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. Buchcik6e224f12005-02-17 11:10:44 +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.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015 * - if we don't intend to use the schema for schemas, we
16 * 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:
21 * - Elimated item creation for: <restriction>, <extension>,
22 * <simpleContent>, <complexContent>, <list>, <union>
23 *
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
37#include <libxml/xmlschemas.h>
38#include <libxml/schemasInternals.h>
39#include <libxml/xmlschemastypes.h>
40#include <libxml/xmlautomata.h>
41#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000042#include <libxml/dict.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000043#ifdef LIBXML_PATTERN_ENABLED
44#include <libxml/pattern.h>
45#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000046
Daniel Veillarda84c0b32003-06-02 16:58:46 +000047/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000048
Daniel Veillard82bbbd42003-05-11 20:16:09 +000049/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000050
Daniel Veillard82bbbd42003-05-11 20:16:09 +000051/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000052
Daniel Veillard118aed72002-09-24 14:13:13 +000053/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000054
Daniel Veillard4255d502002-04-16 15:50:10 +000055/* #define DEBUG_AUTOMATA 1 */
56
Daniel Veillard3646d642004-06-02 19:19:14 +000057/* #define DEBUG_ATTR_VALIDATION 1 */
58
Daniel Veillardc0826a72004-08-10 14:17:33 +000059/* #define DEBUG_UNION_VALIDATION 1 */
60
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000061/* #define DEBUG_IDC 1 */
62
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000063/* #define DEBUG_INCLUDES 1 */
64
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000065#define DUMP_CONTENT_MODEL
66
Daniel Veillardc0826a72004-08-10 14:17:33 +000067
Daniel Veillard4255d502002-04-16 15:50:10 +000068#define UNBOUNDED (1 << 30)
69#define TODO \
70 xmlGenericError(xmlGenericErrorContext, \
71 "Unimplemented block at %s:%d\n", \
72 __FILE__, __LINE__);
73
William M. Brack2f2a6632004-08-20 23:09:47 +000074#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000075
Daniel Veillard4255d502002-04-16 15:50:10 +000076/*
77 * The XML Schemas namespaces
78 */
79static const xmlChar *xmlSchemaNs = (const xmlChar *)
80 "http://www.w3.org/2001/XMLSchema";
81
82static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
83 "http://www.w3.org/2001/XMLSchema-instance";
84
Daniel Veillardc0826a72004-08-10 14:17:33 +000085static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
86 "Element decl.";
87static const xmlChar *xmlSchemaElemDesElemRef = (const xmlChar *)
88 "Element ref.";
89static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
90 "Attribute decl.";
91static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
92 "Attribute ref.";
93static const xmlChar *xmlSchemaElemDesST = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000094 "simple type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000095static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000096 "complex type";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000097static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
98 "Model group";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000099#if 0
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000100static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
101 "Model group ref.";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000102#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000103
Daniel Veillard4255d502002-04-16 15:50:10 +0000104#define IS_SCHEMA(node, type) \
105 ((node != NULL) && (node->ns != NULL) && \
106 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
107 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
108
Daniel Veillardc0826a72004-08-10 14:17:33 +0000109#define FREE_AND_NULL(str) \
110 if (str != NULL) { \
111 xmlFree(str); \
112 str = NULL; \
113 }
114
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000115#define IS_ANYTYPE(item) \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000116 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
117 (item->builtInType == XML_SCHEMAS_ANYTYPE))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000118
119#define IS_COMPLEX_TYPE(item) \
120 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
121 (item->builtInType == XML_SCHEMAS_ANYTYPE))
122
123#define IS_SIMPLE_TYPE(item) \
124 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
125 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
126 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
127
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000128#define IS_ANY_SIMPLE_TYPE(item) \
129 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
130 (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
131
132#define IS_NOT_TYPEFIXED(item) \
133 ((item->type != XML_SCHEMA_TYPE_BASIC) && \
134 ((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
135
136#define HAS_COMPLEX_CONTENT(item) \
137 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
138 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
139 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
140
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000141#define HAS_SIMPLE_CONTENT(item) \
142 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
143 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
144
145#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
146
147#define IS_PARTICLE_EMPTIABLE(item) \
148 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
149
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000150#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
151
152#define IS_MODEL_GROUP(item) \
153 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
154 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
155 (item->type == XML_SCHEMA_TYPE_ALL))
156
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000157#define ELEM_TYPE(item) item->subtypes
158
159#define SUBST_GROUP_AFF(item) item->refDecl
160
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000161#if 0
162#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
163#endif
164
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +0000165/*
Daniel Veillardc0826a72004-08-10 14:17:33 +0000166#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
167#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
168#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +0000169*/
Daniel Veillardc0826a72004-08-10 14:17:33 +0000170
Daniel Veillard4255d502002-04-16 15:50:10 +0000171#define XML_SCHEMAS_PARSE_ERROR 1
172
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000173#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
174
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000175
176/*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000177* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
178* locate schemata to be imported
179* using the namespace name; otherwise
180* the location URI will be used */
181
182/*
183* xmlSchemaParserOption:
184*
185* This is the set of XML Schema parser options.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000186*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000187typedef enum {
188 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000189 * locate schemata to be imported
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000190 * using the namespace name; otherwise
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000191 * the location URI will be used *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000192} xmlSchemaParserOption;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000193*/
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000194
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000195typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000196typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000197
198typedef struct _xmlSchemaItemList xmlSchemaItemList;
199typedef xmlSchemaItemList *xmlSchemaItemListPtr;
200
201struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000202 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000203 int nbItems; /* used for dynamic addition of schemata */
204 int sizeItems; /* used for dynamic addition of schemata */
205};
206
Daniel Veillard4255d502002-04-16 15:50:10 +0000207struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000208 void *userData; /* user specific data block */
209 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
210 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000211 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000212 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000213 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000214
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000215 xmlSchemaPtr topschema; /* The main schema */
216 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
217
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000218 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000219 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000220 int counter;
221
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000222 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000223 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000224 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000225
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000226 const char *buffer;
227 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000228
Daniel Veillard4255d502002-04-16 15:50:10 +0000229 /*
230 * Used to build complex element content models
231 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000232 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000233 xmlAutomataStatePtr start;
234 xmlAutomataStatePtr end;
235 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000236
237 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000238 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000239 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
240 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000241 xmlSchemaAssemblePtr assemble;
242 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000243 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000244 const xmlChar **localImports; /* list of locally imported namespaces */
245 int sizeLocalImports;
246 int nbLocalImports;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000247 xmlHashTablePtr substGroups;
Daniel Veillard4255d502002-04-16 15:50:10 +0000248};
249
250
251#define XML_SCHEMAS_ATTR_UNKNOWN 1
252#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000253#define XML_SCHEMAS_ATTR_PROHIBITED 3
254#define XML_SCHEMAS_ATTR_MISSING 4
255#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
256#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000257#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
258#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000259#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
260#define XML_SCHEMAS_ATTR_WILD_NO_DECL 10
Daniel Veillard4255d502002-04-16 15:50:10 +0000261
262typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
263typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
264struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000265 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000266 xmlAttrPtr attr;
267 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000268 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000269 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000270};
271
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000272/**
273 * xmlSchemaBasicItem:
274 *
275 * The abstract base type for schema components.
276 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000277typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
278typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
279struct _xmlSchemaBasicItem {
280 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000281};
282
283/**
284 * xmlSchemaAnnotItem:
285 *
286 * The abstract base type for annotated schema components.
287 * (Extends xmlSchemaBasicItem)
288 */
289typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
290typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
291struct _xmlSchemaAnnotItem {
292 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000293 xmlSchemaAnnotPtr annot;
294};
295
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000296/**
297 * xmlSchemaTreeItem:
298 *
299 * The abstract base type for tree-like structured schema components.
300 * (Extends xmlSchemaAnnotItem)
301 */
302typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
303typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
304struct _xmlSchemaTreeItem {
305 xmlSchemaTypeType type;
306 xmlSchemaAnnotPtr annot;
307 xmlSchemaTreeItemPtr next;
308 xmlSchemaTreeItemPtr children;
309};
310
311/**
312 * xmlSchemaQNameRef:
313 *
314 * A component reference item (not a schema component)
315 * (Extends xmlSchemaBasicItem)
316 */
317typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
318typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
319struct _xmlSchemaQNameRef {
320 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000321 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000322 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000323 const xmlChar *name;
324 const xmlChar *targetNamespace;
325};
326
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000327/**
328 * xmlSchemaParticle:
329 *
330 * A particle component.
331 * (Extends xmlSchemaTreeItem)
332 */
333typedef struct _xmlSchemaParticle xmlSchemaParticle;
334typedef xmlSchemaParticle *xmlSchemaParticlePtr;
335struct _xmlSchemaParticle {
336 xmlSchemaTypeType type;
337 xmlSchemaAnnotPtr annot;
338 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
339 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
340 int minOccurs;
341 int maxOccurs;
342 xmlNodePtr node;
343};
344
345/**
346 * xmlSchemaModelGroup:
347 *
348 * A model group component.
349 * (Extends xmlSchemaTreeItem)
350 */
351typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
352typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
353struct _xmlSchemaModelGroup {
354 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
355 xmlSchemaAnnotPtr annot;
356 xmlSchemaTreeItemPtr next; /* not used */
357 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
358 xmlNodePtr node;
359};
360
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000361#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000362/**
363 * xmlSchemaModelGroupDef:
364 *
365 * A model group definition component.
366 * (Extends xmlSchemaTreeItem)
367 */
368typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
369typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
370struct _xmlSchemaModelGroupDef {
371 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
372 xmlSchemaAnnotPtr annot;
373 xmlSchemaTreeItemPtr next; /* not used */
374 xmlSchemaTreeItemPtr children; /* the "model group" */
375 const xmlChar *name;
376 const xmlChar *targetNamespace;
377 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000378 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000379};
380
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000381typedef struct _xmlSchemaIDC xmlSchemaIDC;
382typedef xmlSchemaIDC *xmlSchemaIDCPtr;
383
384/**
385 * xmlSchemaIDCSelect:
386 *
387 * The identity-constraint "field" and "selector" item, holding the
388 * XPath expression.
389 */
390typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
391typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
392struct _xmlSchemaIDCSelect {
393 xmlSchemaIDCSelectPtr next;
394 xmlSchemaIDCPtr idc;
395 int index; /* an index position if significant for IDC key-sequences */
396 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000397 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000398};
399
400/**
401 * xmlSchemaIDC:
402 *
403 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000404 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000405 */
406
407struct _xmlSchemaIDC {
408 xmlSchemaTypeType type;
409 xmlSchemaAnnotPtr annot;
410 xmlSchemaIDCPtr next;
411 xmlNodePtr node;
412 const xmlChar *name;
413 const xmlChar *targetNamespace;
414 xmlSchemaIDCSelectPtr selector;
415 xmlSchemaIDCSelectPtr fields;
416 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000417 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000418};
419
420/**
421 * xmlSchemaIDCAug:
422 *
423 * The augmented IDC information used for validation.
424 */
425typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
426typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
427struct _xmlSchemaIDCAug {
428 xmlSchemaIDCAugPtr next; /* next in a list */
429 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000430 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000431 tables need to be bubbled upwards */
432};
433
434/**
435 * xmlSchemaPSVIIDCKeySequence:
436 *
437 * The key sequence of a node table item.
438 */
439typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
440typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
441struct _xmlSchemaPSVIIDCKey {
442 xmlSchemaTypePtr type;
443 xmlSchemaValPtr compValue;
444};
445
446/**
447 * xmlSchemaPSVIIDCNode:
448 *
449 * The node table item of a node table.
450 */
451typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
452typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
453struct _xmlSchemaPSVIIDCNode {
454 xmlNodePtr node;
455 xmlSchemaPSVIIDCKeyPtr *keys;
456};
457
458/**
459 * xmlSchemaPSVIIDCBinding:
460 *
461 * The identity-constraint binding item of the [identity-constraint table].
462 */
463typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
464typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
465struct _xmlSchemaPSVIIDCBinding {
466 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
467 xmlSchemaIDCPtr definition; /* the IDC definition */
468 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
469 int nbNodes; /* number of entries in the node table */
470 int sizeNodes; /* size of the node table */
471 int nbDupls; /* number of already identified duplicates in the node
472 table */
473 /* int nbKeys; number of keys in each key-sequence */
474};
475
476#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
477#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
478
479#define XPATH_STATE_OBJ_MATCHES -2
480#define XPATH_STATE_OBJ_BLOCKED -3
481
482typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
483typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
484
485/**
486 * xmlSchemaIDCStateObj:
487 *
488 * The state object used to evaluate XPath expressions.
489 */
490typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
491typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
492struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000493 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000494 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000495 int depth; /* depth of creation */
496 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000497 int nbHistory;
498 int sizeHistory;
499 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
500 matcher */
501 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000502 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000503};
504
505#define IDC_MATCHER 0
506
507/**
508 * xmlSchemaIDCMatcher:
509 *
510 * Used to IDC selectors (and fields) successively.
511 */
512struct _xmlSchemaIDCMatcher {
513 int type;
514 int depth; /* the tree depth at creation time */
515 xmlSchemaIDCMatcherPtr next; /* next in the list */
516 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
517 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
518 elements */
519 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000520 int targetDepth;
521};
522
523/*
524* Element info flags.
525*/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000526#define XML_SCHEMA_ELEM_INFO_VALUE_NEEDED 1
527/* #define XML_SCHEMA_ELEM_INFO_ATTR 2 */
528/* #define XML_SCHEMA_ELEM_INFO_ELEM 4 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000529
530/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000531 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000532 *
533 * Holds information of an element node.
534 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000535typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
536typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
537struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000538 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000539 int flags; /* combination of node info flags */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000540 xmlNodePtr node;
541 const xmlChar *localName;
542 const xmlChar *namespaceName;
543 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +0000544 xmlSchemaTypePtr decl; /* the element/attribute declaration */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000545 xmlSchemaValPtr value; /* the pre-computed value if any */
546 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
547 for the scope element*/
548 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
549 element */
550};
551
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000552#define XML_SCHEMA_VALID_INVALID_NEG_WILDCARD 1<<0
553
Daniel Veillard4255d502002-04-16 15:50:10 +0000554/**
555 * xmlSchemaValidCtxt:
556 *
557 * A Schemas validation context
558 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000559struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000560 void *userData; /* user specific data block */
561 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000562 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000563 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000564
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000565 xmlSchemaPtr schema; /* The schema in use */
566 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000567 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000568 xmlCharEncoding enc;
569 xmlSAXHandlerPtr sax;
570 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000571
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000572 xmlDocPtr myDoc;
573 int err;
574 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000575
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000576 xmlNodePtr node;
577 xmlNodePtr cur;
578 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000579
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000580 xmlRegExecCtxtPtr regexp;
581 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000582
Daniel Veillard3646d642004-06-02 19:19:14 +0000583 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000584 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000585 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000586 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000587 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000588 xmlNodePtr validationRoot;
589 xmlSchemaParserCtxtPtr pctxt;
590 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000591
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000592 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000593 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000594 int sizeElemInfos;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000595 xmlSchemaNodeInfoPtr nodeInfo; /* the current element information */
596 xmlSchemaNodeInfoPtr attrInfo; /* node infor for the current attribute */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000597
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000598 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
599
600 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
601 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
602
603 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
604 int nbIdcNodes;
605 int sizeIdcNodes;
606
607 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
608 int nbIdcKeys;
609 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000610
611 int flags;
Daniel Veillard4255d502002-04-16 15:50:10 +0000612};
613
Daniel Veillard1d913862003-11-21 00:28:39 +0000614/*
615 * These are the entries in the schemas importSchemas hash table
616 */
617typedef struct _xmlSchemaImport xmlSchemaImport;
618typedef xmlSchemaImport *xmlSchemaImportPtr;
619struct _xmlSchemaImport {
620 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000621 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000622 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000623 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000624};
Daniel Veillard4255d502002-04-16 15:50:10 +0000625
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000626/*
627 * These are the entries associated to includes in a schemas
628 */
629typedef struct _xmlSchemaInclude xmlSchemaInclude;
630typedef xmlSchemaInclude *xmlSchemaIncludePtr;
631struct _xmlSchemaInclude {
632 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000633 const xmlChar *schemaLocation;
634 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000635 const xmlChar *origTargetNamespace;
636 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000637};
638
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000639/**
640 * xmlSchemaSubstGroup:
641 *
642 *
643 */
644typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
645typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
646struct _xmlSchemaSubstGroup {
647 xmlSchemaElementPtr head;
648 xmlSchemaItemListPtr members;
649};
650
Daniel Veillard4255d502002-04-16 15:50:10 +0000651/************************************************************************
652 * *
653 * Some predeclarations *
654 * *
655 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000656
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000657static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
658 xmlSchemaPtr schema,
659 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000660static void
661xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
662 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000663static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000664xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
665static int
666xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000667 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000668 const xmlChar *value,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000669 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000670 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000671 int normalize,
672 int checkNodes);
673static int
674xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
675 xmlSchemaElementPtr elemDecl);
676static int
677xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000678 xmlSchemaWildcardPtr wild);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000679static int
680xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000681static int
682xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
683 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000684static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000685xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
686 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000687static void
688xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000689static int
690xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
691 xmlSchemaTypePtr type,
692 const xmlChar *value,
693 xmlSchemaValPtr *val);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000694static int
695xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000696static xmlSchemaTreeItemPtr
697xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
698 xmlNodePtr node, xmlSchemaTypeType type,
699 int withParticle);
700static const xmlChar *
701xmlSchemaCompTypeToString(xmlSchemaTypeType type);
702static xmlSchemaTypeLinkPtr
703xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
William M. Brack87640d52004-04-17 14:58:15 +0000704
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000705/************************************************************************
706 * *
707 * Datatype error handlers *
708 * *
709 ************************************************************************/
710
711/**
712 * xmlSchemaPErrMemory:
713 * @node: a context node
714 * @extra: extra informations
715 *
716 * Handle an out of memory condition
717 */
718static void
719xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
720 const char *extra, xmlNodePtr node)
721{
722 if (ctxt != NULL)
723 ctxt->nberrors++;
724 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
725 extra);
726}
727
728/**
729 * xmlSchemaPErr:
730 * @ctxt: the parsing context
731 * @node: the context node
732 * @error: the error code
733 * @msg: the error message
734 * @str1: extra data
735 * @str2: extra data
736 *
737 * Handle a parser error
738 */
739static void
740xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
741 const char *msg, const xmlChar * str1, const xmlChar * str2)
742{
743 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000744 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000745 void *data = NULL;
746
747 if (ctxt != NULL) {
748 ctxt->nberrors++;
749 channel = ctxt->error;
750 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000751 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000752 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000753 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000754 error, XML_ERR_ERROR, NULL, 0,
755 (const char *) str1, (const char *) str2, NULL, 0, 0,
756 msg, str1, str2);
757}
758
759/**
760 * xmlSchemaPErr2:
761 * @ctxt: the parsing context
762 * @node: the context node
763 * @node: the current child
764 * @error: the error code
765 * @msg: the error message
766 * @str1: extra data
767 * @str2: extra data
768 *
769 * Handle a parser error
770 */
771static void
772xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
773 xmlNodePtr child, int error,
774 const char *msg, const xmlChar * str1, const xmlChar * str2)
775{
776 if (child != NULL)
777 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
778 else
779 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
780}
781
Daniel Veillard01fa6152004-06-29 17:04:39 +0000782
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000783/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000784 * xmlSchemaPErrExt:
785 * @ctxt: the parsing context
786 * @node: the context node
787 * @error: the error code
788 * @strData1: extra data
789 * @strData2: extra data
790 * @strData3: extra data
791 * @msg: the message
792 * @str1: extra parameter for the message display
793 * @str2: extra parameter for the message display
794 * @str3: extra parameter for the message display
795 * @str4: extra parameter for the message display
796 * @str5: extra parameter for the message display
797 *
798 * Handle a parser error
799 */
800static void
801xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
802 const xmlChar * strData1, const xmlChar * strData2,
803 const xmlChar * strData3, const char *msg, const xmlChar * str1,
804 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
805 const xmlChar * str5)
806{
807
808 xmlGenericErrorFunc channel = NULL;
809 xmlStructuredErrorFunc schannel = NULL;
810 void *data = NULL;
811
812 if (ctxt != NULL) {
813 ctxt->nberrors++;
814 channel = ctxt->error;
815 data = ctxt->userData;
816 schannel = ctxt->serror;
817 }
818 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
819 error, XML_ERR_ERROR, NULL, 0,
820 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000821 (const char *) strData3, 0, 0, msg, str1, str2,
822 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000823}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000824
Daniel Veillard3646d642004-06-02 19:19:14 +0000825
826/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000827 * xmlSchemaVTypeErrMemory:
828 * @node: a context node
829 * @extra: extra informations
830 *
831 * Handle an out of memory condition
832 */
833static void
834xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
835 const char *extra, xmlNodePtr node)
836{
837 if (ctxt != NULL) {
838 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000839 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000840 }
841 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
842 extra);
843}
844
845/**
846 * xmlSchemaVErr3:
847 * @ctxt: the validation context
848 * @node: the context node
849 * @error: the error code
850 * @msg: the error message
851 * @str1: extra data
852 * @str2: extra data
853 * @str3: extra data
854 *
855 * Handle a validation error
856 */
857static void
858xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
859 const char *msg, const xmlChar *str1, const xmlChar *str2,
860 const xmlChar *str3)
861{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000862 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000863 xmlGenericErrorFunc channel = NULL;
864 void *data = NULL;
865
866 if (ctxt != NULL) {
867 ctxt->nberrors++;
868 ctxt->err = error;
869 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000870 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000871 data = ctxt->userData;
872 }
873 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000874 /* Removed, since the old schema error codes have been
875 * substituted for the global error codes.
876 *
877 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
878 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000879 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000880 error, XML_ERR_ERROR, NULL, 0,
881 (const char *) str1, (const char *) str2,
882 (const char *) str3, 0, 0,
883 msg, str1, str2, str3);
884}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000885
886/**
887 * xmlSchemaVErrExt:
888 * @ctxt: the validation context
889 * @node: the context node
890 * @error: the error code
891 * @msg: the message
892 * @str1: extra parameter for the message display
893 * @str2: extra parameter for the message display
894 * @str3: extra parameter for the message display
895 * @str4: extra parameter for the message display
896 * @str5: extra parameter for the message display
897 *
898 * Handle a validation error
899 */
900static void
901xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
902 const char *msg, const xmlChar * str1,
903 const xmlChar * str2, const xmlChar * str3,
904 const xmlChar * str4, const xmlChar * str5)
905{
906 xmlStructuredErrorFunc schannel = NULL;
907 xmlGenericErrorFunc channel = NULL;
908 void *data = NULL;
909
910 if (ctxt != NULL) {
911 ctxt->nberrors++;
912 ctxt->err = error;
913 channel = ctxt->error;
914 schannel = ctxt->serror;
915 data = ctxt->userData;
916 }
917 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000918 /* Removed, since the old schema error codes have been
919 * substituted for the global error codes.
920 *
921 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
922 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000923 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000924 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
925 msg, str1, str2, str3, str4, str5);
926}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000927/**
928 * xmlSchemaVErr:
929 * @ctxt: the validation context
930 * @node: the context node
931 * @error: the error code
932 * @msg: the error message
933 * @str1: extra data
934 * @str2: extra data
935 *
936 * Handle a validation error
937 */
938static void
939xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
940 const char *msg, const xmlChar * str1, const xmlChar * str2)
941{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000942 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000943 xmlGenericErrorFunc channel = NULL;
944 void *data = NULL;
945
946 if (ctxt != NULL) {
947 ctxt->nberrors++;
948 ctxt->err = error;
949 channel = ctxt->error;
950 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000951 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000952 }
953 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000954 /* Removed, since the old schema error codes have been
955 * substituted for the global error codes.
956 *
957 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
958 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000959 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000960 error, XML_ERR_ERROR, NULL, 0,
961 (const char *) str1, (const char *) str2, NULL, 0, 0,
962 msg, str1, str2);
963}
Daniel Veillard4255d502002-04-16 15:50:10 +0000964
Daniel Veillardc0826a72004-08-10 14:17:33 +0000965/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000966 * xmlSchemaGetComponentNode:
967 * @item: a schema component
968 *
969 * Returns node associated with the schema component.
970 * NOTE that such a node need not be available; plus, a component's
971 * node need not to reflect the component directly, since there is no
972 * one-to-one relationship between the XML Schema representation and
973 * the component representation.
974 */
975static xmlNodePtr
976xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
977{
978 switch (item->type) {
979 case XML_SCHEMA_TYPE_ELEMENT:
980 return (((xmlSchemaElementPtr) item)->node);
981 case XML_SCHEMA_TYPE_ATTRIBUTE:
982 return (((xmlSchemaAttributePtr) item)->node);
983 case XML_SCHEMA_TYPE_COMPLEX:
984 case XML_SCHEMA_TYPE_SIMPLE:
985 return (((xmlSchemaTypePtr) item)->node);
986 case XML_SCHEMA_TYPE_ANY:
987 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
988 return (((xmlSchemaWildcardPtr) item)->node);
989 case XML_SCHEMA_TYPE_PARTICLE:
990 return (((xmlSchemaParticlePtr) item)->node);
991 case XML_SCHEMA_TYPE_SEQUENCE:
992 case XML_SCHEMA_TYPE_CHOICE:
993 case XML_SCHEMA_TYPE_ALL:
994 return (((xmlSchemaModelGroupPtr) item)->node);
995 case XML_SCHEMA_TYPE_GROUP:
996 return (((xmlSchemaModelGroupDefPtr) item)->node);
997 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
998 return (((xmlSchemaAttributeGroupPtr) item)->node);
999 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1000 case XML_SCHEMA_TYPE_IDC_KEY:
1001 case XML_SCHEMA_TYPE_IDC_KEYREF:
1002 return (((xmlSchemaIDCPtr) item)->node);
1003 default:
1004 return (NULL);
1005 }
1006}
1007
1008#if 0
1009/**
1010 * xmlSchemaGetNextComponent:
1011 * @item: a schema component
1012 *
1013 * Returns the next sibling of the schema component.
1014 */
1015static xmlSchemaBasicItemPtr
1016xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1017{
1018 switch (item->type) {
1019 case XML_SCHEMA_TYPE_ELEMENT:
1020 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1021 case XML_SCHEMA_TYPE_ATTRIBUTE:
1022 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1023 case XML_SCHEMA_TYPE_COMPLEX:
1024 case XML_SCHEMA_TYPE_SIMPLE:
1025 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1026 case XML_SCHEMA_TYPE_ANY:
1027 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1028 return (NULL);
1029 case XML_SCHEMA_TYPE_PARTICLE:
1030 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1031 case XML_SCHEMA_TYPE_SEQUENCE:
1032 case XML_SCHEMA_TYPE_CHOICE:
1033 case XML_SCHEMA_TYPE_ALL:
1034 return (NULL);
1035 case XML_SCHEMA_TYPE_GROUP:
1036 return (NULL);
1037 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1038 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1039 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1040 case XML_SCHEMA_TYPE_IDC_KEY:
1041 case XML_SCHEMA_TYPE_IDC_KEYREF:
1042 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1043 default:
1044 return (NULL);
1045 }
1046}
1047#endif
1048
1049/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001050 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001051 * @attr: the attribute declaration/use
1052 *
1053 * Returns the name of the attribute; if the attribute
1054 * is a reference, the name of the referenced global type will be returned.
1055 */
1056static const xmlChar *
1057xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
1058{
1059 if (attr->ref != NULL)
1060 return(attr->ref);
1061 else
1062 return(attr->name);
1063}
1064
1065/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001066 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001067 * @type: the type (element or attribute)
1068 *
1069 * Returns the target namespace URI of the type; if the type is a reference,
1070 * the target namespace of the referenced type will be returned.
1071 */
1072static const xmlChar *
1073xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
1074{
1075 if (attr->ref != NULL)
1076 return (attr->refNs);
1077 else
1078 return(attr->targetNamespace);
1079}
1080
1081/**
1082 * xmlSchemaFormatNsUriLocal:
1083 * @buf: the string buffer
1084 * @uri: the namespace URI
1085 * @local: the local name
1086 *
1087 * Returns a representation of the given URI used
1088 * for error reports.
1089 *
1090 * Returns an empty string, if @ns is NULL, a formatted
1091 * string otherwise.
1092 */
1093static const xmlChar*
1094xmlSchemaFormatNsUriLocal(xmlChar **buf,
1095 const xmlChar *uri, const xmlChar *local)
1096{
1097 if (*buf != NULL)
1098 xmlFree(*buf);
1099 if (uri == NULL) {
1100 *buf = xmlStrdup(BAD_CAST "{'");
1101 *buf = xmlStrcat(*buf, local);
1102 } else {
1103 *buf = xmlStrdup(BAD_CAST "{'");
1104 *buf = xmlStrcat(*buf, uri);
1105 *buf = xmlStrcat(*buf, BAD_CAST "', '");
1106 *buf = xmlStrcat(*buf, local);
1107 }
1108 *buf = xmlStrcat(*buf, BAD_CAST "'}");
1109 return ((const xmlChar *) *buf);
1110}
1111
1112/**
1113 * xmlSchemaFormatNsPrefixLocal:
1114 * @buf: the string buffer
1115 * @ns: the namespace
1116 * @local: the local name
1117 *
1118 * Returns a representation of the given URI used
1119 * for error reports.
1120 *
1121 * Returns an empty string, if @ns is NULL, a formatted
1122 * string otherwise.
1123 */
1124static const xmlChar*
1125xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
1126 xmlNsPtr ns, const xmlChar *local)
1127{
1128 if (*buf != NULL) {
1129 xmlFree(*buf);
1130 *buf = NULL;
1131 }
1132 if ((ns == NULL) || (ns->prefix == NULL))
1133 return(local);
1134 else {
1135 *buf = xmlStrdup(ns->prefix);
1136 *buf = xmlStrcat(*buf, BAD_CAST ":");
1137 *buf = xmlStrcat(*buf, local);
1138 }
1139 return ((const xmlChar *) *buf);
1140}
1141
1142/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001143 * xmlSchemaFormatQName:
1144 * @buf: the string buffer
1145 * @namespaceName: the namespace name
1146 * @localName: the local name
1147 *
1148 * Returns the given QName in the format "{namespaceName}localName" or
1149 * just "localName" if @namespaceName is NULL.
1150 *
1151 * Returns the localName if @namespaceName is NULL, a formatted
1152 * string otherwise.
1153 */
1154static const xmlChar*
1155xmlSchemaFormatQName(xmlChar **buf,
1156 const xmlChar *namespaceName,
1157 const xmlChar *localName)
1158{
1159 FREE_AND_NULL(*buf)
1160 if (namespaceName == NULL)
1161 return(localName);
1162
1163 *buf = xmlStrdup(BAD_CAST "{");
1164 *buf = xmlStrcat(*buf, namespaceName);
1165 *buf = xmlStrcat(*buf, BAD_CAST "}");
1166 *buf = xmlStrcat(*buf, localName);
1167
1168 return ((const xmlChar *) *buf);
1169}
1170
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001171static const xmlChar *
1172xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1173{
1174 switch (item->type) {
1175 case XML_SCHEMA_TYPE_ELEMENT:
1176 return (((xmlSchemaElementPtr) item)->name);
1177 case XML_SCHEMA_TYPE_ATTRIBUTE:
1178 return (((xmlSchemaAttributePtr) item)->name);
1179 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1180 return (((xmlSchemaAttributeGroupPtr) item)->name);
1181 case XML_SCHEMA_TYPE_SIMPLE:
1182 case XML_SCHEMA_TYPE_COMPLEX:
1183 return (((xmlSchemaTypePtr) item)->name);
1184 case XML_SCHEMA_TYPE_GROUP:
1185 return (((xmlSchemaModelGroupDefPtr) item)->name);
1186 case XML_SCHEMA_TYPE_IDC_KEY:
1187 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1188 case XML_SCHEMA_TYPE_IDC_KEYREF:
1189 return (((xmlSchemaIDCPtr) item)->name);
1190 default:
1191 /*
1192 * Other components cannot have names.
1193 */
1194 break;
1195 }
1196 return (NULL);
1197}
1198
1199static const xmlChar *
1200xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1201{
1202 switch (item->type) {
1203 case XML_SCHEMA_TYPE_ELEMENT:
1204 return (((xmlSchemaElementPtr) item)->targetNamespace);
1205 case XML_SCHEMA_TYPE_ATTRIBUTE:
1206 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1207 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1208 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1209 case XML_SCHEMA_TYPE_SIMPLE:
1210 case XML_SCHEMA_TYPE_COMPLEX:
1211 return (((xmlSchemaTypePtr) item)->targetNamespace);
1212 case XML_SCHEMA_TYPE_GROUP:
1213 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1214 case XML_SCHEMA_TYPE_IDC_KEY:
1215 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1216 case XML_SCHEMA_TYPE_IDC_KEYREF:
1217 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1218 default:
1219 /*
1220 * Other components cannot have names.
1221 */
1222 break;
1223 }
1224 return (NULL);
1225}
1226
1227static const xmlChar*
1228xmlSchemaGetComponentQName(xmlChar **buf,
1229 void *item)
1230{
1231 return (xmlSchemaFormatQName(buf,
1232 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1233 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1234}
1235
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001236/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001237 * xmlSchemaWildcardPCToString:
1238 * @pc: the type of processContents
1239 *
1240 * Returns a string representation of the type of
1241 * processContents.
1242 */
1243static const xmlChar *
1244xmlSchemaWildcardPCToString(int pc)
1245{
1246 switch (pc) {
1247 case XML_SCHEMAS_ANY_SKIP:
1248 return (BAD_CAST "skip");
1249 case XML_SCHEMAS_ANY_LAX:
1250 return (BAD_CAST "lax");
1251 case XML_SCHEMAS_ANY_STRICT:
1252 return (BAD_CAST "strict");
1253 default:
1254 return (BAD_CAST "invalid process contents");
1255 }
1256}
1257
1258/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001259 * xmlSchemaFormatItemForReport:
1260 * @buf: the string buffer
1261 * @itemDes: the designation of the item
1262 * @itemName: the name of the item
1263 * @item: the item as an object
1264 * @itemNode: the node of the item
1265 * @local: the local name
1266 * @parsing: if the function is used during the parse
1267 *
1268 * Returns a representation of the given item used
1269 * for error reports.
1270 *
1271 * The following order is used to build the resulting
1272 * designation if the arguments are not NULL:
1273 * 1a. If itemDes not NULL -> itemDes
1274 * 1b. If (itemDes not NULL) and (itemName not NULL)
1275 * -> itemDes + itemName
1276 * 2. If the preceding was NULL and (item not NULL) -> item
1277 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1278 *
1279 * If the itemNode is an attribute node, the name of the attribute
1280 * will be appended to the result.
1281 *
1282 * Returns the formatted string and sets @buf to the resulting value.
1283 */
1284static xmlChar*
1285xmlSchemaFormatItemForReport(xmlChar **buf,
1286 const xmlChar *itemDes,
1287 xmlSchemaTypePtr item,
1288 xmlNodePtr itemNode,
1289 int parsing)
1290{
1291 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00001292 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001293
1294 if (*buf != NULL) {
1295 xmlFree(*buf);
1296 *buf = NULL;
1297 }
1298
William M. Brack2f2a6632004-08-20 23:09:47 +00001299 if (itemDes != NULL) {
1300 *buf = xmlStrdup(itemDes);
1301 } else if (item != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001302 switch (item->type) {
1303 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001304 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
1305 *buf = xmlStrdup(BAD_CAST "'anyType'");
1306 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
1307 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
1308 else {
1309 /* *buf = xmlStrdup(BAD_CAST "bi "); */
1310 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
1311 *buf = xmlStrdup(BAD_CAST "'");
1312 *buf = xmlStrcat(*buf, item->name);
1313 *buf = xmlStrcat(*buf, BAD_CAST "'");
1314 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001315 break;
1316 case XML_SCHEMA_TYPE_SIMPLE:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001317 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1318 *buf = xmlStrdup(xmlSchemaElemDesST);
1319 *buf = xmlStrcat(*buf, BAD_CAST " '");
1320 *buf = xmlStrcat(*buf, item->name);
1321 *buf = xmlStrcat(*buf, BAD_CAST "'");
1322 } else {
1323 *buf = xmlStrdup(xmlSchemaElemDesST);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001324 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001325 break;
1326 case XML_SCHEMA_TYPE_COMPLEX:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001327 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1328 *buf = xmlStrdup(xmlSchemaElemDesCT);
1329 *buf = xmlStrcat(*buf, BAD_CAST " '");
1330 *buf = xmlStrcat(*buf, item->name);
1331 *buf = xmlStrcat(*buf, BAD_CAST "'");
1332 } else {
1333 *buf = xmlStrdup(xmlSchemaElemDesCT);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001334 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001335 break;
1336 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1337 xmlSchemaAttributePtr attr;
1338
1339 attr = (xmlSchemaAttributePtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001340 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001341 (attr->ref == NULL)) {
1342 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1343 *buf = xmlStrcat(*buf, BAD_CAST " '");
1344 *buf = xmlStrcat(*buf, attr->name);
1345 *buf = xmlStrcat(*buf, BAD_CAST "'");
1346 } else {
1347 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1348 *buf = xmlStrcat(*buf, BAD_CAST " '");
1349 *buf = xmlStrcat(*buf, attr->refPrefix);
1350 *buf = xmlStrcat(*buf, BAD_CAST ":");
1351 *buf = xmlStrcat(*buf, attr->ref);
1352 *buf = xmlStrcat(*buf, BAD_CAST "'");
1353 }
1354 }
1355 break;
1356 case XML_SCHEMA_TYPE_ELEMENT: {
1357 xmlSchemaElementPtr elem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001358
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001359 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001360 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001361 (elem->ref == NULL)) {
1362 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1363 *buf = xmlStrcat(*buf, BAD_CAST " '");
1364 *buf = xmlStrcat(*buf, elem->name);
1365 *buf = xmlStrcat(*buf, BAD_CAST "'");
1366 } else {
1367 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
1368 *buf = xmlStrcat(*buf, BAD_CAST " '");
1369 *buf = xmlStrcat(*buf, elem->refPrefix);
1370 *buf = xmlStrcat(*buf, BAD_CAST ":");
1371 *buf = xmlStrcat(*buf, elem->ref);
1372 *buf = xmlStrcat(*buf, BAD_CAST "'");
1373 }
1374 }
1375 break;
1376 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1377 case XML_SCHEMA_TYPE_IDC_KEY:
1378 case XML_SCHEMA_TYPE_IDC_KEYREF:
1379 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1380 *buf = xmlStrdup(BAD_CAST "unique '");
1381 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1382 *buf = xmlStrdup(BAD_CAST "key '");
1383 else
1384 *buf = xmlStrdup(BAD_CAST "keyRef '");
1385 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1386 *buf = xmlStrcat(*buf, BAD_CAST "'");
1387 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001388 case XML_SCHEMA_TYPE_ANY:
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001389 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001390 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1391 ((xmlSchemaWildcardPtr) item)->processContents));
1392 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1393 break;
1394 case XML_SCHEMA_FACET_MININCLUSIVE:
1395 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1396 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1397 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1398 case XML_SCHEMA_FACET_TOTALDIGITS:
1399 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1400 case XML_SCHEMA_FACET_PATTERN:
1401 case XML_SCHEMA_FACET_ENUMERATION:
1402 case XML_SCHEMA_FACET_WHITESPACE:
1403 case XML_SCHEMA_FACET_LENGTH:
1404 case XML_SCHEMA_FACET_MAXLENGTH:
1405 case XML_SCHEMA_FACET_MINLENGTH:
1406 *buf = xmlStrdup(BAD_CAST "facet '");
1407 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1408 *buf = xmlStrcat(*buf, BAD_CAST "'");
1409 break;
1410 case XML_SCHEMA_TYPE_NOTATION:
1411 *buf = xmlStrdup(BAD_CAST "notation");
1412 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001413 case XML_SCHEMA_TYPE_GROUP: {
1414 xmlChar *s = NULL;
1415
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001416 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1417 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001418 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&s,
1419 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1420 ((xmlSchemaModelGroupDefPtr) item)->name));
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001421 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001422 FREE_AND_NULL(s)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001423 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001424 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001425 case XML_SCHEMA_TYPE_SEQUENCE:
1426 case XML_SCHEMA_TYPE_CHOICE:
1427 case XML_SCHEMA_TYPE_ALL:
1428 case XML_SCHEMA_TYPE_PARTICLE:
1429 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1430 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001431 default:
William M. Brack2f2a6632004-08-20 23:09:47 +00001432 named = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001433 }
William M. Brack2f2a6632004-08-20 23:09:47 +00001434 } else
1435 named = 0;
1436
1437 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00001438 xmlNodePtr elem;
1439
1440 if (itemNode->type == XML_ATTRIBUTE_NODE)
1441 elem = itemNode->parent;
1442 else
1443 elem = itemNode;
1444 *buf = xmlStrdup(BAD_CAST "Element '");
1445 if (parsing)
1446 *buf = xmlStrcat(*buf, elem->name);
1447 else
1448 *buf = xmlStrcat(*buf,
1449 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
1450 *buf = xmlStrcat(*buf, BAD_CAST "'");
1451 }
1452 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1453 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1454 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
1455 itemNode->ns, itemNode->name));
1456 *buf = xmlStrcat(*buf, BAD_CAST "'");
1457 }
1458 FREE_AND_NULL(str);
1459
1460 return (*buf);
1461}
1462
1463/**
1464 * xmlSchemaPFormatItemDes:
1465 * @buf: the string buffer
1466 * @item: the item as a schema object
1467 * @itemNode: the item as a node
1468 *
1469 * If the pointer to @buf is not NULL and @but holds no value,
1470 * the value is set to a item designation using
1471 * xmlSchemaFormatItemForReport. This one avoids adding
1472 * an attribute designation postfix.
1473 *
1474 * Returns a string of all enumeration elements.
1475 */
1476static void
1477xmlSchemaPRequestItemDes(xmlChar **buf,
1478 xmlSchemaTypePtr item,
1479 xmlNodePtr itemNode)
1480{
1481 if ((buf == 0) || (*buf != NULL))
1482 return;
1483 if (itemNode->type == XML_ATTRIBUTE_NODE)
1484 itemNode = itemNode->parent;
1485 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
1486}
1487
1488/**
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001489 * xmlSchemaGetCanonValueWhtsp:
1490 * @val: the precomputed value
1491 * @retValue: the returned value
1492 * @ws: the whitespace type of the value
1493 *
1494 * Get a the cononical representation of the value.
1495 * The caller has to free the returned retValue.
1496 *
1497 * Returns 0 if the value could be built and -1 in case of
1498 * API errors or if the value type is not supported yet.
1499 */
1500static int
1501xmlSchemaGetCanonValueWhtsp(const xmlChar *value,
1502 xmlSchemaValPtr val,
1503 xmlSchemaWhitespaceValueType ws,
1504 const xmlChar **retValue)
1505{
1506 xmlSchemaValType valType;
1507
1508 if ((retValue == NULL) || (value == NULL) || (val == NULL))
1509 return (-1);
1510 *retValue = NULL;
1511 valType = xmlSchemaGetValType(val);
1512 switch (valType) {
1513 case XML_SCHEMAS_STRING:
1514 if (value == NULL)
1515 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001516 else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1517 *retValue = xmlSchemaCollapseString(value);
1518 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1519 *retValue = xmlSchemaWhiteSpaceReplace(value);
1520 if ((*retValue) == NULL)
1521 *retValue = BAD_CAST xmlStrdup(value);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001522 break;
1523 case XML_SCHEMAS_NORMSTRING:
1524 if (value == NULL)
1525 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
1526 else {
1527 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1528 *retValue = xmlSchemaCollapseString(value);
1529 else
1530 *retValue = xmlSchemaWhiteSpaceReplace(value);
1531 if ((*retValue) == NULL)
1532 *retValue = BAD_CAST xmlStrdup(value);
1533 }
1534 break;
1535 default:
1536 return (xmlSchemaGetCanonValue(val, retValue));
1537 }
1538 return (0);
1539}
1540
1541/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001542 * xmlSchemaFormatFacetEnumSet:
1543 * @buf: the string buffer
1544 * @type: the type holding the enumeration facets
1545 *
1546 * Builds a string consisting of all enumeration elements.
1547 *
1548 * Returns a string of all enumeration elements.
1549 */
1550static const xmlChar *
1551xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
1552{
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001553 xmlSchemaFacetPtr facet;
1554 xmlSchemaWhitespaceValueType ws;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001555 const xmlChar *value = NULL;
1556 int res, found = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001557
1558 if (*buf != NULL)
1559 xmlFree(*buf);
1560 *buf = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001561
1562 do {
1563 /*
1564 * Use the whitespace type of the base type.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001565 */
1566 ws = (xmlSchemaWhitespaceValueType)
1567 xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001568 for (facet = type->facets; facet != NULL; facet = facet->next) {
1569 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1570 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001571 found = 1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001572 res = xmlSchemaGetCanonValueWhtsp(facet->value, facet->val,
1573 ws, &value);
1574 if (res == -1) {
1575 xmlSchemaVErr(NULL, NULL,
1576 XML_SCHEMAV_INTERNAL,
1577 "Internal error: xmlSchemaFormatFacetEnumSet, failed to "
1578 "compute the canonical lexical representation.\n",
1579 NULL, NULL);
1580 if (*buf != NULL)
1581 xmlFree(*buf);
1582 *buf = NULL;
1583 return (NULL);
1584 }
1585 if (*buf == NULL) {
1586 *buf = xmlStrdup(BAD_CAST "'");
1587 *buf = xmlStrcat(*buf, value);
1588 *buf = xmlStrcat(*buf, BAD_CAST "'");
1589 } else {
1590 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1591 *buf = xmlStrcat(*buf, value);
1592 *buf = xmlStrcat(*buf, BAD_CAST "'");
1593 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001594 if (value != NULL) {
1595 xmlFree((xmlChar *)value);
1596 value = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001597 }
1598 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001599 type = type->baseType;
1600 } while ((! found) && (type != NULL) &&
1601 (type->type != XML_SCHEMA_TYPE_BASIC));
1602
Daniel Veillardc0826a72004-08-10 14:17:33 +00001603 return ((const xmlChar *) *buf);
1604}
1605
1606/**
1607 * xmlSchemaVFacetErr:
1608 * @ctxt: the schema validation context
1609 * @error: the error code
1610 * @node: the node to be validated
1611 * @value: the value of the node
1612 * @type: the type holding the facet
1613 * @facet: the facet
1614 * @message: the error message of NULL
1615 * @str1: extra data
1616 * @str2: extra data
1617 * @str3: extra data
1618 *
1619 * Reports a facet validation error.
1620 * TODO: Should this report the value of an element as well?
1621 */
1622static void
1623xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
1624 xmlParserErrors error,
1625 xmlNodePtr node,
1626 const xmlChar *value,
1627 unsigned long length,
1628 xmlSchemaTypePtr type,
1629 xmlSchemaFacetPtr facet,
1630 const char *message,
1631 const xmlChar *str1,
1632 const xmlChar *str2,
1633 const xmlChar *str3)
1634{
1635 xmlChar *str = NULL, *msg = NULL;
1636 xmlSchemaTypeType facetType;
1637
1638 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1639 msg = xmlStrcat(msg, BAD_CAST " [");
1640 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1641 msg = xmlStrcat(msg, BAD_CAST ", facet '");
1642 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1643 facetType = XML_SCHEMA_FACET_ENUMERATION;
1644 /*
1645 * If enumerations are validated, one must not expect the
1646 * facet to be given.
1647 */
1648 } else
1649 facetType = facet->type;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001650 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001651 msg = xmlStrcat(msg, BAD_CAST "']: ");
1652 if (message == NULL) {
1653 /*
1654 * Use a default message.
1655 */
1656 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1657 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1658 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1659
1660 char len[25], actLen[25];
1661
1662 /* FIXME, TODO: What is the max expected string length of the
1663 * this value?
1664 */
1665 if (node->type == XML_ATTRIBUTE_NODE)
1666 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1667 else
1668 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1669
1670 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1671 snprintf(actLen, 24, "%lu", length);
1672
1673 if (facetType == XML_SCHEMA_FACET_LENGTH)
1674 msg = xmlStrcat(msg,
1675 BAD_CAST "this differs from the allowed length of '%s'.\n");
1676 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
1677 msg = xmlStrcat(msg,
1678 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
1679 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
1680 msg = xmlStrcat(msg,
1681 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
1682
1683 if (node->type == XML_ATTRIBUTE_NODE)
1684 xmlSchemaVErrExt(ctxt, node, error,
1685 (const char *) msg,
1686 value, (const xmlChar *) actLen, (const xmlChar *) len,
1687 NULL, NULL);
1688 else
1689 xmlSchemaVErr(ctxt, node, error,
1690 (const char *) msg,
1691 (const xmlChar *) actLen, (const xmlChar *) len);
1692
1693 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
1694 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
1695 "of the set {%s}.\n");
1696 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1697 xmlSchemaFormatFacetEnumSet(&str, type));
1698 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1699 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1700 "by the pattern '%s'.\n");
1701 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001702 facet->value);
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001703 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
1704 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
1705 "minimum value allowed ('%s').\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001706 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001707 facet->value);
1708 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
1709 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
1710 "maximum value allowed ('%s').\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001711 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001712 facet->value);
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001713 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
Daniel Veillardf3598452005-04-05 11:10:45 +00001714 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
1715 "'%s'.\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001716 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1717 facet->value);
1718 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
Daniel Veillardf3598452005-04-05 11:10:45 +00001719 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
1720 "'%s'.\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001721 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1722 facet->value);
Daniel Veillardf3598452005-04-05 11:10:45 +00001723 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001724 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
Daniel Veillardf3598452005-04-05 11:10:45 +00001725 "digits than are allowed ('%s').\n");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001726 xmlSchemaVErr(ctxt, node, error, (const char*) msg, value,
Daniel Veillardf3598452005-04-05 11:10:45 +00001727 facet->value);
1728 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001729 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
Daniel Veillardf3598452005-04-05 11:10:45 +00001730 "digits than are allowed ('%s').\n");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001731 xmlSchemaVErr(ctxt, node, error, (const char*) msg, value,
Daniel Veillardf3598452005-04-05 11:10:45 +00001732 facet->value);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001733 } else if (node->type == XML_ATTRIBUTE_NODE) {
1734 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001735 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001736 } else {
1737 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1738 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1739 }
1740 } else {
1741 msg = xmlStrcat(msg, (const xmlChar *) message);
1742 msg = xmlStrcat(msg, BAD_CAST ".\n");
1743 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1744 }
1745 FREE_AND_NULL(str)
1746 xmlFree(msg);
1747}
1748
1749/**
1750 * xmlSchemaVSimpleTypeErr:
1751 * @ctxt: the schema validation context
1752 * @error: the error code
1753 * @type: the type used for validation
1754 * @node: the node containing the validated value
1755 * @value: the validated value
1756 *
1757 * Reports a simple type validation error.
1758 * TODO: Should this report the value of an element as well?
1759 */
1760static void
1761xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1762 xmlParserErrors error,
1763 xmlNodePtr node,
1764 const xmlChar *value,
1765 xmlSchemaTypePtr type)
1766{
1767 xmlChar *str = NULL, *msg = NULL;
1768
1769 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1770 msg = xmlStrcat(msg, BAD_CAST " [");
1771 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1772 if (node->type == XML_ATTRIBUTE_NODE) {
1773 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1774 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1775 } else {
1776 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1777 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1778 }
1779 FREE_AND_NULL(str)
1780 xmlFree(msg);
1781}
1782
1783/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001784 * xmlSchemaVComplexTypeErr:
1785 * @ctxt: the schema validation context
1786 * @error: the error code
1787 * @node: the node containing the validated value
1788 * @type: the complex type used for validation
1789 * @message: the error message
1790 *
1791 * Reports a complex type validation error.
1792 */
1793static void
1794xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1795 xmlParserErrors error,
1796 xmlNodePtr node,
1797 xmlSchemaTypePtr type,
1798 const char *message)
1799{
1800 xmlChar *str = NULL, *msg = NULL;
1801
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001802 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001803 /* Specify the complex type only if it is global. */
1804 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001805 msg = xmlStrcat(msg, BAD_CAST " [");
1806 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1807 msg = xmlStrcat(msg, BAD_CAST "]");
1808 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001809 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1810 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001811 (const xmlChar *) message, NULL);
1812 FREE_AND_NULL(str)
1813 xmlFree(msg);
1814}
1815
1816/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001817 * xmlSchemaVComplexTypeElemErr:
1818 * @ctxt: the schema validation context
1819 * @error: the error code
1820 * @node: the node containing the validated value
1821 * @type: the complex type used for validation
1822 * @message: the error message
1823 *
1824 * Reports a complex type validation error.
1825 */
1826static void
1827xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1828 xmlParserErrors error,
1829 xmlNodePtr node,
1830 xmlSchemaTypePtr type,
1831 const char *message,
1832 int nbval,
1833 int nbneg,
1834 xmlChar **values)
1835{
1836 xmlChar *str = NULL, *msg = NULL;
1837 xmlChar *localName, *nsName;
1838 const xmlChar *cur, *end;
1839 int i;
1840
1841 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1842 /* Specify the complex type only if it is global. */
1843 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1844 msg = xmlStrcat(msg, BAD_CAST " [");
1845 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1846 msg = xmlStrcat(msg, BAD_CAST "]");
1847 FREE_AND_NULL(str)
1848 }
1849 msg = xmlStrcat(msg, BAD_CAST ": ");
1850 msg = xmlStrcat(msg, (const xmlChar *) message);
1851 /*
1852 * Note that is does not make sense to report that we have a
1853 * wildcard here, since the wildcard might be unfolded into
1854 * multiple transitions.
1855 */
1856 if (nbval + nbneg > 0) {
1857 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001858 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001859 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001860 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001861 nsName = NULL;
1862
1863 for (i = 0; i < nbval + nbneg; i++) {
1864 cur = values[i];
1865 /*
1866 * Get the local name.
1867 */
1868 localName = NULL;
1869
1870 end = cur;
1871 if (*end == '*') {
1872 localName = xmlStrdup(BAD_CAST "*");
1873 *end++;
1874 } else {
1875 while ((*end != 0) && (*end != '|'))
1876 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001877 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001878 }
1879 if (*end != 0) {
1880 *end++;
1881 /*
1882 * Skip "*|*" if they come with negated expressions, since
1883 * they represent the same negated wildcard.
1884 */
1885 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1886 /*
1887 * Get the namespace name.
1888 */
1889 cur = end;
1890 if (*end == '*') {
1891 nsName = xmlStrdup(BAD_CAST "{*}");
1892 } else {
1893 while (*end != 0)
1894 end++;
1895
1896 if (i >= nbval)
1897 nsName = xmlStrdup(BAD_CAST "{##other:");
1898 else
1899 nsName = xmlStrdup(BAD_CAST "{");
1900
1901 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1902 nsName = xmlStrcat(nsName, BAD_CAST "}");
1903 }
1904 str = xmlStrcat(str, BAD_CAST nsName);
1905 FREE_AND_NULL(nsName)
1906 } else {
1907 FREE_AND_NULL(localName);
1908 continue;
1909 }
1910 }
1911 str = xmlStrcat(str, BAD_CAST localName);
1912 FREE_AND_NULL(localName);
1913
1914 if (i < nbval + nbneg -1)
1915 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001916 }
1917 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001918 msg = xmlStrcat(msg, BAD_CAST str);
1919 FREE_AND_NULL(str)
1920 }
1921 msg = xmlStrcat(msg, BAD_CAST ".\n");
1922 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1923 xmlFree(msg);
1924}
1925
1926/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001927 * xmlSchemaPMissingAttrErr:
1928 * @ctxt: the schema validation context
1929 * @ownerDes: the designation of the owner
1930 * @ownerName: the name of the owner
1931 * @ownerItem: the owner as a schema object
1932 * @ownerElem: the owner as an element node
1933 * @node: the parent element node of the missing attribute node
1934 * @type: the corresponding type of the attribute node
1935 *
1936 * Reports an illegal attribute.
1937 */
1938static void
1939xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1940 xmlParserErrors error,
1941 xmlChar **ownerDes,
1942 xmlSchemaTypePtr ownerItem,
1943 xmlNodePtr ownerElem,
1944 const char *name,
1945 const char *message)
1946{
1947 xmlChar *des = NULL;
1948
1949 if (ownerDes == NULL)
1950 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1951 else if (*ownerDes == NULL) {
1952 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1953 des = *ownerDes;
1954 } else
1955 des = *ownerDes;
1956 if (message != NULL)
1957 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1958 else
1959 xmlSchemaPErr(ctxt, ownerElem, error,
1960 "%s: The attribute '%s' is required but missing.\n",
1961 BAD_CAST des, BAD_CAST name);
1962 if (ownerDes == NULL)
1963 FREE_AND_NULL(des);
1964}
1965
William M. Brack2f2a6632004-08-20 23:09:47 +00001966/**
1967 * xmlSchemaCompTypeToString:
1968 * @type: the type of the schema item
1969 *
1970 * Returns the component name of a schema item.
1971 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001972static const xmlChar *
Daniel Veillardc0826a72004-08-10 14:17:33 +00001973xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1974{
1975 switch (type) {
1976 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001977 return(BAD_CAST "simple type definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001978 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001979 return(BAD_CAST "complex type definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001980 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001981 return(BAD_CAST "element declaration");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001982 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001983 return(BAD_CAST "attribute declaration");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001984 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001985 return(BAD_CAST "model group definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001986 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001987 return(BAD_CAST "attribute group definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001988 case XML_SCHEMA_TYPE_NOTATION:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001989 return(BAD_CAST "notation declaration");
1990 case XML_SCHEMA_TYPE_SEQUENCE:
1991 return(BAD_CAST "model group (sequence)");
1992 case XML_SCHEMA_TYPE_CHOICE:
1993 return(BAD_CAST "model group (choice)");
1994 case XML_SCHEMA_TYPE_ALL:
1995 return(BAD_CAST "model group (all)");
1996 case XML_SCHEMA_TYPE_PARTICLE:
1997 return(BAD_CAST "particle");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001998 default:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001999 return(BAD_CAST "Not a schema component");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002000 }
2001}
2002/**
2003 * xmlSchemaPResCompAttrErr:
2004 * @ctxt: the schema validation context
2005 * @error: the error code
2006 * @ownerDes: the designation of the owner
2007 * @ownerItem: the owner as a schema object
2008 * @ownerElem: the owner as an element node
2009 * @name: the name of the attribute holding the QName
2010 * @refName: the referenced local name
2011 * @refURI: the referenced namespace URI
2012 * @message: optional message
2013 *
2014 * Used to report QName attribute values that failed to resolve
2015 * to schema components.
2016 */
2017static void
2018xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2019 xmlParserErrors error,
2020 xmlChar **ownerDes,
2021 xmlSchemaTypePtr ownerItem,
2022 xmlNodePtr ownerElem,
2023 const char *name,
2024 const xmlChar *refName,
2025 const xmlChar *refURI,
2026 xmlSchemaTypeType refType,
2027 const char *refTypeStr)
2028{
2029 xmlChar *des = NULL, *strA = NULL;
2030
2031 if (ownerDes == NULL)
2032 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
2033 else if (*ownerDes == NULL) {
2034 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
2035 des = *ownerDes;
2036 } else
2037 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002038 if (refTypeStr == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002039 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002040 xmlSchemaPErrExt(ctxt, ownerElem, error,
2041 NULL, NULL, NULL,
2042 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
2043 "%s.\n", BAD_CAST des, BAD_CAST name,
2044 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
2045 BAD_CAST refTypeStr, NULL);
2046 if (ownerDes == NULL)
2047 FREE_AND_NULL(des)
2048 FREE_AND_NULL(strA)
2049}
2050
William M. Brack2f2a6632004-08-20 23:09:47 +00002051/**
2052 * xmlSchemaPCustomAttrErr:
2053 * @ctxt: the schema parser context
2054 * @error: the error code
2055 * @ownerDes: the designation of the owner
2056 * @ownerItem: the owner as a schema object
2057 * @attr: the illegal attribute node
2058 *
2059 * Reports an illegal attribute during the parse.
2060 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002061static void
2062xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00002063 xmlParserErrors error,
2064 xmlChar **ownerDes,
2065 xmlSchemaTypePtr ownerItem,
2066 xmlAttrPtr attr,
2067 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002068{
2069 xmlChar *des = NULL;
2070
2071 if (ownerDes == NULL)
2072 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2073 else if (*ownerDes == NULL) {
2074 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2075 des = *ownerDes;
2076 } else
2077 des = *ownerDes;
2078 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2079 "%s, attribute '%s': %s.\n",
2080 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2081 if (ownerDes == NULL)
2082 FREE_AND_NULL(des);
2083}
2084
2085/**
2086 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002087 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002088 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002089 * @ownerDes: the designation of the attribute's owner
2090 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00002091 * @attr: the illegal attribute node
2092 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002093 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002094 */
2095static void
2096xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2097 xmlParserErrors error,
2098 xmlChar **ownerDes,
2099 xmlSchemaTypePtr ownerItem,
2100 xmlAttrPtr attr)
2101{
2102 xmlChar *des = NULL, *strA = NULL;
2103
2104 if (ownerDes == NULL)
2105 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2106 else if (*ownerDes == NULL) {
2107 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2108 des = *ownerDes;
2109 } else
2110 des = *ownerDes;
2111 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2112 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2113 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2114 if (ownerDes == NULL)
2115 FREE_AND_NULL(des);
2116 FREE_AND_NULL(strA);
2117}
2118
William M. Brack2f2a6632004-08-20 23:09:47 +00002119/**
2120 * xmlSchemaPAquireDes:
2121 * @des: the first designation
2122 * @itemDes: the second designation
2123 * @item: the schema item
2124 * @itemElem: the node of the schema item
2125 *
2126 * Creates a designation for an item.
2127 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002128static void
2129xmlSchemaPAquireDes(xmlChar **des,
2130 xmlChar **itemDes,
2131 xmlSchemaTypePtr item,
2132 xmlNodePtr itemElem)
2133{
2134 if (itemDes == NULL)
2135 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
2136 else if (*itemDes == NULL) {
2137 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
2138 *des = *itemDes;
2139 } else
2140 *des = *itemDes;
2141}
2142
William M. Brack2f2a6632004-08-20 23:09:47 +00002143/**
2144 * xmlSchemaPCustomErr:
2145 * @ctxt: the schema parser context
2146 * @error: the error code
2147 * @itemDes: the designation of the schema item
2148 * @item: the schema item
2149 * @itemElem: the node of the schema item
2150 * @message: the error message
2151 * @str1: an optional param for the error message
2152 * @str2: an optional param for the error message
2153 * @str3: an optional param for the error message
2154 *
2155 * Reports an error during parsing.
2156 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002157static void
2158xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2159 xmlParserErrors error,
2160 xmlChar **itemDes,
2161 xmlSchemaTypePtr item,
2162 xmlNodePtr itemElem,
2163 const char *message,
2164 const xmlChar *str1,
2165 const xmlChar *str2,
2166 const xmlChar *str3)
2167{
2168 xmlChar *des = NULL, *msg = NULL;
2169
2170 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
2171 msg = xmlStrdup(BAD_CAST "%s: ");
2172 msg = xmlStrcat(msg, (const xmlChar *) message);
2173 msg = xmlStrcat(msg, BAD_CAST ".\n");
2174 if ((itemElem == NULL) && (item != NULL))
2175 itemElem = item->node;
2176 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2177 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2178 if (itemDes == NULL)
2179 FREE_AND_NULL(des);
2180 FREE_AND_NULL(msg);
2181}
2182
William M. Brack2f2a6632004-08-20 23:09:47 +00002183/**
2184 * xmlSchemaPCustomErr:
2185 * @ctxt: the schema parser context
2186 * @error: the error code
2187 * @itemDes: the designation of the schema item
2188 * @item: the schema item
2189 * @itemElem: the node of the schema item
2190 * @message: the error message
2191 * @str1: the optional param for the error message
2192 *
2193 * Reports an error during parsing.
2194 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002195static void
2196xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2197 xmlParserErrors error,
2198 xmlChar **itemDes,
2199 xmlSchemaTypePtr item,
2200 xmlNodePtr itemElem,
2201 const char *message,
2202 const xmlChar *str1)
2203{
2204 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2205 str1, NULL, NULL);
2206}
2207
William M. Brack2f2a6632004-08-20 23:09:47 +00002208/**
2209 * xmlSchemaPAttrUseErr:
2210 * @ctxt: the schema parser context
2211 * @error: the error code
2212 * @itemDes: the designation of the schema type
2213 * @item: the schema type
2214 * @itemElem: the node of the schema type
2215 * @attr: the invalid schema attribute
2216 * @message: the error message
2217 * @str1: the optional param for the error message
2218 *
2219 * Reports an attribute use error during parsing.
2220 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002221static void
2222xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
2223 xmlParserErrors error,
2224 xmlChar **itemDes,
2225 xmlSchemaTypePtr item,
2226 xmlNodePtr itemElem,
2227 const xmlSchemaAttributePtr attr,
2228 const char *message,
2229 const xmlChar *str1)
2230{
2231 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
2232
2233 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
2234 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
2235 xmlSchemaGetAttrName(attr));
2236 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
2237 msg = xmlStrcat(msg, (const xmlChar *) message);
2238 msg = xmlStrcat(msg, BAD_CAST ".\n");
2239 if ((itemElem == NULL) && (item != NULL))
2240 itemElem = item->node;
2241 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2242 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
2243 if (itemDes == NULL)
2244 FREE_AND_NULL(des);
2245 FREE_AND_NULL(strA);
2246 xmlFree(msg);
2247}
2248
William M. Brack2f2a6632004-08-20 23:09:47 +00002249/**
2250 * xmlSchemaPIllegalFacetAtomicErr:
2251 * @ctxt: the schema parser context
2252 * @error: the error code
2253 * @itemDes: the designation of the type
2254 * @item: the schema type
2255 * @baseItem: the base type of type
2256 * @facet: the illegal facet
2257 *
2258 * Reports an illegal facet for atomic simple types.
2259 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002260static void
2261xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
2262 xmlParserErrors error,
2263 xmlChar **itemDes,
2264 xmlSchemaTypePtr item,
2265 xmlSchemaTypePtr baseItem,
2266 xmlSchemaFacetPtr facet)
2267{
2268 xmlChar *des = NULL, *strT = NULL;
2269
2270 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2271 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2272 "%s: The facet '%s' is not allowed on types derived from the "
2273 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002274 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002275 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
2276 NULL, NULL);
2277 if (itemDes == NULL)
2278 FREE_AND_NULL(des);
2279 FREE_AND_NULL(strT);
2280}
2281
William M. Brack2f2a6632004-08-20 23:09:47 +00002282/**
2283 * xmlSchemaPIllegalFacetListUnionErr:
2284 * @ctxt: the schema parser context
2285 * @error: the error code
2286 * @itemDes: the designation of the schema item involved
2287 * @item: the schema item involved
2288 * @facet: the illegal facet
2289 *
2290 * Reports an illegal facet for <list> and <union>.
2291 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002292static void
2293xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
2294 xmlParserErrors error,
2295 xmlChar **itemDes,
2296 xmlSchemaTypePtr item,
2297 xmlSchemaFacetPtr facet)
2298{
2299 xmlChar *des = NULL, *strT = NULL;
2300
2301 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2302 xmlSchemaPErr(ctxt, item->node, error,
2303 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002304 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002305 if (itemDes == NULL)
2306 FREE_AND_NULL(des);
2307 FREE_AND_NULL(strT);
2308}
2309
2310/**
2311 * xmlSchemaPMutualExclAttrErr:
2312 * @ctxt: the schema validation context
2313 * @error: the error code
2314 * @elemDes: the designation of the parent element node
2315 * @attr: the bad attribute node
2316 * @type: the corresponding type of the attribute node
2317 *
2318 * Reports an illegal attribute.
2319 */
2320static void
2321xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2322 xmlParserErrors error,
2323 xmlChar **ownerDes,
2324 xmlSchemaTypePtr ownerItem,
2325 xmlAttrPtr attr,
2326 const char *name1,
2327 const char *name2)
2328{
2329 xmlChar *des = NULL;
2330
2331 if (ownerDes == NULL)
2332 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2333 else if (*ownerDes == NULL) {
2334 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2335 des = *ownerDes;
2336 } else
2337 des = *ownerDes;
2338 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2339 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
2340 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2341 if (ownerDes == NULL)
2342 FREE_AND_NULL(des)
2343}
2344
2345/**
2346 * xmlSchemaPSimpleTypeErr:
2347 * @ctxt: the schema validation context
2348 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002349 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002350 * @ownerDes: the designation of the owner
2351 * @ownerItem: the schema object if existent
2352 * @node: the validated node
2353 * @value: the validated value
2354 *
2355 * Reports a simple type validation error.
2356 * TODO: Should this report the value of an element as well?
2357 */
2358static void
2359xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2360 xmlParserErrors error,
2361 xmlChar **ownerDes,
2362 xmlSchemaTypePtr ownerItem,
2363 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002364 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002365 const char *typeDes,
2366 const xmlChar *value,
2367 const char *message,
2368 const xmlChar *str1,
2369 const xmlChar *str2)
2370{
William M. Brack2f2a6632004-08-20 23:09:47 +00002371 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002372
2373 if (ownerDes == NULL)
2374 xmlSchemaPRequestItemDes(&des, ownerItem, node);
2375 else if (*ownerDes == NULL) {
2376 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
2377 des = *ownerDes;
2378 } else
2379 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00002380 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002381 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002382 if (message == NULL) {
2383 /*
2384 * Use default messages.
2385 */
2386 if (node->type == XML_ATTRIBUTE_NODE) {
2387 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2388 "%s, attribute '%s' [%s]: The value '%s' is not "
2389 "valid.\n",
2390 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
2391 node->name), BAD_CAST typeDes, value, NULL);
2392 } else {
2393 xmlSchemaPErr(ctxt, node, error,
2394 "%s [%s]: The character content is not valid.\n",
2395 BAD_CAST des, BAD_CAST typeDes);
2396 }
2397 } else {
2398 xmlChar *msg;
2399
2400 msg = xmlStrdup(BAD_CAST "%s");
2401 if (node->type == XML_ATTRIBUTE_NODE)
2402 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
2403 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
2404 msg = xmlStrcat(msg, (const xmlChar *) message);
2405 msg = xmlStrcat(msg, BAD_CAST ".\n");
2406 if (node->type == XML_ATTRIBUTE_NODE) {
2407 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2408 (const char *) msg,
2409 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
2410 node->ns, node->name), BAD_CAST typeDes, str1, str2);
2411 } else {
2412 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2413 (const char *) msg,
2414 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
2415 }
2416 xmlFree(msg);
2417 }
2418 /* Cleanup. */
2419 FREE_AND_NULL(strA)
2420 FREE_AND_NULL(strT)
2421 if (ownerDes == NULL)
2422 FREE_AND_NULL(des)
2423}
2424
William M. Brack2f2a6632004-08-20 23:09:47 +00002425/**
2426 * xmlSchemaPContentErr:
2427 * @ctxt: the schema parser context
2428 * @error: the error code
2429 * @onwerDes: the designation of the holder of the content
2430 * @ownerItem: the owner item of the holder of the content
2431 * @ownerElem: the node of the holder of the content
2432 * @child: the invalid child node
2433 * @message: the optional error message
2434 * @content: the optional string describing the correct content
2435 *
2436 * Reports an error concerning the content of a schema element.
2437 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002438static void
2439xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
2440 xmlParserErrors error,
2441 xmlChar **ownerDes,
2442 xmlSchemaTypePtr ownerItem,
2443 xmlNodePtr ownerElem,
2444 xmlNodePtr child,
2445 const char *message,
2446 const char *content)
2447{
2448 xmlChar *des = NULL;
2449
2450 if (ownerDes == NULL)
2451 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
2452 else if (*ownerDes == NULL) {
2453 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
2454 des = *ownerDes;
2455 } else
2456 des = *ownerDes;
2457 if (message != NULL)
2458 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2459 "%s: %s.\n",
2460 BAD_CAST des, BAD_CAST message);
2461 else {
2462 if (content != NULL) {
2463 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2464 "%s: The content is not valid. Expected is %s.\n",
2465 BAD_CAST des, BAD_CAST content);
2466 } else {
2467 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2468 "%s: The content is not valid.\n",
2469 BAD_CAST des, NULL);
2470 }
2471 }
2472 if (ownerDes == NULL)
2473 FREE_AND_NULL(des)
2474}
2475
2476/**
2477 * xmlSchemaVIllegalAttrErr:
2478 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002479 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00002480 * @attr: the illegal attribute node
2481 *
2482 * Reports an illegal attribute.
2483 */
2484static void
2485xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002486 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002487 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002488{
2489 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002490
2491 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
2492 error,
2493 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002494 "%s: The attribute '%s' is not allowed.\n",
2495 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
2496 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2497 FREE_AND_NULL(strE)
2498 FREE_AND_NULL(strA)
2499}
2500
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002501
2502static int
2503xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2504{
2505 switch (item->type) {
2506 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002507 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002508 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2509 return(1);
2510 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002511 case XML_SCHEMA_TYPE_GROUP:
2512 return (1);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002513 case XML_SCHEMA_TYPE_ELEMENT:
2514 if ( ((xmlSchemaElementPtr) item)->flags &
2515 XML_SCHEMAS_ELEM_GLOBAL)
2516 return(1);
2517 break;
2518 case XML_SCHEMA_TYPE_ATTRIBUTE:
2519 if ( ((xmlSchemaAttributePtr) item)->flags &
2520 XML_SCHEMAS_ATTR_GLOBAL)
2521 return(1);
2522 break;
2523 /* Note that attribute groups are always global. */
2524 default:
2525 return(1);
2526 }
2527 return (0);
2528}
2529
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002530
2531static void
2532xmlSchemaStreamVCustomErr(xmlSchemaValidCtxtPtr vctxt,
2533 xmlParserErrors error,
2534 xmlSchemaNodeInfoPtr nodeInfo,
2535 xmlSchemaTypePtr type,
2536 const char *message,
2537 const xmlChar *str1,
2538 const xmlChar *str2)
2539{
2540 xmlChar *msg = NULL, *str = NULL;
2541
2542 msg = xmlStrdup(BAD_CAST "Element '");
2543
2544 if (vctxt->elemInfos[vctxt->depth] != nodeInfo) {
2545 xmlSchemaNodeInfoPtr elemInfo;
2546 /*
2547 * The node info is an attribute info.
2548 */
2549 elemInfo = vctxt->elemInfos[vctxt->depth];
2550 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2551 elemInfo->namespaceName, elemInfo->localName));
2552 msg = xmlStrcat(msg, BAD_CAST "', ");
2553 msg = xmlStrcat(msg, BAD_CAST "attribute '");
2554 }
2555 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2556 nodeInfo->namespaceName, nodeInfo->localName));
2557 msg = xmlStrcat(msg, BAD_CAST "'");
2558
2559 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2560 msg = xmlStrcat(msg, BAD_CAST " [");
2561 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str,
2562 NULL, type, NULL, 0));
2563 msg = xmlStrcat(msg, BAD_CAST "]");
2564 }
2565 msg = xmlStrcat(msg, BAD_CAST ": ");
2566
2567 msg = xmlStrcat(msg, (const xmlChar *) message);
2568 msg = xmlStrcat(msg, BAD_CAST ".\n");
2569 xmlSchemaVErr(vctxt, nodeInfo->node, error, (const char *) msg,
2570 str1, str2);
2571 FREE_AND_NULL(msg)
2572 FREE_AND_NULL(str)
2573}
2574
William M. Brack2f2a6632004-08-20 23:09:47 +00002575/**
2576 * xmlSchemaVCustomErr:
2577 * @ctxt: the schema validation context
2578 * @error: the error code
2579 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002580 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00002581 * @message: the error message
2582 * @str1: the optional param for the message
2583 *
2584 * Reports a validation error.
2585 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002586static void
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00002587xmlSchemaVCustomErrExt(xmlSchemaValidCtxtPtr ctxt,
2588 xmlParserErrors error,
2589 xmlNodePtr node,
2590 xmlSchemaTypePtr type,
2591 const char *message,
2592 const xmlChar *str1,
2593 const xmlChar *str2,
2594 const xmlChar *str3)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002595{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002596 xmlChar *msg = NULL, *str = NULL;
2597
2598 if (node == NULL) {
2599 xmlSchemaVErr(ctxt, NULL,
2600 XML_SCHEMAV_INTERNAL,
2601 "Internal error: xmlSchemaVCustomErr, no node "
2602 "given.\n", NULL, NULL);
2603 return;
2604 }
2605 /* TODO: Are the HTML and DOCB doc nodes expected here? */
2606 if (node->type != XML_DOCUMENT_NODE) {
2607 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002608 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002609 msg = xmlStrcat(msg, BAD_CAST " [");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00002610 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL,
2611 type, NULL, 0));
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002612 msg = xmlStrcat(msg, BAD_CAST "]");
2613 }
2614 msg = xmlStrcat(msg, BAD_CAST ": ");
2615 } else
2616 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002617 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002618 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00002619 xmlSchemaVErrExt(ctxt, node, error, (const char *) msg, str1, str2,
2620 str3, NULL, NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002621 FREE_AND_NULL(msg)
2622 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002623}
2624
William M. Brack2f2a6632004-08-20 23:09:47 +00002625/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00002626 * xmlSchemaVCustomErr:
2627 * @ctxt: the schema validation context
2628 * @error: the error code
2629 * @node: the validated node
2630 * @type: the schema type of the validated node
2631 * @message: the error message
2632 * @str1: the optional param for the message
2633 *
2634 * Reports a validation error.
2635 */
2636static void
2637xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
2638 xmlParserErrors error,
2639 xmlNodePtr node,
2640 xmlSchemaTypePtr type,
2641 const char *message,
2642 const xmlChar *str1)
2643{
2644 xmlSchemaVCustomErrExt(ctxt, error, node, type, message, str1, NULL, NULL);
2645}
2646
2647/**
William M. Brack2f2a6632004-08-20 23:09:47 +00002648 * xmlSchemaVWildcardErr:
2649 * @ctxt: the schema validation context
2650 * @error: the error code
2651 * @node: the validated node
2652 * @wild: the wildcard used
2653 * @message: the error message
2654 *
2655 * Reports an validation-by-wildcard error.
2656 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002657static void
2658xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
2659 xmlParserErrors error,
2660 xmlNodePtr node,
2661 xmlSchemaWildcardPtr wild,
2662 const char *message)
2663{
2664 xmlChar *des = NULL, *msg = NULL;
2665
2666 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00002667 msg = xmlStrdup(BAD_CAST "%s [");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002668 msg = xmlStrcat(msg, xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002669 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002670 msg = xmlStrcat(msg, (const xmlChar *) message);
2671 msg = xmlStrcat(msg, BAD_CAST ".\n");
2672 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
2673 FREE_AND_NULL(des);
2674 FREE_AND_NULL(msg);
2675}
2676
2677/**
2678 * xmlSchemaVMissingAttrErr:
2679 * @ctxt: the schema validation context
2680 * @node: the parent element node of the missing attribute node
2681 * @type: the corresponding type of the attribute node
2682 *
2683 * Reports an illegal attribute.
2684 */
2685static void
2686xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
2687 xmlNodePtr elem,
2688 xmlSchemaAttributePtr type)
2689{
2690 const xmlChar *name, *uri;
2691 xmlChar *strE = NULL, *strA = NULL;
2692
2693 if (type->ref != NULL) {
2694 name = type->ref;
2695 uri = type->refNs;
2696 } else {
2697 name = type->name;
2698 uri = type->targetNamespace;
2699 }
2700 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002701 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
2702 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002703 "%s: The attribute %s is required but missing.\n",
2704 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
2705 xmlSchemaFormatNsUriLocal(&strA, uri, name));
2706 FREE_AND_NULL(strE)
2707 FREE_AND_NULL(strA)
2708}
2709
Daniel Veillard4255d502002-04-16 15:50:10 +00002710/************************************************************************
2711 * *
2712 * Allocation functions *
2713 * *
2714 ************************************************************************/
2715
2716/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002717 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002718 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002719 *
2720 * Allocate a new Schema structure.
2721 *
2722 * Returns the newly allocated structure or NULL in case or error
2723 */
2724static xmlSchemaPtr
2725xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2726{
2727 xmlSchemaPtr ret;
2728
2729 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2730 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002731 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002732 return (NULL);
2733 }
2734 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002735 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002736 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002737
2738 return (ret);
2739}
2740
2741/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002742 * xmlSchemaNewSchema:
2743 * @ctxt: a schema validation context
2744 *
2745 * Allocate a new Schema structure.
2746 *
2747 * Returns the newly allocated structure or NULL in case or error
2748 */
2749static xmlSchemaAssemblePtr
2750xmlSchemaNewAssemble(void)
2751{
2752 xmlSchemaAssemblePtr ret;
2753
2754 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2755 if (ret == NULL) {
2756 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2757 return (NULL);
2758 }
2759 memset(ret, 0, sizeof(xmlSchemaAssemble));
2760 ret->items = NULL;
2761 return (ret);
2762}
2763
2764/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002765 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002766 *
2767 * Allocate a new Facet structure.
2768 *
2769 * Returns the newly allocated structure or NULL in case or error
2770 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002771xmlSchemaFacetPtr
2772xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002773{
2774 xmlSchemaFacetPtr ret;
2775
2776 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2777 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002778 return (NULL);
2779 }
2780 memset(ret, 0, sizeof(xmlSchemaFacet));
2781
2782 return (ret);
2783}
2784
2785/**
2786 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002787 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002788 * @node: a node
2789 *
2790 * Allocate a new annotation structure.
2791 *
2792 * Returns the newly allocated structure or NULL in case or error
2793 */
2794static xmlSchemaAnnotPtr
2795xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2796{
2797 xmlSchemaAnnotPtr ret;
2798
2799 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2800 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002801 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002802 return (NULL);
2803 }
2804 memset(ret, 0, sizeof(xmlSchemaAnnot));
2805 ret->content = node;
2806 return (ret);
2807}
2808
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002809static xmlSchemaItemListPtr
2810xmlSchemaNewItemList(void)
2811{
2812 xmlSchemaItemListPtr ret;
2813
2814 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2815 if (ret == NULL) {
2816 xmlSchemaPErrMemory(NULL,
2817 "allocating an item list structure", NULL);
2818 return (NULL);
2819 }
2820 memset(ret, 0, sizeof(xmlSchemaItemList));
2821 return (ret);
2822}
2823
2824/**
2825 * xmlSchemaAddElementSubstitutionMember:
2826 * @pctxt: a schema parser context
2827 * @head: the head of the substitution group
2828 * @member: the new member of the substitution group
2829 *
2830 * Allocate a new annotation structure.
2831 *
2832 * Returns the newly allocated structure or NULL in case or error
2833 */
2834static int
2835xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2836 xmlSchemaElementPtr head,
2837 xmlSchemaElementPtr member)
2838{
2839 xmlSchemaSubstGroupPtr substGroup;
2840
2841 if (pctxt == NULL)
2842 return (-1);
2843
2844 if (pctxt->substGroups == NULL) {
2845 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2846 if (pctxt->substGroups == NULL)
2847 return (-1);
2848 }
2849 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2850 head->targetNamespace);
2851 if (substGroup == NULL) {
2852 int res;
2853
2854 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2855 if (substGroup == NULL) {
2856 xmlSchemaPErrMemory(NULL,
2857 "xmlSchemaAddElementSubstitution, allocating a substitution "
2858 "group container",
2859 NULL);
2860 return (-1);
2861 }
2862 substGroup->members = xmlSchemaNewItemList();
2863 if (substGroup->members == NULL) {
2864 xmlFree(substGroup);
2865 return (-1);
2866 }
2867 substGroup->head = head;
2868
2869 res = xmlHashAddEntry2(pctxt->substGroups,
2870 head->name, head->targetNamespace, substGroup);
2871 if (res != 0) {
2872 xmlFree(substGroup->members);
2873 xmlFree(substGroup);
2874 xmlSchemaPErr(pctxt, member->node,
2875 XML_SCHEMAP_INTERNAL,
2876 "Internal error: xmlSchemaAddElementSubstitution, "
2877 "failed to add a new substitution group container for "
2878 "'%s'.\n", head->name, NULL);
2879 return (-1);
2880 }
2881 }
2882 if (substGroup->members->items == NULL) {
2883 substGroup->members->items = (void **) xmlMalloc(
2884 5 * sizeof(xmlSchemaElementPtr));
2885 if (substGroup->members->items == NULL) {
2886 xmlSchemaPErrMemory(NULL,
2887 "allocating list of substitution group members", NULL);
2888 return (-1);
2889 }
2890 substGroup->members->sizeItems = 5;
2891 } else if (substGroup->members->sizeItems <=
2892 substGroup->members->nbItems) {
2893 substGroup->members->sizeItems *= 2;
2894 substGroup->members->items = (void **) xmlRealloc(
2895 substGroup->members->items,
2896 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2897 if (substGroup->members->items == NULL) {
2898 xmlSchemaPErrMemory(NULL,
2899 "re-allocating list of substitution group members", NULL);
2900 substGroup->members->sizeItems = 0;
2901 return (-1);
2902 }
2903 }
2904 ((xmlSchemaElementPtr *) substGroup->members->items)
2905 [substGroup->members->nbItems++] = (void *) member;
2906 return (0);
2907}
2908
2909/**
2910 * xmlSchemaGetElementSubstitutionGroup:
2911 * @pctxt: a schema parser context
2912 * @head: the head of the substitution group
2913 * @member: the new member of the substitution group
2914 *
2915 * Allocate a new annotation structure.
2916 *
2917 * Returns the newly allocated structure or NULL in case or error
2918 */
2919static xmlSchemaSubstGroupPtr
2920xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2921 xmlSchemaElementPtr head)
2922{
2923 if (pctxt == NULL)
2924 return (NULL);
2925
2926 if (pctxt->substGroups == NULL)
2927 return (NULL);
2928
2929 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2930 head->name, head->targetNamespace));
2931}
2932
2933/**
2934 * xmlSchemaFreeItemList:
2935 * @annot: a schema type structure
2936 *
2937 * Deallocate a annotation structure
2938 */
2939static void
2940xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2941{
2942 if (list == NULL)
2943 return;
2944 if (list->items != NULL)
2945 xmlFree(list->items);
2946 xmlFree(list);
2947}
2948
Daniel Veillard4255d502002-04-16 15:50:10 +00002949/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002950 * xmlSchemaFreeAnnot:
2951 * @annot: a schema type structure
2952 *
2953 * Deallocate a annotation structure
2954 */
2955static void
2956xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2957{
2958 if (annot == NULL)
2959 return;
2960 xmlFree(annot);
2961}
2962
2963/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002964 * xmlSchemaFreeImport:
2965 * @import: a schema import structure
2966 *
2967 * Deallocate an import structure
2968 */
2969static void
2970xmlSchemaFreeImport(xmlSchemaImportPtr import)
2971{
2972 if (import == NULL)
2973 return;
2974
2975 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002976 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002977 xmlFree(import);
2978}
2979
2980/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002981 * xmlSchemaFreeInclude:
2982 * @include: a schema include structure
2983 *
2984 * Deallocate an include structure
2985 */
2986static void
2987xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2988{
2989 if (include == NULL)
2990 return;
2991
2992 xmlFreeDoc(include->doc);
2993 xmlFree(include);
2994}
2995
2996/**
2997 * xmlSchemaFreeIncludeList:
2998 * @includes: a schema include list
2999 *
3000 * Deallocate an include structure
3001 */
3002static void
3003xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
3004{
3005 xmlSchemaIncludePtr next;
3006
3007 while (includes != NULL) {
3008 next = includes->next;
3009 xmlSchemaFreeInclude(includes);
3010 includes = next;
3011 }
3012}
3013
3014/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003015 * xmlSchemaFreeNotation:
3016 * @schema: a schema notation structure
3017 *
3018 * Deallocate a Schema Notation structure.
3019 */
3020static void
3021xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3022{
3023 if (nota == NULL)
3024 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003025 xmlFree(nota);
3026}
3027
3028/**
3029 * xmlSchemaFreeAttribute:
3030 * @schema: a schema attribute structure
3031 *
3032 * Deallocate a Schema Attribute structure.
3033 */
3034static void
3035xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3036{
3037 if (attr == NULL)
3038 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003039 if (attr->annot != NULL)
3040 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003041 if (attr->defVal != NULL)
3042 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003043 xmlFree(attr);
3044}
3045
3046/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003047 * xmlSchemaFreeWildcardNsSet:
3048 * set: a schema wildcard namespace
3049 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003050 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003051 */
3052static void
3053xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3054{
3055 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00003056
Daniel Veillard3646d642004-06-02 19:19:14 +00003057 while (set != NULL) {
3058 next = set->next;
3059 xmlFree(set);
3060 set = next;
3061 }
3062}
3063
3064/**
3065 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003066 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003067 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003068 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003069 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003070void
Daniel Veillard3646d642004-06-02 19:19:14 +00003071xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3072{
3073 if (wildcard == NULL)
3074 return;
3075 if (wildcard->annot != NULL)
3076 xmlSchemaFreeAnnot(wildcard->annot);
3077 if (wildcard->nsSet != NULL)
3078 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3079 if (wildcard->negNsSet != NULL)
3080 xmlFree(wildcard->negNsSet);
3081 xmlFree(wildcard);
3082}
3083
3084/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003085 * xmlSchemaFreeAttributeGroup:
3086 * @schema: a schema attribute group structure
3087 *
3088 * Deallocate a Schema Attribute Group structure.
3089 */
3090static void
3091xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
3092{
3093 if (attr == NULL)
3094 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00003095 if (attr->annot != NULL)
3096 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003097 xmlFree(attr);
3098}
3099
3100/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003101 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003102 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00003103 *
3104 * Deallocate a list of schema attribute uses.
3105 */
3106static void
3107xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3108{
3109 xmlSchemaAttributeLinkPtr next;
3110
3111 while (attrUse != NULL) {
3112 next = attrUse->next;
3113 xmlFree(attrUse);
3114 attrUse = next;
3115 }
3116}
3117
3118/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003119 * xmlSchemaFreeQNameRef:
3120 * @item: a QName reference structure
3121 *
3122 * Deallocatea a QName reference structure.
3123 */
3124static void
3125xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3126{
3127 xmlFree(item);
3128}
3129
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003130/**
3131 * xmlSchemaFreeQNameRef:
3132 * @item: a QName reference structure
3133 *
3134 * Deallocatea a QName reference structure.
3135 */
3136static void
3137xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3138{
3139 if (item == NULL)
3140 return;
3141 if (item->members != NULL)
3142 xmlSchemaFreeItemList(item->members);
3143 xmlFree(item);
3144}
3145
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003146static int
3147xmlSchemaAddVolatile(xmlSchemaPtr schema,
3148 xmlSchemaBasicItemPtr item)
3149{
3150 xmlSchemaItemListPtr list;
3151
3152 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003153 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003154 if (schema->volatiles == NULL) {
3155 xmlSchemaPErrMemory(NULL,
3156 "allocating list of volatiles", NULL);
3157 return (-1);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003158 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003159 }
3160 list = (xmlSchemaItemListPtr) schema->volatiles;
3161 if (list->items == NULL) {
3162 list->items = (void **) xmlMalloc(
3163 20 * sizeof(xmlSchemaBasicItemPtr));
3164 if (list->items == NULL) {
3165 xmlSchemaPErrMemory(NULL,
3166 "allocating new volatile item buffer", NULL);
3167 return (-1);
3168 }
3169 list->sizeItems = 20;
3170 } else if (list->sizeItems <= list->nbItems) {
3171 list->sizeItems *= 2;
3172 list->items = (void **) xmlRealloc(list->items,
3173 list->sizeItems * sizeof(xmlSchemaTypePtr));
3174 if (list->items == NULL) {
3175 xmlSchemaPErrMemory(NULL,
3176 "growing volatile item buffer", NULL);
3177 list->sizeItems = 0;
3178 return (-1);
3179 }
3180 }
3181 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3182 return (0);
3183}
3184
3185/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003186 * xmlSchemaFreeTypeLinkList:
3187 * @alink: a type link
3188 *
3189 * Deallocate a list of types.
3190 */
3191static void
3192xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3193{
3194 xmlSchemaTypeLinkPtr next;
3195
3196 while (link != NULL) {
3197 next = link->next;
3198 xmlFree(link);
3199 link = next;
3200 }
3201}
3202
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003203static void
3204xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3205{
3206 xmlSchemaIDCStateObjPtr next;
3207 while (sto != NULL) {
3208 next = sto->next;
3209 if (sto->history != NULL)
3210 xmlFree(sto->history);
3211 if (sto->xpathCtxt != NULL)
3212 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3213 xmlFree(sto);
3214 sto = next;
3215 }
3216}
3217
3218/**
3219 * xmlSchemaFreeIDC:
3220 * @idc: a identity-constraint definition
3221 *
3222 * Deallocates an identity-constraint definition.
3223 */
3224static void
3225xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3226{
3227 xmlSchemaIDCSelectPtr cur, prev;
3228
3229 if (idcDef == NULL)
3230 return;
3231 if (idcDef->annot != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003232 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003233 /* Selector */
3234 if (idcDef->selector != NULL) {
3235 if (idcDef->selector->xpathComp != NULL)
3236 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3237 xmlFree(idcDef->selector);
3238 }
3239 /* Fields */
3240 if (idcDef->fields != NULL) {
3241 cur = idcDef->fields;
3242 do {
3243 prev = cur;
3244 cur = cur->next;
3245 if (prev->xpathComp != NULL)
3246 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3247 xmlFree(prev);
3248 } while (cur != NULL);
3249 }
3250 xmlFree(idcDef);
3251}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003252
Daniel Veillard01fa6152004-06-29 17:04:39 +00003253/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003254 * xmlSchemaFreeElement:
3255 * @schema: a schema element structure
3256 *
3257 * Deallocate a Schema Element structure.
3258 */
3259static void
3260xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3261{
3262 if (elem == NULL)
3263 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003264 if (elem->annot != NULL)
3265 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003266 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003267 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003268 if (elem->defVal != NULL)
3269 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003270 xmlFree(elem);
3271}
3272
3273/**
3274 * xmlSchemaFreeFacet:
3275 * @facet: a schema facet structure
3276 *
3277 * Deallocate a Schema Facet structure.
3278 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003279void
Daniel Veillard4255d502002-04-16 15:50:10 +00003280xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3281{
3282 if (facet == NULL)
3283 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003284 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003285 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003286 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003287 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003288 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003289 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003290 xmlFree(facet);
3291}
3292
3293/**
3294 * xmlSchemaFreeType:
3295 * @type: a schema type structure
3296 *
3297 * Deallocate a Schema Type structure.
3298 */
3299void
3300xmlSchemaFreeType(xmlSchemaTypePtr type)
3301{
3302 if (type == NULL)
3303 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003304 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003305 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003306 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003307 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003308
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003309 facet = type->facets;
3310 while (facet != NULL) {
3311 next = facet->next;
3312 xmlSchemaFreeFacet(facet);
3313 facet = next;
3314 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003315 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003316 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3317 if (type->attributeUses != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003318 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003319 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003320 if (type->memberTypes != NULL)
3321 xmlSchemaFreeTypeLinkList(type->memberTypes);
3322 if (type->facetSet != NULL) {
3323 xmlSchemaFacetLinkPtr next, link;
3324
3325 link = type->facetSet;
3326 do {
3327 next = link->next;
3328 xmlFree(link);
3329 link = next;
3330 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003331 }
3332 if (type->contModel != NULL)
3333 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003334 xmlFree(type);
3335}
3336
3337/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003338 * xmlSchemaFreeModelGroupDef:
3339 * @item: a schema model group definition
3340 *
3341 * Deallocates a schema model group definition.
3342 */
3343static void
3344xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3345{
3346 if (item->annot != NULL)
3347 xmlSchemaFreeAnnot(item->annot);
3348 xmlFree(item);
3349}
3350
3351/**
3352 * xmlSchemaFreeModelGroup:
3353 * @item: a schema model group
3354 *
3355 * Deallocates a schema model group structure.
3356 */
3357static void
3358xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3359{
3360 if (item->annot != NULL)
3361 xmlSchemaFreeAnnot(item->annot);
3362 xmlFree(item);
3363}
3364
3365/**
3366 * xmlSchemaFreeParticle:
3367 * @type: a schema type structure
3368 *
3369 * Deallocate a Schema Type structure.
3370 */
3371static void
3372xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3373{
3374 if (item->annot != NULL)
3375 xmlSchemaFreeAnnot(item->annot);
3376 xmlFree(item);
3377}
3378
3379/**
3380 * xmlSchemaFreeMiscComponents:
3381 * @item: a schema component
3382 *
3383 * Deallocates misc. schema component structures.
3384 */
3385static void
3386xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3387{
3388 if (item == NULL)
3389 return;
3390 switch (item->type) {
3391 case XML_SCHEMA_TYPE_PARTICLE:
3392 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3393 return;
3394 case XML_SCHEMA_TYPE_SEQUENCE:
3395 case XML_SCHEMA_TYPE_CHOICE:
3396 case XML_SCHEMA_TYPE_ALL:
3397 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3398 return;
3399 case XML_SCHEMA_TYPE_ANY:
3400 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3401 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3402 break;
3403 default:
3404 /* TODO: This should never be hit. */
3405 TODO
3406 return;
3407 }
3408}
3409
3410static void
3411xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3412{
3413 if (schema->volatiles == NULL)
3414 return;
3415 {
3416 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3417 xmlSchemaTreeItemPtr item;
3418 int i;
3419
3420 for (i = 0; i < list->nbItems; i++) {
3421 if (list->items[i] != NULL) {
3422 item = (xmlSchemaTreeItemPtr) list->items[i];
3423 switch (item->type) {
3424 case XML_SCHEMA_EXTRA_QNAMEREF:
3425 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3426 break;
3427 default:
3428 xmlSchemaFreeMiscComponents(item);
3429 }
3430 }
3431 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003432 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003433 }
3434}
3435/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003436 * xmlSchemaFreeTypeList:
3437 * @type: a schema type structure
3438 *
3439 * Deallocate a Schema Type structure.
3440 */
3441static void
3442xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3443{
3444 xmlSchemaTypePtr next;
3445
3446 while (type != NULL) {
3447 next = type->redef;
3448 xmlSchemaFreeType(type);
3449 type = next;
3450 }
3451}
3452
3453/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003454 * xmlSchemaFree:
3455 * @schema: a schema structure
3456 *
3457 * Deallocate a Schema structure.
3458 */
3459void
3460xmlSchemaFree(xmlSchemaPtr schema)
3461{
3462 if (schema == NULL)
3463 return;
3464
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003465 if (schema->volatiles != NULL)
3466 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003467 if (schema->notaDecl != NULL)
3468 xmlHashFree(schema->notaDecl,
3469 (xmlHashDeallocator) xmlSchemaFreeNotation);
3470 if (schema->attrDecl != NULL)
3471 xmlHashFree(schema->attrDecl,
3472 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3473 if (schema->attrgrpDecl != NULL)
3474 xmlHashFree(schema->attrgrpDecl,
3475 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3476 if (schema->elemDecl != NULL)
3477 xmlHashFree(schema->elemDecl,
3478 (xmlHashDeallocator) xmlSchemaFreeElement);
3479 if (schema->typeDecl != NULL)
3480 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003481 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003482 if (schema->groupDecl != NULL)
3483 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003484 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003485 if (schema->idcDef != NULL)
3486 xmlHashFree(schema->idcDef,
3487 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003488 if (schema->schemasImports != NULL)
3489 xmlHashFree(schema->schemasImports,
3490 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003491 if (schema->includes != NULL) {
3492 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3493 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003494 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003495 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003496 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003497 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003498 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003499 xmlFree(schema);
3500}
3501
3502/************************************************************************
3503 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003504 * Debug functions *
3505 * *
3506 ************************************************************************/
3507
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003508#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003509
Daniel Veillard4255d502002-04-16 15:50:10 +00003510/**
3511 * xmlSchemaElementDump:
3512 * @elem: an element
3513 * @output: the file output
3514 *
3515 * Dump the element
3516 */
3517static void
3518xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003519 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003520 const xmlChar * namespace ATTRIBUTE_UNUSED,
3521 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003522{
3523 if (elem == NULL)
3524 return;
3525
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003526 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3527 fprintf(output, "Particle: %s", name);
3528 fprintf(output, ", term element: %s", elem->ref);
3529 if (elem->refNs != NULL)
3530 fprintf(output, " ns %s", elem->refNs);
3531 } else {
3532 fprintf(output, "Element");
3533 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3534 fprintf(output, " (global)");
3535 fprintf(output, ": %s ", elem->name);
3536 if (namespace != NULL)
3537 fprintf(output, "ns %s", namespace);
3538 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003539 fprintf(output, "\n");
3540 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003541 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003542 if (elem->maxOccurs >= UNBOUNDED)
3543 fprintf(output, "max: unbounded\n");
3544 else if (elem->maxOccurs != 1)
3545 fprintf(output, "max: %d\n", elem->maxOccurs);
3546 else
3547 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003548 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003549 /*
3550 * Misc other properties.
3551 */
3552 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3553 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3554 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3555 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3556 (elem->id != NULL)) {
3557 fprintf(output, " props: ");
3558 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3559 fprintf(output, "[fixed] ");
3560 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3561 fprintf(output, "[default] ");
3562 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3563 fprintf(output, "[abstract] ");
3564 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3565 fprintf(output, "[nillable] ");
3566 if (elem->id != NULL)
3567 fprintf(output, "[id: '%s'] ", elem->id);
3568 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003569 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003570 /*
3571 * Default/fixed value.
3572 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003573 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003574 fprintf(output, " value: '%s'\n", elem->value);
3575 /*
3576 * Type.
3577 */
3578 if (elem->namedType != NULL) {
3579 fprintf(output, " type: %s ", elem->namedType);
3580 if (elem->namedTypeNs != NULL)
3581 fprintf(output, "ns %s\n", elem->namedTypeNs);
3582 else
3583 fprintf(output, "\n");
3584 }
3585 /*
3586 * Substitution group.
3587 */
3588 if (elem->substGroup != NULL) {
3589 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3590 if (elem->substGroupNs != NULL)
3591 fprintf(output, "ns %s\n", elem->substGroupNs);
3592 else
3593 fprintf(output, "\n");
3594 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003595}
3596
3597/**
3598 * xmlSchemaAnnotDump:
3599 * @output: the file output
3600 * @annot: a annotation
3601 *
3602 * Dump the annotation
3603 */
3604static void
3605xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3606{
3607 xmlChar *content;
3608
3609 if (annot == NULL)
3610 return;
3611
3612 content = xmlNodeGetContent(annot->content);
3613 if (content != NULL) {
3614 fprintf(output, " Annot: %s\n", content);
3615 xmlFree(content);
3616 } else
3617 fprintf(output, " Annot: empty\n");
3618}
3619
3620/**
3621 * xmlSchemaTypeDump:
3622 * @output: the file output
3623 * @type: a type structure
3624 *
3625 * Dump a SchemaType structure
3626 */
3627static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003628xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3629{
3630 xmlChar *str = NULL;
3631 xmlSchemaTreeItemPtr term;
3632 char shift[100];
3633 int i;
3634
3635 if (particle == NULL)
3636 return;
3637 for (i = 0;((i < depth) && (i < 25));i++)
3638 shift[2 * i] = shift[2 * i + 1] = ' ';
3639 shift[2 * i] = shift[2 * i + 1] = 0;
3640 fprintf(output, shift);
3641 if (particle->children == NULL) {
3642 fprintf(output, "MISSING particle term\n");
3643 return;
3644 }
3645 term = particle->children;
3646 switch (term->type) {
3647 case XML_SCHEMA_TYPE_ELEMENT:
3648 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
3649 ((xmlSchemaElementPtr)term)->targetNamespace,
3650 ((xmlSchemaElementPtr)term)->name));
3651 break;
3652 case XML_SCHEMA_TYPE_SEQUENCE:
3653 fprintf(output, "SEQUENCE");
3654 break;
3655 case XML_SCHEMA_TYPE_CHOICE:
3656 fprintf(output, "CHOICE");
3657 break;
3658 case XML_SCHEMA_TYPE_ALL:
3659 fprintf(output, "ALL");
3660 break;
3661 case XML_SCHEMA_TYPE_ANY:
3662 fprintf(output, "ANY");
3663 break;
3664 default:
3665 fprintf(output, "UNKNOWN\n");
3666 return;
3667 }
3668 if (particle->minOccurs != 1)
3669 fprintf(output, " min: %d", particle->minOccurs);
3670 if (particle->maxOccurs >= UNBOUNDED)
3671 fprintf(output, " max: unbounded");
3672 else if (particle->maxOccurs != 1)
3673 fprintf(output, " max: %d", particle->maxOccurs);
3674 fprintf(output, "\n");
3675 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3676 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3677 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3678 (term->children != NULL)) {
3679 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3680 output, depth +1);
3681 }
3682 if (particle->next != NULL)
3683 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3684 output, depth);
3685}
3686/**
3687 * xmlSchemaTypeDump:
3688 * @output: the file output
3689 * @type: a type structure
3690 *
3691 * Dump a SchemaType structure
3692 */
3693static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003694xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3695{
3696 if (type == NULL) {
3697 fprintf(output, "Type: NULL\n");
3698 return;
3699 }
3700 fprintf(output, "Type: ");
3701 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003702 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003703 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003704 fprintf(output, "no name ");
3705 if (type->targetNamespace != NULL)
3706 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003707 switch (type->type) {
3708 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003709 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003710 break;
3711 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003712 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003713 break;
3714 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003715 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003716 break;
3717 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003718 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003719 break;
3720 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003721 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003722 break;
3723 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003724 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003725 break;
3726 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003727 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003728 break;
3729 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003730 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003731 break;
3732 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003733 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003734 break;
3735 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003736 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003737 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003738 }
3739 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003740 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003741 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003742 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003743 break;
3744 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003745 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003746 break;
3747 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003748 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003749 break;
3750 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003751 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003752 break;
3753 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003754 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003755 break;
3756 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003757 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003758 break;
3759 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003760 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003761 break;
3762 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003763 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003764 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003765 }
3766 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003767 if (type->base != NULL) {
3768 fprintf(output, " base type: %s", type->base);
3769 if (type->baseNs != NULL)
3770 fprintf(output, " ns %s\n", type->baseNs);
3771 else
3772 fprintf(output, "\n");
3773 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003774 if (type->annot != NULL)
3775 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003776#ifdef DUMP_CONTENT_MODEL
3777 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3778 (type->subtypes != NULL)) {
3779 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3780 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003781 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003782#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003783}
3784
3785/**
3786 * xmlSchemaDump:
3787 * @output: the file output
3788 * @schema: a schema structure
3789 *
3790 * Dump a Schema structure.
3791 */
3792void
3793xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3794{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003795 if (output == NULL)
3796 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003797 if (schema == NULL) {
3798 fprintf(output, "Schemas: NULL\n");
3799 return;
3800 }
3801 fprintf(output, "Schemas: ");
3802 if (schema->name != NULL)
3803 fprintf(output, "%s, ", schema->name);
3804 else
3805 fprintf(output, "no name, ");
3806 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003807 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003808 else
3809 fprintf(output, "no target namespace");
3810 fprintf(output, "\n");
3811 if (schema->annot != NULL)
3812 xmlSchemaAnnotDump(output, schema->annot);
3813
3814 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3815 output);
3816 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003817 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003818}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003819
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003820#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003821/**
3822 * xmlSchemaDebugDumpIDCTable:
3823 * @vctxt: the WXS validation context
3824 *
3825 * Displays the current IDC table for debug purposes.
3826 */
3827static void
3828xmlSchemaDebugDumpIDCTable(FILE * output,
3829 const xmlChar *namespaceName,
3830 const xmlChar *localName,
3831 xmlSchemaPSVIIDCBindingPtr bind)
3832{
3833 xmlChar *str = NULL, *value;
3834 xmlSchemaPSVIIDCNodePtr tab;
3835 xmlSchemaPSVIIDCKeyPtr key;
3836 int i, j, res;
3837
3838 fprintf(output, "IDC: TABLES on %s\n",
3839 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
3840 FREE_AND_NULL(str)
3841
3842 if (bind == NULL)
3843 return;
3844 do {
3845 fprintf(output, "IDC: BINDING %s\n",
3846 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
3847 bind->definition->name));
3848 FREE_AND_NULL(str)
3849 for (i = 0; i < bind->nbNodes; i++) {
3850 tab = bind->nodeTable[i];
3851 fprintf(output, " ( ");
3852 for (j = 0; j < bind->definition->nbFields; j++) {
3853 key = tab->keys[j];
3854 if ((key != NULL) && (key->compValue != NULL)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003855 res = xmlSchemaGetCanonValue(key->compValue, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003856 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003857 fprintf(output, "\"%s\" ", value);
3858 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003859 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003860 if (res == 0)
3861 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003862 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003863 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003864 else
3865 fprintf(output, "(key missing), ");
3866 }
3867 fprintf(output, ")\n");
3868 }
3869 bind = bind->next;
3870 } while (bind != NULL);
3871}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003872#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003873#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003874
3875/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003876 * *
3877 * Utilities *
3878 * *
3879 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003880
Daniel Veillardc0826a72004-08-10 14:17:33 +00003881/**
3882 * xmlSchemaGetPropNode:
3883 * @node: the element node
3884 * @name: the name of the attribute
3885 *
3886 * Seeks an attribute with a name of @name in
3887 * no namespace.
3888 *
3889 * Returns the attribute or NULL if not present.
3890 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003891static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003892xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003893{
3894 xmlAttrPtr prop;
3895
Daniel Veillardc0826a72004-08-10 14:17:33 +00003896 if ((node == NULL) || (name == NULL))
3897 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003898 prop = node->properties;
3899 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003900 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3901 return(prop);
3902 prop = prop->next;
3903 }
3904 return (NULL);
3905}
3906
3907/**
3908 * xmlSchemaGetPropNodeNs:
3909 * @node: the element node
3910 * @uri: the uri
3911 * @name: the name of the attribute
3912 *
3913 * Seeks an attribute with a local name of @name and
3914 * a namespace URI of @uri.
3915 *
3916 * Returns the attribute or NULL if not present.
3917 */
3918static xmlAttrPtr
3919xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3920{
3921 xmlAttrPtr prop;
3922
3923 if ((node == NULL) || (name == NULL))
3924 return(NULL);
3925 prop = node->properties;
3926 while (prop != NULL) {
3927 if ((prop->ns != NULL) &&
3928 xmlStrEqual(prop->name, BAD_CAST name) &&
3929 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003930 return(prop);
3931 prop = prop->next;
3932 }
3933 return (NULL);
3934}
3935
3936static const xmlChar *
3937xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3938{
3939 xmlChar *val;
3940 const xmlChar *ret;
3941
3942 val = xmlNodeGetContent(node);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003943 if (val == NULL)
3944 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003945 ret = xmlDictLookup(ctxt->dict, val, -1);
3946 xmlFree(val);
3947 return(ret);
3948}
3949
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003950/**
3951 * xmlSchemaGetProp:
3952 * @ctxt: the parser context
3953 * @node: the node
3954 * @name: the property name
3955 *
3956 * Read a attribute value and internalize the string
3957 *
3958 * Returns the string or NULL if not present.
3959 */
3960static const xmlChar *
3961xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3962 const char *name)
3963{
3964 xmlChar *val;
3965 const xmlChar *ret;
3966
3967 val = xmlGetProp(node, BAD_CAST name);
3968 if (val == NULL)
3969 return(NULL);
3970 ret = xmlDictLookup(ctxt->dict, val, -1);
3971 xmlFree(val);
3972 return(ret);
3973}
3974
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003975/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003976 * *
3977 * Parsing functions *
3978 * *
3979 ************************************************************************/
3980
3981/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003982 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003983 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003984 * @name: the element name
3985 * @ns: the element namespace
3986 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003987 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003988 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003989 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003990 */
3991static xmlSchemaElementPtr
3992xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003993 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003994{
3995 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003996
3997 if ((name == NULL) || (schema == NULL))
3998 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003999
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004000 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00004001 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004002 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004003 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004004 } else
4005 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00004006 /*
4007 * This one was removed, since top level element declarations have
4008 * the target namespace specified in targetNamespace of the <schema>
4009 * information element, even if elementFormDefault is "unqualified".
4010 */
4011
4012 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004013 if (xmlStrEqual(namespace, schema->targetNamespace))
4014 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
4015 else
4016 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00004017 if ((ret != NULL) &&
4018 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004019 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00004020 }
William M. Bracke7091952004-05-11 15:09:58 +00004021 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004022
William M. Brack2f2a6632004-08-20 23:09:47 +00004023 /*
4024 * Removed since imported components will be hold by the main schema only.
4025 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004026 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004027 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004028 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004029 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004030 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00004031 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00004032 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
4033 return (ret);
4034 } else
4035 ret = NULL;
4036 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004037 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004038#ifdef DEBUG
4039 if (ret == NULL) {
4040 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004041 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004042 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004043 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004044 namespace);
4045 }
4046#endif
4047 return (ret);
4048}
4049
4050/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004051 * xmlSchemaGetType:
4052 * @schema: the schemas context
4053 * @name: the type name
4054 * @ns: the type namespace
4055 *
4056 * Lookup a type in the schemas or the predefined types
4057 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004058 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004059 */
4060static xmlSchemaTypePtr
4061xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004062 const xmlChar * namespace)
4063{
Daniel Veillard4255d502002-04-16 15:50:10 +00004064 xmlSchemaTypePtr ret;
4065
4066 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004067 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004068 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004069 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004070 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004071 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004072 }
4073 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00004074 if (ret != NULL)
4075 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004076 /*
4077 * Removed, since the imported components will be grafted on the
4078 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00004079 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004080 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004081 else
Daniel Veillard1d913862003-11-21 00:28:39 +00004082 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004083 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00004084 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004085 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
4086 return (ret);
4087 } else
4088 ret = NULL;
4089 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004090 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004091#ifdef DEBUG
4092 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004093 if (namespace == NULL)
4094 fprintf(stderr, "Unable to lookup type %s", name);
4095 else
4096 fprintf(stderr, "Unable to lookup type %s:%s", name,
4097 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004098 }
4099#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004100 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004101}
4102
Daniel Veillard3646d642004-06-02 19:19:14 +00004103/**
4104 * xmlSchemaGetAttribute:
4105 * @schema: the context of the schema
4106 * @name: the name of the attribute
4107 * @ns: the target namespace of the attribute
4108 *
4109 * Lookup a an attribute in the schema or imported schemas
4110 *
4111 * Returns the attribute declaration or NULL if not found.
4112 */
4113static xmlSchemaAttributePtr
4114xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
4115 const xmlChar * namespace)
4116{
4117 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004118
4119 if ((name == NULL) || (schema == NULL))
4120 return (NULL);
4121
4122
4123 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4124 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
4125 return (ret);
4126 else
4127 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004128 /*
4129 * Removed, since imported components will be hold by the main schema only.
4130 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004131 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004132 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004133 else
4134 import = xmlHashLookup(schema->schemasImports, namespace);
4135 if (import != NULL) {
4136 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
4137 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4138 return (ret);
4139 } else
4140 ret = NULL;
4141 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004142 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004143#ifdef DEBUG
4144 if (ret == NULL) {
4145 if (namespace == NULL)
4146 fprintf(stderr, "Unable to lookup attribute %s", name);
4147 else
4148 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4149 namespace);
4150 }
4151#endif
4152 return (ret);
4153}
4154
4155/**
4156 * xmlSchemaGetAttributeGroup:
4157 * @schema: the context of the schema
4158 * @name: the name of the attribute group
4159 * @ns: the target namespace of the attribute group
4160 *
4161 * Lookup a an attribute group in the schema or imported schemas
4162 *
4163 * Returns the attribute group definition or NULL if not found.
4164 */
4165static xmlSchemaAttributeGroupPtr
4166xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4167 const xmlChar * namespace)
4168{
4169 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004170
4171 if ((name == NULL) || (schema == NULL))
4172 return (NULL);
4173
4174
4175 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4176 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4177 return (ret);
4178 else
4179 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004180 /*
4181 * Removed since imported components will be hold by the main schema only.
4182 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004183 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004184 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004185 else
4186 import = xmlHashLookup(schema->schemasImports, namespace);
4187 if (import != NULL) {
4188 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4189 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4190 return (ret);
4191 else
4192 ret = NULL;
4193 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004194 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004195#ifdef DEBUG
4196 if (ret == NULL) {
4197 if (namespace == NULL)
4198 fprintf(stderr, "Unable to lookup attribute group %s", name);
4199 else
4200 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4201 namespace);
4202 }
4203#endif
4204 return (ret);
4205}
4206
4207/**
4208 * xmlSchemaGetGroup:
4209 * @schema: the context of the schema
4210 * @name: the name of the group
4211 * @ns: the target namespace of the group
4212 *
4213 * Lookup a group in the schema or imported schemas
4214 *
4215 * Returns the group definition or NULL if not found.
4216 */
4217static xmlSchemaTypePtr
4218xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4219 const xmlChar * namespace)
4220{
4221 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004222
4223 if ((name == NULL) || (schema == NULL))
4224 return (NULL);
4225
Daniel Veillard3646d642004-06-02 19:19:14 +00004226 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004227 /*
4228 * Removed since imported components will be hold by the main schema only.
4229 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004230 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004231 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004232 else
4233 import = xmlHashLookup(schema->schemasImports, namespace);
4234 if (import != NULL) {
4235 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4236 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4237 return (ret);
4238 else
4239 ret = NULL;
4240 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004241 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004242#ifdef DEBUG
4243 if (ret == NULL) {
4244 if (namespace == NULL)
4245 fprintf(stderr, "Unable to lookup group %s", name);
4246 else
4247 fprintf(stderr, "Unable to lookup group %s:%s", name,
4248 namespace);
4249 }
4250#endif
4251 return (ret);
4252}
4253
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004254/**
4255 * xmlSchemaGetNamedComponent:
4256 * @schema: the schema
4257 * @name: the name of the group
4258 * @ns: the target namespace of the group
4259 *
4260 * Lookup a group in the schema or imported schemas
4261 *
4262 * Returns the group definition or NULL if not found.
4263 */
4264static xmlSchemaTreeItemPtr
4265xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4266 xmlSchemaTypeType itemType,
4267 const xmlChar *name,
4268 const xmlChar *targetNs)
4269{
4270 switch (itemType) {
4271 case XML_SCHEMA_TYPE_GROUP:
4272 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4273 name, targetNs));
4274 case XML_SCHEMA_TYPE_ELEMENT:
4275 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4276 name, targetNs));
4277 default:
4278 return (NULL);
4279 }
4280}
4281
Daniel Veillard4255d502002-04-16 15:50:10 +00004282/************************************************************************
4283 * *
4284 * Parsing functions *
4285 * *
4286 ************************************************************************/
4287
4288#define IS_BLANK_NODE(n) \
4289 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
4290
4291/**
4292 * xmlSchemaIsBlank:
4293 * @str: a string
4294 *
4295 * Check if a string is ignorable
4296 *
4297 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4298 */
4299static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004300xmlSchemaIsBlank(xmlChar * str)
4301{
Daniel Veillard4255d502002-04-16 15:50:10 +00004302 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004303 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004304 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00004305 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004306 return (0);
4307 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004308 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004309 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004310}
4311
4312/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004313 * xmlSchemaAddAssembledItem:
4314 * @ctxt: a schema parser context
4315 * @schema: the schema being built
4316 * @item: the item
4317 *
4318 * Add a item to the schema's list of current items.
4319 * This is used if the schema was already constructed and
4320 * new schemata need to be added to it.
4321 * *WARNING* this interface is highly subject to change.
4322 *
4323 * Returns 0 if suceeds and -1 if an internal error occurs.
4324 */
4325static int
4326xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4327 xmlSchemaTypePtr item)
4328{
4329 static int growSize = 100;
4330 xmlSchemaAssemblePtr ass;
4331
4332 ass = ctxt->assemble;
4333 if (ass->sizeItems < 0) {
4334 /* If disabled. */
4335 return (0);
4336 }
4337 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004338 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004339 if (ass->items == NULL) {
4340 xmlSchemaPErrMemory(ctxt,
4341 "allocating new item buffer", NULL);
4342 return (-1);
4343 }
4344 ass->sizeItems = growSize;
4345 } else if (ass->sizeItems <= ass->nbItems) {
4346 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004347 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004348 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4349 if (ass->items == NULL) {
4350 xmlSchemaPErrMemory(ctxt,
4351 "growing item buffer", NULL);
4352 ass->sizeItems = 0;
4353 return (-1);
4354 }
4355 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004356 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004357 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4358 return (0);
4359}
4360
4361/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004362 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004363 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004364 * @schema: the schema being built
4365 * @name: the item name
4366 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004367 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004368 * *WARNING* this interface is highly subject to change
4369 *
4370 * Returns the new struture or NULL in case of error
4371 */
4372static xmlSchemaNotationPtr
4373xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004374 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004375{
4376 xmlSchemaNotationPtr ret = NULL;
4377 int val;
4378
4379 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4380 return (NULL);
4381
4382 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004383 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004384 if (schema->notaDecl == NULL)
4385 return (NULL);
4386
4387 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4388 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004389 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004390 return (NULL);
4391 }
4392 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004393 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004394 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4395 ret);
4396 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004397 /*
4398 * TODO: This should never happen, since a unique name will be computed.
4399 * If it fails, then an other internal error must have occured.
4400 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004401 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4402 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004403 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004404 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004405 xmlFree(ret);
4406 return (NULL);
4407 }
4408 return (ret);
4409}
4410
4411
4412/**
4413 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004414 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004415 * @schema: the schema being built
4416 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004417 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004418 *
4419 * Add an XML schema Attrribute declaration
4420 * *WARNING* this interface is highly subject to change
4421 *
4422 * Returns the new struture or NULL in case of error
4423 */
4424static xmlSchemaAttributePtr
4425xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004426 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004427 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004428{
4429 xmlSchemaAttributePtr ret = NULL;
4430 int val;
4431
4432 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4433 return (NULL);
4434
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004435#ifdef DEBUG
4436 fprintf(stderr, "Adding attribute %s\n", name);
4437 if (namespace != NULL)
4438 fprintf(stderr, " target namespace %s\n", namespace);
4439#endif
4440
Daniel Veillard4255d502002-04-16 15:50:10 +00004441 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004442 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004443 if (schema->attrDecl == NULL)
4444 return (NULL);
4445
4446 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4447 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004448 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004449 return (NULL);
4450 }
4451 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004452 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004453 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004454 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004455 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004456 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004457 if (topLevel) {
4458 xmlSchemaPCustomErr(ctxt,
4459 XML_SCHEMAP_REDEFINED_ATTR,
4460 NULL, NULL, node,
4461 "A global attribute declaration with the name '%s' does "
4462 "already exist", name);
4463 xmlFree(ret);
4464 return (NULL);
4465 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004466 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004467 /*
4468 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4469 * in the scenario:
4470 * 1. multiple top-level complex types have different target
4471 * namespaces but have the SAME NAME; this can happen if
4472 * schemata are imported
4473 * 2. those complex types contain attributes with an equal name
4474 * 3. those attributes are in no namespace
4475 * We will compute a new context string.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004476 */
4477 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004478 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004479 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004480
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004481 if (val != 0) {
4482 xmlSchemaPCustomErr(ctxt,
4483 XML_SCHEMAP_INTERNAL,
4484 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004485 "Internal error: xmlSchemaAddAttribute, "
4486 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004487 "could not be added to the hash.", name);
4488 xmlFree(ret);
4489 return (NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004490 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004491 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004492 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004493 if (ctxt->assemble != NULL)
4494 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004495 return (ret);
4496}
4497
4498/**
4499 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004500 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004501 * @schema: the schema being built
4502 * @name: the item name
4503 *
4504 * Add an XML schema Attrribute Group declaration
4505 *
4506 * Returns the new struture or NULL in case of error
4507 */
4508static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004509xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004510 xmlSchemaPtr schema, const xmlChar * name,
4511 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004512{
4513 xmlSchemaAttributeGroupPtr ret = NULL;
4514 int val;
4515
4516 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4517 return (NULL);
4518
4519 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004520 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004521 if (schema->attrgrpDecl == NULL)
4522 return (NULL);
4523
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004524 ret =
4525 (xmlSchemaAttributeGroupPtr)
4526 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004527 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004528 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004529 return (NULL);
4530 }
4531 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004532 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004533 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004534 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004535 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004536 xmlSchemaPCustomErr(ctxt,
4537 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4538 NULL, NULL, node,
4539 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004540 xmlFree(ret);
4541 return (NULL);
4542 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004543 if (ctxt->assemble != NULL)
4544 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004545 return (ret);
4546}
4547
4548/**
4549 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004550 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004551 * @schema: the schema being built
4552 * @name: the type name
4553 * @namespace: the type namespace
4554 *
4555 * Add an XML schema Element declaration
4556 * *WARNING* this interface is highly subject to change
4557 *
4558 * Returns the new struture or NULL in case of error
4559 */
4560static xmlSchemaElementPtr
4561xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004562 const xmlChar * name, const xmlChar * namespace,
4563 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004564{
4565 xmlSchemaElementPtr ret = NULL;
4566 int val;
4567
4568 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4569 return (NULL);
4570
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004571#ifdef DEBUG
4572 fprintf(stderr, "Adding element %s\n", name);
4573 if (namespace != NULL)
4574 fprintf(stderr, " target namespace %s\n", namespace);
4575#endif
4576
Daniel Veillard4255d502002-04-16 15:50:10 +00004577 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004578 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004579 if (schema->elemDecl == NULL)
4580 return (NULL);
4581
4582 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4583 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004584 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004585 return (NULL);
4586 }
4587 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004588 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004589 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004590 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004591 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004592 if (topLevel) {
4593 xmlSchemaPCustomErr(ctxt,
4594 XML_SCHEMAP_REDEFINED_ELEMENT,
4595 NULL, NULL, node,
4596 "A global element declaration with the name '%s' does "
4597 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004598 xmlFree(ret);
4599 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004600 } else {
4601 char buf[30];
4602
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004603 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004604 val = xmlHashAddEntry3(schema->elemDecl, name,
4605 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004606 if (val != 0) {
4607 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004608 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004609 NULL, NULL, node,
4610 "Internal error: xmlSchemaAddElement, "
4611 "a dublicate element declaration with the name '%s' "
4612 "could not be added to the hash.", name);
4613 xmlFree(ret);
4614 return (NULL);
4615 }
4616 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004617
Daniel Veillard4255d502002-04-16 15:50:10 +00004618 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004619 if (ctxt->assemble != NULL)
4620 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004621 return (ret);
4622}
4623
4624/**
4625 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004626 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004627 * @schema: the schema being built
4628 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004629 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004630 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004631 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004632 * *WARNING* this interface is highly subject to change
4633 *
4634 * Returns the new struture or NULL in case of error
4635 */
4636static xmlSchemaTypePtr
4637xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004638 const xmlChar * name, const xmlChar * namespace,
4639 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004640{
4641 xmlSchemaTypePtr ret = NULL;
4642 int val;
4643
4644 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4645 return (NULL);
4646
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004647#ifdef DEBUG
4648 fprintf(stderr, "Adding type %s\n", name);
4649 if (namespace != NULL)
4650 fprintf(stderr, " target namespace %s\n", namespace);
4651#endif
4652
Daniel Veillard4255d502002-04-16 15:50:10 +00004653 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004654 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004655 if (schema->typeDecl == NULL)
4656 return (NULL);
4657
4658 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4659 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004660 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004661 return (NULL);
4662 }
4663 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004664 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004665 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004666 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004667 if (val != 0) {
4668 if (ctxt->includes == 0) {
4669 xmlSchemaPCustomErr(ctxt,
4670 XML_SCHEMAP_REDEFINED_TYPE,
4671 NULL, NULL, node,
4672 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004673 xmlFree(ret);
4674 return (NULL);
4675 } else {
4676 xmlSchemaTypePtr prev;
4677
4678 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4679 if (prev == NULL) {
4680 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004681 XML_ERR_INTERNAL_ERROR,
4682 "Internal error: xmlSchemaAddType, on type "
4683 "'%s'.\n",
4684 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004685 xmlFree(ret);
4686 return (NULL);
4687 }
4688 ret->redef = prev->redef;
4689 prev->redef = ret;
4690 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004691 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004692 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004693 ret->minOccurs = 1;
4694 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004695 ret->attributeUses = NULL;
4696 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004697 if (ctxt->assemble != NULL)
4698 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004699 return (ret);
4700}
4701
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004702static xmlSchemaQNameRefPtr
4703xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4704 xmlSchemaTypeType refType,
4705 const xmlChar *refName,
4706 const xmlChar *refNs)
4707{
4708 xmlSchemaQNameRefPtr ret;
4709
4710 ret = (xmlSchemaQNameRefPtr)
4711 xmlMalloc(sizeof(xmlSchemaQNameRef));
4712 if (ret == NULL) {
4713 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4714 NULL);
4715 return (NULL);
4716 }
4717 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4718 ret->name = refName;
4719 ret->targetNamespace = refNs;
4720 ret->item = NULL;
4721 ret->itemType = refType;
4722 /*
4723 * Store the reference item in the schema.
4724 */
4725 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4726 return (ret);
4727}
4728
4729/**
4730 * xmlSchemaAddModelGroup:
4731 * @ctxt: a schema parser context
4732 * @schema: the schema being built
4733 * @type: the "compositor" type of the model group
4734 * @container: the internal component name
4735 * @node: the node in the schema doc
4736 *
4737 * Adds a schema model group
4738 * *WARNING* this interface is highly subject to change
4739 *
4740 * Returns the new struture or NULL in case of error
4741 */
4742static xmlSchemaModelGroupPtr
4743xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4744 xmlSchemaTypeType type, const xmlChar **container,
4745 xmlNodePtr node)
4746{
4747 xmlSchemaModelGroupPtr ret = NULL;
4748 xmlChar buf[30];
4749
4750 if ((ctxt == NULL) || (schema == NULL))
4751 return (NULL);
4752
4753#ifdef DEBUG
4754 fprintf(stderr, "Adding model group component\n");
4755#endif
4756 ret = (xmlSchemaModelGroupPtr)
4757 xmlMalloc(sizeof(xmlSchemaModelGroup));
4758 if (ret == NULL) {
4759 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4760 NULL);
4761 return (NULL);
4762 }
4763 ret->type = type;
4764 ret->annot = NULL;
4765 ret->node = node;
4766 ret->children = NULL;
4767 ret->next = NULL;
4768 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4769 if (container != NULL)
4770 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4771 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
4772 if (container != NULL)
4773 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4774 } else {
4775 if (container != NULL)
4776 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4777 }
4778 if (container != NULL)
4779 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4780 /*
4781 * Add to volatile items.
4782 * TODO: this should be changed someday.
4783 */
4784 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4785 xmlFree(ret);
4786 return (NULL);
4787 }
4788 return (ret);
4789}
4790
4791
4792/**
4793 * xmlSchemaAddParticle:
4794 * @ctxt: a schema parser context
4795 * @schema: the schema being built
4796 * @node: the corresponding node in the schema doc
4797 * @min: the minOccurs
4798 * @max: the maxOccurs
4799 *
4800 * Adds an XML schema particle component.
4801 * *WARNING* this interface is highly subject to change
4802 *
4803 * Returns the new struture or NULL in case of error
4804 */
4805static xmlSchemaParticlePtr
4806xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4807 xmlNodePtr node, int min, int max)
4808{
4809 xmlSchemaParticlePtr ret = NULL;
4810 if ((ctxt == NULL) || (schema == NULL))
4811 return (NULL);
4812
4813#ifdef DEBUG
4814 fprintf(stderr, "Adding particle component\n");
4815#endif
4816 ret = (xmlSchemaParticlePtr)
4817 xmlMalloc(sizeof(xmlSchemaParticle));
4818 if (ret == NULL) {
4819 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4820 NULL);
4821 return (NULL);
4822 }
4823 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4824 ret->annot = NULL;
4825 ret->node = node;
4826 ret->minOccurs = min;
4827 ret->maxOccurs = max;
4828 ret->next = NULL;
4829 ret->children = NULL;
4830
4831 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4832 xmlFree(ret);
4833 return (NULL);
4834 }
4835 return (ret);
4836}
4837
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004838/**
4839 * xmlSchemaAddGroup:
4840 * @ctxt: a schema validation context
4841 * @schema: the schema being built
4842 * @name: the group name
4843 *
4844 * Add an XML schema Group definition
4845 *
4846 * Returns the new struture or NULL in case of error
4847 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004848static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004849xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004850 const xmlChar *name, const xmlChar *namespaceName,
4851 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004852{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004853 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004854 int val;
4855
4856 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4857 return (NULL);
4858
4859 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004860 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004861 if (schema->groupDecl == NULL)
4862 return (NULL);
4863
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004864 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004865 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004866 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004867 return (NULL);
4868 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004869 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004870 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004871 ret->type = XML_SCHEMA_TYPE_GROUP;
4872 ret->node = node;
4873 ret->targetNamespace = namespaceName;
4874 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004875 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004876 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004877 XML_SCHEMAP_REDEFINED_GROUP,
4878 NULL, NULL, node,
4879 "A global model group definition with the name '%s' does already "
4880 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004881 xmlFree(ret);
4882 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004883 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004884 if (ctxt->assemble != NULL)
4885 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004886 return (ret);
4887}
4888
Daniel Veillard3646d642004-06-02 19:19:14 +00004889/**
4890 * xmlSchemaNewWildcardNs:
4891 * @ctxt: a schema validation context
4892 *
4893 * Creates a new wildcard namespace constraint.
4894 *
4895 * Returns the new struture or NULL in case of error
4896 */
4897static xmlSchemaWildcardNsPtr
4898xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4899{
4900 xmlSchemaWildcardNsPtr ret;
4901
4902 ret = (xmlSchemaWildcardNsPtr)
4903 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4904 if (ret == NULL) {
4905 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
4906 return (NULL);
4907 }
4908 ret->value = NULL;
4909 ret->next = NULL;
4910 return (ret);
4911}
4912
4913/**
4914 * xmlSchemaAddWildcard:
4915 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004916 * @schema: a schema
4917 *
4918 * Adds a wildcard.
4919 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004920 *
4921 * Returns the new struture or NULL in case of error
4922 */
4923static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004924xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4925 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004926{
4927 xmlSchemaWildcardPtr ret = NULL;
4928
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004929 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004930 return (NULL);
4931
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004932#ifdef DEBUG
4933 fprintf(stderr, "Adding wildcard component\n");
4934#endif
4935
Daniel Veillard3646d642004-06-02 19:19:14 +00004936 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4937 if (ret == NULL) {
4938 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4939 return (NULL);
4940 }
4941 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004942 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004943 ret->minOccurs = 1;
4944 ret->maxOccurs = 1;
4945
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004946 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4947 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4948 "Failed to add a wildcard component to the list", NULL);
4949 xmlFree(ret);
4950 return (NULL);
4951 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004952 return (ret);
4953}
4954
Daniel Veillard4255d502002-04-16 15:50:10 +00004955/************************************************************************
4956 * *
4957 * Utilities for parsing *
4958 * *
4959 ************************************************************************/
4960
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004961#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004962/**
4963 * xmlGetQNameProp:
4964 * @ctxt: a schema validation context
4965 * @node: a subtree containing XML Schema informations
4966 * @name: the attribute name
4967 * @namespace: the result namespace if any
4968 *
4969 * Extract a QName Attribute value
4970 *
4971 * Returns the NCName or NULL if not found, and also update @namespace
4972 * with the namespace URI
4973 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004974static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004975xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004976 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004977{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004978 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004979 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004980 const xmlChar *ret, *prefix;
4981 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004982 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004983
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004984 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004985 attr = xmlSchemaGetPropNode(node, name);
4986 if (attr == NULL)
4987 return (NULL);
4988 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004989
Daniel Veillard4255d502002-04-16 15:50:10 +00004990 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004991 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004992
Daniel Veillardba0153a2004-04-01 10:42:31 +00004993 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004994 ns = xmlSearchNs(node->doc, node, 0);
4995 if (ns) {
4996 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4997 return (val);
4998 }
4999 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005000 ret = xmlSplitQName3(val, &len);
5001 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005002 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005003 }
5004 ret = xmlDictLookup(ctxt->dict, ret, -1);
5005 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00005006
5007 ns = xmlSearchNs(node->doc, node, prefix);
5008 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005009 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
5010 NULL, NULL, (xmlNodePtr) attr,
5011 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005012 "The QName value '%s' has no corresponding namespace "
5013 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005014 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005015 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005016 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005017 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005018}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00005019#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00005020
5021/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005022 * xmlSchemaPValAttrNodeQNameValue:
5023 * @ctxt: a schema parser context
5024 * @schema: the schema context
5025 * @ownerDes: the designation of the parent element
5026 * @ownerItem: the parent as a schema object
5027 * @value: the QName value
5028 * @local: the resulting local part if found, the attribute value otherwise
5029 * @uri: the resulting namespace URI if found
5030 *
5031 * Extracts the local name and the URI of a QName value and validates it.
5032 * This one is intended to be used on attribute values that
5033 * should resolve to schema components.
5034 *
5035 * Returns 0, in case the QName is valid, a positive error code
5036 * if not valid and -1 if an internal error occurs.
5037 */
5038static int
5039xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5040 xmlSchemaPtr schema,
5041 xmlChar **ownerDes,
5042 xmlSchemaTypePtr ownerItem,
5043 xmlAttrPtr attr,
5044 const xmlChar *value,
5045 const xmlChar **uri,
5046 const xmlChar **prefix,
5047 const xmlChar **local)
5048{
5049 const xmlChar *pref;
5050 xmlNsPtr ns;
5051 int len, ret;
5052
5053 *uri = NULL;
5054 *local = NULL;
5055 if (prefix != 0)
5056 *prefix = NULL;
5057 ret = xmlValidateQName(value, 1);
5058 if (ret > 0) {
5059 xmlSchemaPSimpleTypeErr(ctxt,
5060 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5061 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005062 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5063 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005064 NULL, NULL, NULL);
5065 *local = value;
5066 return (ctxt->err);
5067 } else if (ret < 0)
5068 return (-1);
5069
5070 if (!strchr((char *) value, ':')) {
5071 ns = xmlSearchNs(attr->doc, attr->parent, 0);
5072 if (ns)
5073 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5074 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5075 /*
5076 * This one takes care of included schemas with no
5077 * target namespace.
5078 */
5079 *uri = schema->targetNamespace;
5080 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005081 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005082 return (0);
5083 }
5084 /*
5085 * At this point xmlSplitQName3 has to return a local name.
5086 */
5087 *local = xmlSplitQName3(value, &len);
5088 *local = xmlDictLookup(ctxt->dict, *local, -1);
5089 pref = xmlDictLookup(ctxt->dict, value, len);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005090 if (prefix != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00005091 *prefix = pref;
5092 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5093 if (ns == NULL) {
5094 xmlSchemaPSimpleTypeErr(ctxt,
5095 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5096 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005097 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
5098 "The QName value '%s' has no corresponding namespace "
5099 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005100 return (ctxt->err);
5101 } else {
5102 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5103 }
5104 return (0);
5105}
5106
5107/**
5108 * xmlSchemaPValAttrNodeQName:
5109 * @ctxt: a schema parser context
5110 * @schema: the schema context
5111 * @ownerDes: the designation of the owner element
5112 * @ownerItem: the owner as a schema object
5113 * @attr: the attribute node
5114 * @local: the resulting local part if found, the attribute value otherwise
5115 * @uri: the resulting namespace URI if found
5116 *
5117 * Extracts and validates the QName of an attribute value.
5118 * This one is intended to be used on attribute values that
5119 * should resolve to schema components.
5120 *
5121 * Returns 0, in case the QName is valid, a positive error code
5122 * if not valid and -1 if an internal error occurs.
5123 */
5124static int
5125xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5126 xmlSchemaPtr schema,
5127 xmlChar **ownerDes,
5128 xmlSchemaTypePtr ownerItem,
5129 xmlAttrPtr attr,
5130 const xmlChar **uri,
5131 const xmlChar **prefix,
5132 const xmlChar **local)
5133{
5134 const xmlChar *value;
5135
5136 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5137 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5138 ownerDes, ownerItem, attr, value, uri, prefix, local));
5139}
5140
5141/**
5142 * xmlSchemaPValAttrQName:
5143 * @ctxt: a schema parser context
5144 * @schema: the schema context
5145 * @ownerDes: the designation of the parent element
5146 * @ownerItem: the owner as a schema object
5147 * @ownerElem: the parent node of the attribute
5148 * @name: the name of the attribute
5149 * @local: the resulting local part if found, the attribute value otherwise
5150 * @uri: the resulting namespace URI if found
5151 *
5152 * Extracts and validates the QName of an attribute value.
5153 *
5154 * Returns 0, in case the QName is valid, a positive error code
5155 * if not valid and -1 if an internal error occurs.
5156 */
5157static int
5158xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5159 xmlSchemaPtr schema,
5160 xmlChar **ownerDes,
5161 xmlSchemaTypePtr ownerItem,
5162 xmlNodePtr ownerElem,
5163 const char *name,
5164 const xmlChar **uri,
5165 const xmlChar **prefix,
5166 const xmlChar **local)
5167{
5168 xmlAttrPtr attr;
5169
5170 attr = xmlSchemaGetPropNode(ownerElem, name);
5171 if (attr == NULL) {
5172 *local = NULL;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00005173 if (prefix != NULL)
5174 *prefix = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005175 *uri = NULL;
5176 return (0);
5177 }
5178 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5179 ownerDes, ownerItem, attr, uri, prefix, local));
5180}
5181
5182/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005183 * xmlSchemaPValAttrID:
5184 * @ctxt: a schema parser context
5185 * @schema: the schema context
5186 * @ownerDes: the designation of the parent element
5187 * @ownerItem: the owner as a schema object
5188 * @ownerElem: the parent node of the attribute
5189 * @name: the name of the attribute
5190 *
5191 * Extracts and validates the ID of an attribute value.
5192 *
5193 * Returns 0, in case the ID is valid, a positive error code
5194 * if not valid and -1 if an internal error occurs.
5195 */
5196static int
5197xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5198 xmlChar **ownerDes,
5199 xmlSchemaTypePtr ownerItem,
5200 xmlNodePtr ownerElem,
5201 const xmlChar *name)
5202{
5203 int ret;
5204 xmlChar *value;
5205 xmlAttrPtr attr;
5206
5207 value = xmlGetNoNsProp(ownerElem, name);
5208 if (value == NULL)
5209 return (0);
5210
5211 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5212 if (attr == NULL)
5213 return (-1);
5214
5215 ret = xmlValidateNCName(BAD_CAST value, 1);
5216 if (ret == 0) {
5217 /*
5218 * NOTE: the IDness might have already be declared in the DTD
5219 */
5220 if (attr->atype != XML_ATTRIBUTE_ID) {
5221 xmlIDPtr res;
5222 xmlChar *strip;
5223
5224 /*
5225 * TODO: Use xmlSchemaStrip here; it's not exported at this
5226 * moment.
5227 */
5228 strip = xmlSchemaCollapseString(BAD_CAST value);
5229 if (strip != NULL)
5230 value = strip;
5231 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5232 if (res == NULL) {
5233 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5234 xmlSchemaPSimpleTypeErr(ctxt,
5235 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5236 ownerDes, ownerItem, (xmlNodePtr) attr,
5237 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00005238 NULL, NULL, "The ID '%s' is already defined",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005239 BAD_CAST value, NULL);
5240 } else
5241 attr->atype = XML_ATTRIBUTE_ID;
5242 if (strip != NULL)
5243 xmlFree(strip);
5244 }
5245 } else if (ret > 0) {
5246 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5247 xmlSchemaPSimpleTypeErr(ctxt,
5248 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5249 ownerDes, ownerItem, (xmlNodePtr) attr,
5250 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5251 NULL, BAD_CAST value, NULL, NULL, NULL);
5252 }
5253 xmlFree(value);
5254
5255 return (ret);
5256}
5257
5258/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005259 * xmlGetMaxOccurs:
5260 * @ctxt: a schema validation context
5261 * @node: a subtree containing XML Schema informations
5262 *
5263 * Get the maxOccurs property
5264 *
5265 * Returns the default if not found, or the value
5266 */
5267static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005268xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5269 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005270{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005271 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005272 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005273 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005274
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005275 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5276 if (attr == NULL)
5277 return (def);
5278 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005279
5280 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005281 if (max != UNBOUNDED) {
5282 xmlSchemaPSimpleTypeErr(ctxt,
5283 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5284 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5285 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5286 val, NULL, NULL, NULL);
5287 return (def);
5288 } else
5289 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005290 }
5291
5292 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005293 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005294 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005295 if (*cur == 0) {
5296 xmlSchemaPSimpleTypeErr(ctxt,
5297 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5298 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5299 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5300 val, NULL, NULL, NULL);
5301 return (def);
5302 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005303 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005304 ret = ret * 10 + (*cur - '0');
5305 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005306 }
William M. Brack76e95df2003-10-18 16:20:14 +00005307 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005308 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005309 /*
5310 * TODO: Restrict the maximal value to Integer.
5311 */
5312 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
5313 xmlSchemaPSimpleTypeErr(ctxt,
5314 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5315 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5316 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5317 val, NULL, NULL, NULL);
5318 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005319 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005320 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005321}
5322
5323/**
5324 * xmlGetMinOccurs:
5325 * @ctxt: a schema validation context
5326 * @node: a subtree containing XML Schema informations
5327 *
5328 * Get the minOccurs property
5329 *
5330 * Returns the default if not found, or the value
5331 */
5332static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005333xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5334 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005335{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005336 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005337 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005338 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005339
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005340 attr = xmlSchemaGetPropNode(node, "minOccurs");
5341 if (attr == NULL)
5342 return (def);
5343 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005344 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005345 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005346 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005347 if (*cur == 0) {
5348 xmlSchemaPSimpleTypeErr(ctxt,
5349 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5350 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5351 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5352 val, NULL, NULL, NULL);
5353 return (def);
5354 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005355 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005356 ret = ret * 10 + (*cur - '0');
5357 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005358 }
William M. Brack76e95df2003-10-18 16:20:14 +00005359 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005360 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005361 /*
5362 * TODO: Restrict the maximal value to Integer.
5363 */
5364 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
5365 xmlSchemaPSimpleTypeErr(ctxt,
5366 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5367 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5368 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5369 val, NULL, NULL, NULL);
5370 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005371 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005372 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005373}
5374
5375/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005376 * xmlSchemaPGetBoolNodeValue:
5377 * @ctxt: a schema validation context
5378 * @ownerDes: owner designation
5379 * @ownerItem: the owner as a schema item
5380 * @node: the node holding the value
5381 *
5382 * Converts a boolean string value into 1 or 0.
5383 *
5384 * Returns 0 or 1.
5385 */
5386static int
5387xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5388 xmlChar **ownerDes,
5389 xmlSchemaTypePtr ownerItem,
5390 xmlNodePtr node)
5391{
5392 xmlChar *value = NULL;
5393 int res = 0;
5394
5395 value = xmlNodeGetContent(node);
5396 /*
5397 * 3.2.2.1 Lexical representation
5398 * An instance of a datatype that is defined as ·boolean·
5399 * can have the following legal literals {true, false, 1, 0}.
5400 */
5401 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5402 res = 1;
5403 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5404 res = 0;
5405 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5406 res = 1;
5407 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
5408 res = 0;
5409 else {
5410 xmlSchemaPSimpleTypeErr(ctxt,
5411 XML_SCHEMAP_INVALID_BOOLEAN,
5412 ownerDes, ownerItem, node,
5413 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5414 "(1 | 0 | true | false)", BAD_CAST value,
5415 NULL, NULL, NULL);
5416 }
5417 if (value != NULL)
5418 xmlFree(value);
5419 return (res);
5420}
5421
5422/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005423 * xmlGetBooleanProp:
5424 * @ctxt: a schema validation context
5425 * @node: a subtree containing XML Schema informations
5426 * @name: the attribute name
5427 * @def: the default value
5428 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005429 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005430 *
5431 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005432 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005433 */
5434static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00005435xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5436 xmlChar **ownerDes,
5437 xmlSchemaTypePtr ownerItem,
5438 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005439 const char *name, int def)
5440{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005441 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005442
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005443 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005444 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005445 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005446 /*
5447 * 3.2.2.1 Lexical representation
5448 * An instance of a datatype that is defined as ·boolean·
5449 * can have the following legal literals {true, false, 1, 0}.
5450 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005451 if (xmlStrEqual(val, BAD_CAST "true"))
5452 def = 1;
5453 else if (xmlStrEqual(val, BAD_CAST "false"))
5454 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005455 else if (xmlStrEqual(val, BAD_CAST "1"))
5456 def = 1;
5457 else if (xmlStrEqual(val, BAD_CAST "0"))
5458 def = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005459 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005460 xmlSchemaPSimpleTypeErr(ctxt,
5461 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005462 ownerDes, ownerItem,
5463 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
William M. Brack2f2a6632004-08-20 23:09:47 +00005464 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5465 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005466 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005467 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005468}
5469
5470/************************************************************************
5471 * *
5472 * Shema extraction from an Infoset *
5473 * *
5474 ************************************************************************/
5475static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5476 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005477 xmlNodePtr node,
5478 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005479static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5480 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005481 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005482 xmlNodePtr node,
5483 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005484static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5485 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005486 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005487 xmlNodePtr node,
5488 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005489static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5490 ctxt,
5491 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005492 xmlNodePtr node,
5493 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005494static xmlSchemaAttributeGroupPtr
5495xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005496 xmlSchemaPtr schema, xmlNodePtr node,
5497 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005498static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5499 xmlSchemaPtr schema,
5500 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005501static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005502xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5503 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005504
5505/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005506 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005507 *
5508 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005509 * @ownerDes: the designation of the parent element
5510 * @ownerItem: the schema object owner if existent
5511 * @attr: the schema attribute node being validated
5512 * @value: the value
5513 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005514 *
5515 * Validates a value against the given built-in type.
5516 * This one is intended to be used internally for validation
5517 * of schema attribute values during parsing of the schema.
5518 *
5519 * Returns 0 if the value is valid, a positive error code
5520 * number otherwise and -1 in case of an internal or API error.
5521 */
5522static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00005523xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
5524 xmlChar **ownerDes,
5525 xmlSchemaTypePtr ownerItem,
5526 xmlAttrPtr attr,
5527 const xmlChar *value,
5528 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005529{
Daniel Veillard01fa6152004-06-29 17:04:39 +00005530
Daniel Veillardc0826a72004-08-10 14:17:33 +00005531 int ret = 0;
5532
5533 /*
5534 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5535 * one is really meant to be used internally, so better not.
5536 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005537 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005538 return (-1);
5539 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5540 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005541 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005542 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005543 "type '%s' is not a built-in type.\n",
5544 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005545 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005546 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005547 switch (type->builtInType) {
5548 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005549 case XML_SCHEMAS_QNAME:
5550 case XML_SCHEMAS_ANYURI:
5551 case XML_SCHEMAS_TOKEN:
5552 case XML_SCHEMAS_LANGUAGE:
5553 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
5554 break;
5555
5556 /*
5557 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005558 ret = xmlValidateNCName(value, 1);
5559 break;
5560 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00005561 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005562 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005563 "Internal error: xmlSchemaPvalueAttrNode, use "
5564 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
5565 "for extracting QName valueues instead.\n",
5566 NULL, NULL);
5567 return (-1);
5568 case XML_SCHEMAS_ANYURI:
5569 if (value != NULL) {
5570 xmlURIPtr uri = xmlParseURI((const char *) value);
5571 if (uri == NULL)
5572 ret = 1;
5573 else
5574 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005575 }
5576 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005577 case XML_SCHEMAS_TOKEN: {
5578 const xmlChar *cur = value;
5579
5580 if (IS_BLANK_CH(*cur)) {
5581 ret = 1;
5582 } else while (*cur != 0) {
5583 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
5584 ret = 1;
5585 break;
5586 } else if (*cur == ' ') {
5587 cur++;
5588 if ((*cur == 0) || (*cur == ' ')) {
5589 ret = 1;
5590 break;
5591 }
5592 } else {
5593 cur++;
5594 }
5595 }
5596 }
5597 break;
5598 case XML_SCHEMAS_LANGUAGE:
5599 if (xmlCheckLanguageID(value) != 1)
5600 ret = 1;
5601 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005602 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005603 default: {
5604 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005605 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005606 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005607 "valueidation using the type '%s' is not implemented "
5608 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00005609 type->name, NULL);
5610 return (-1);
5611 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005612 }
5613 /*
5614 * TODO: Should we use the S4S error codes instead?
5615 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005616 if (ret < 0) {
5617 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
5618 XML_SCHEMAP_INTERNAL,
5619 "Internal error: xmlSchemaPValAttrNodeValue, "
5620 "failed to validate a schema attribute value.\n",
5621 NULL, NULL);
5622 return (-1);
5623 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005624 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
5625 xmlSchemaPSimpleTypeErr(ctxt,
5626 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
5627 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005628 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005629 NULL, NULL, NULL);
5630 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
5631 } else {
5632 xmlSchemaPSimpleTypeErr(ctxt,
5633 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
5634 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005635 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005636 NULL, NULL, NULL);
5637 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
5638 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005639 }
5640 return (ret);
5641}
5642
5643/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005644 * xmlSchemaPValAttrNode:
5645 *
5646 * @ctxt: a schema parser context
5647 * @ownerDes: the designation of the parent element
5648 * @ownerItem: the schema object owner if existent
5649 * @attr: the schema attribute node being validated
5650 * @type: the built-in type to be validated against
5651 * @value: the resulting value if any
5652 *
5653 * Extracts and validates a value against the given built-in type.
5654 * This one is intended to be used internally for validation
5655 * of schema attribute values during parsing of the schema.
5656 *
5657 * Returns 0 if the value is valid, a positive error code
5658 * number otherwise and -1 in case of an internal or API error.
5659 */
5660static int
5661xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5662 xmlChar **ownerDes,
5663 xmlSchemaTypePtr ownerItem,
5664 xmlAttrPtr attr,
5665 xmlSchemaTypePtr type,
5666 const xmlChar **value)
5667{
5668 const xmlChar *val;
5669
5670 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
5671 return (-1);
5672
5673 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5674 if (value != NULL)
5675 *value = val;
5676
5677 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
5678 val, type));
5679}
5680
5681/**
5682 * xmlSchemaPValAttr:
5683 *
5684 * @ctxt: a schema parser context
5685 * @node: the element node of the attribute
5686 * @ownerDes: the designation of the parent element
5687 * @ownerItem: the schema object owner if existent
5688 * @ownerElem: the owner element node
5689 * @name: the name of the schema attribute node
5690 * @type: the built-in type to be validated against
5691 * @value: the resulting value if any
5692 *
5693 * Extracts and validates a value against the given built-in type.
5694 * This one is intended to be used internally for validation
5695 * of schema attribute values during parsing of the schema.
5696 *
5697 * Returns 0 if the value is valid, a positive error code
5698 * number otherwise and -1 in case of an internal or API error.
5699 */
5700static int
5701xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
5702 xmlChar **ownerDes,
5703 xmlSchemaTypePtr ownerItem,
5704 xmlNodePtr ownerElem,
5705 const char *name,
5706 xmlSchemaTypePtr type,
5707 const xmlChar **value)
5708{
5709 xmlAttrPtr attr;
5710
5711 if ((ctxt == NULL) || (type == NULL)) {
5712 if (value != NULL)
5713 *value = NULL;
5714 return (-1);
5715 }
5716 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5717 if (value != NULL)
5718 *value = NULL;
5719 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005720 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005721 "Internal error: xmlSchemaPValAttr, the given "
5722 "type '%s' is not a built-in type.\n",
5723 type->name, NULL);
5724 return (-1);
5725 }
5726 attr = xmlSchemaGetPropNode(ownerElem, name);
5727 if (attr == NULL) {
5728 if (value != NULL)
5729 *value = NULL;
5730 return (0);
5731 }
5732 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
5733 type, value));
5734}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005735
5736static int
5737xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5738 xmlSchemaPtr schema,
5739 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005740 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005741 const xmlChar *namespaceName)
5742{
5743 if (xmlStrEqual(schema->targetNamespace, namespaceName))
5744 return (1);
5745 if (pctxt->localImports != NULL) {
5746 int i;
5747 for (i = 0; i < pctxt->nbLocalImports; i++)
5748 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5749 return (1);
5750 }
5751 if (namespaceName == NULL)
5752 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005753 NULL, (xmlSchemaTypePtr) item, node,
5754 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005755 "namespace are not valid, since not indicated by an import "
5756 "statement", NULL);
5757 else
5758 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005759 NULL, (xmlSchemaTypePtr) item, node,
5760 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005761 "namespace '%s' are not valid, since not indicated by an import "
5762 "statement", namespaceName);
5763 return (0);
5764}
5765
Daniel Veillardc0826a72004-08-10 14:17:33 +00005766/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005767 * xmlSchemaParseAttrDecls:
5768 * @ctxt: a schema validation context
5769 * @schema: the schema being built
5770 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005771 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005772 *
5773 * parse a XML schema attrDecls declaration corresponding to
5774 * <!ENTITY % attrDecls
5775 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5776 */
5777static xmlNodePtr
5778xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5779 xmlNodePtr child, xmlSchemaTypePtr type)
5780{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005781 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005782
Daniel Veillard4255d502002-04-16 15:50:10 +00005783 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005784 (IS_SCHEMA(child, "attributeGroup"))) {
5785 attr = NULL;
5786 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005787 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005788 } else if (IS_SCHEMA(child, "attributeGroup")) {
5789 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005790 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005791 }
5792 if (attr != NULL) {
5793 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005794 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5795 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5796 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005797 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005798 lastattr = attr;
5799 } else {
5800 lastattr->next = attr;
5801 lastattr = attr;
5802 }
5803 }
5804 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005805 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005806 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005807}
5808
5809/**
5810 * xmlSchemaParseAnnotation:
5811 * @ctxt: a schema validation context
5812 * @schema: the schema being built
5813 * @node: a subtree containing XML Schema informations
5814 *
5815 * parse a XML schema Attrribute declaration
5816 * *WARNING* this interface is highly subject to change
5817 *
William M. Bracke7091952004-05-11 15:09:58 +00005818 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005819 * 1 in case of success.
5820 */
5821static xmlSchemaAnnotPtr
5822xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5823 xmlNodePtr node)
5824{
5825 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005826 xmlNodePtr child = NULL;
5827 xmlAttrPtr attr;
5828 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005829
Daniel Veillardc0826a72004-08-10 14:17:33 +00005830 /*
5831 * INFO: S4S completed.
5832 */
5833 /*
5834 * id = ID
5835 * {any attributes with non-schema namespace . . .}>
5836 * Content: (appinfo | documentation)*
5837 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005838 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5839 return (NULL);
5840 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005841 attr = node->properties;
5842 while (attr != NULL) {
5843 if (((attr->ns == NULL) &&
5844 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
5845 ((attr->ns != NULL) &&
5846 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
5847
5848 xmlSchemaPIllegalAttrErr(ctxt,
5849 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5850 NULL, NULL, attr);
5851 }
5852 attr = attr->next;
5853 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005854 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005855 /*
5856 * And now for the children...
5857 */
5858 child = node->children;
5859 while (child != NULL) {
5860 if (IS_SCHEMA(child, "appinfo")) {
5861 /* TODO: make available the content of "appinfo". */
5862 /*
5863 * source = anyURI
5864 * {any attributes with non-schema namespace . . .}>
5865 * Content: ({any})*
5866 */
5867 attr = child->properties;
5868 while (attr != NULL) {
5869 if (((attr->ns == NULL) &&
5870 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
5871 ((attr->ns != NULL) &&
5872 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005873
Daniel Veillardc0826a72004-08-10 14:17:33 +00005874 xmlSchemaPIllegalAttrErr(ctxt,
5875 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5876 NULL, NULL, attr);
5877 }
5878 attr = attr->next;
5879 }
5880 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5881 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
5882 child = child->next;
5883 } else if (IS_SCHEMA(child, "documentation")) {
5884 /* TODO: make available the content of "documentation". */
5885 /*
5886 * source = anyURI
5887 * {any attributes with non-schema namespace . . .}>
5888 * Content: ({any})*
5889 */
5890 attr = child->properties;
5891 while (attr != NULL) {
5892 if (attr->ns == NULL) {
5893 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
5894 xmlSchemaPIllegalAttrErr(ctxt,
5895 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5896 NULL, NULL, attr);
5897 }
5898 } else {
5899 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5900 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5901 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
5902
5903 xmlSchemaPIllegalAttrErr(ctxt,
5904 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5905 NULL, NULL, attr);
5906 }
5907 }
5908 attr = attr->next;
5909 }
5910 /*
5911 * Attribute "xml:lang".
5912 */
5913 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5914 if (attr != NULL)
5915 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
5916 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
5917 child = child->next;
5918 } else {
5919 if (!barked)
5920 xmlSchemaPContentErr(ctxt,
5921 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5922 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5923 barked = 1;
5924 child = child->next;
5925 }
5926 }
5927
Daniel Veillard4255d502002-04-16 15:50:10 +00005928 return (ret);
5929}
5930
5931/**
5932 * xmlSchemaParseFacet:
5933 * @ctxt: a schema validation context
5934 * @schema: the schema being built
5935 * @node: a subtree containing XML Schema informations
5936 *
5937 * parse a XML schema Facet declaration
5938 * *WARNING* this interface is highly subject to change
5939 *
5940 * Returns the new type structure or NULL in case of error
5941 */
5942static xmlSchemaFacetPtr
5943xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005944 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005945{
5946 xmlSchemaFacetPtr facet;
5947 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005948 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005949
5950 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5951 return (NULL);
5952
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005953 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005954 if (facet == NULL) {
5955 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5956 return (NULL);
5957 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005958 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005959 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005960 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005961 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5962 "Facet %s has no value\n", node->name, NULL);
5963 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005964 return (NULL);
5965 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005966 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005967 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005968 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005969 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005970 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005971 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005972 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005973 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005974 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005975 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005976 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005977 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005978 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005979 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005980 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005981 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005982 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005983 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005984 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005985 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005986 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005987 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5988 } else if (IS_SCHEMA(node, "minLength")) {
5989 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5990 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005991 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5992 "Unknown facet type %s\n", node->name, NULL);
5993 xmlSchemaFreeFacet(facet);
5994 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005995 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005996 xmlSchemaPValAttrID(ctxt, NULL,
5997 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005998 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005999 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6000 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6001 const xmlChar *fixed;
6002
6003 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6004 if (fixed != NULL) {
6005 if (xmlStrEqual(fixed, BAD_CAST "true"))
6006 facet->fixed = 1;
6007 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006008 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006009 child = node->children;
6010
6011 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006012 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6013 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006014 }
6015 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006016 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6017 "Facet %s has unexpected child content\n",
6018 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006019 }
6020 return (facet);
6021}
6022
6023/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006024 * xmlSchemaParseWildcardNs:
6025 * @ctxt: a schema parser context
6026 * @wildc: the wildcard, already created
6027 * @node: a subtree containing XML Schema informations
6028 *
6029 * Parses the attribute "processContents" and "namespace"
6030 * of a xsd:anyAttribute and xsd:any.
6031 * *WARNING* this interface is highly subject to change
6032 *
6033 * Returns 0 if everything goes fine, a positive error code
6034 * if something is not valid and -1 if an internal error occurs.
6035 */
6036static int
6037xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6038 xmlSchemaPtr schema,
6039 xmlSchemaWildcardPtr wildc,
6040 xmlNodePtr node)
6041{
6042 const xmlChar *pc, *ns, *dictnsItem;
6043 int ret = 0;
6044 xmlChar *nsItem;
6045 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6046 xmlAttrPtr attr;
6047
6048 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6049 if ((pc == NULL)
6050 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6051 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6052 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6053 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6054 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6055 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6056 } else {
6057 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006058 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006059 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00006060 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006061 NULL, NULL, NULL);
6062 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006063 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006064 }
6065 /*
6066 * Build the namespace constraints.
6067 */
6068 attr = xmlSchemaGetPropNode(node, "namespace");
6069 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006070 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006071 wildc->any = 1;
6072 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6073 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6074 if (wildc->negNsSet == NULL) {
6075 return (-1);
6076 }
6077 wildc->negNsSet->value = schema->targetNamespace;
6078 } else {
6079 const xmlChar *end, *cur;
6080
6081 cur = ns;
6082 do {
6083 while (IS_BLANK_CH(*cur))
6084 cur++;
6085 end = cur;
6086 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6087 end++;
6088 if (end == cur)
6089 break;
6090 nsItem = xmlStrndup(cur, end - cur);
6091 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6092 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6093 xmlSchemaPSimpleTypeErr(ctxt,
6094 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6095 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006096 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006097 "((##any | ##other) | List of (anyURI | "
6098 "(##targetNamespace | ##local)))",
6099 nsItem, NULL, NULL, NULL);
6100 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6101 } else {
6102 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6103 dictnsItem = schema->targetNamespace;
6104 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6105 dictnsItem = NULL;
6106 } else {
6107 /*
6108 * Validate the item (anyURI).
6109 */
6110 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
6111 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6112 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6113 }
6114 /*
6115 * Avoid dublicate namespaces.
6116 */
6117 tmp = wildc->nsSet;
6118 while (tmp != NULL) {
6119 if (dictnsItem == tmp->value)
6120 break;
6121 tmp = tmp->next;
6122 }
6123 if (tmp == NULL) {
6124 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6125 if (tmp == NULL) {
6126 xmlFree(nsItem);
6127 return (-1);
6128 }
6129 tmp->value = dictnsItem;
6130 tmp->next = NULL;
6131 if (wildc->nsSet == NULL)
6132 wildc->nsSet = tmp;
6133 else
6134 lastNs->next = tmp;
6135 lastNs = tmp;
6136 }
6137
6138 }
6139 xmlFree(nsItem);
6140 cur = end;
6141 } while (*cur != 0);
6142 }
6143 return (ret);
6144}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006145
6146static int
6147xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006148 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006149 xmlNodePtr node,
6150 int minOccurs,
6151 int maxOccurs) {
6152
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006153 if ((maxOccurs == 0) && ( minOccurs == 0))
6154 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006155 if (maxOccurs != UNBOUNDED) {
6156 /*
6157 * TODO: Maby we should better not create the particle,
6158 * if min/max is invalid, since it could confuse the build of the
6159 * content model.
6160 */
6161 /*
6162 * 3.9.6 Schema Component Constraint: Particle Correct
6163 *
6164 */
6165 if (maxOccurs < 1) {
6166 /*
6167 * 2.2 {max occurs} must be greater than or equal to 1.
6168 */
6169 xmlSchemaPCustomAttrErr(ctxt,
6170 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006171 NULL, NULL,
6172 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006173 "The value must be greater than or equal to 1");
6174 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6175 } else if (minOccurs > maxOccurs) {
6176 /*
6177 * 2.1 {min occurs} must not be greater than {max occurs}.
6178 */
6179 xmlSchemaPCustomAttrErr(ctxt,
6180 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006181 NULL, NULL,
6182 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006183 "The value must not be greater than the value of 'maxOccurs'");
6184 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6185 }
6186 }
6187 return (0);
6188}
6189
Daniel Veillardc0826a72004-08-10 14:17:33 +00006190/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006191 * xmlSchemaParseAny:
6192 * @ctxt: a schema validation context
6193 * @schema: the schema being built
6194 * @node: a subtree containing XML Schema informations
6195 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006196 * Parsea a XML schema <any> element. A particle and wildcard
6197 * will be created (except if minOccurs==maxOccurs==0, in this case
6198 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006199 * *WARNING* this interface is highly subject to change
6200 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006201 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006202 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006203static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006204xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6205 xmlNodePtr node)
6206{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006207 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006208 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006209 xmlSchemaWildcardPtr wild;
6210 int min, max;
6211 xmlAttrPtr attr;
6212 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006213
6214 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6215 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006216 /*
6217 * Check for illegal attributes.
6218 */
6219 attr = node->properties;
6220 while (attr != NULL) {
6221 if (attr->ns == NULL) {
6222 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6223 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6224 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6225 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6226 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6227 xmlSchemaPIllegalAttrErr(ctxt,
6228 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6229 NULL, NULL, attr);
6230 }
6231 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6232 xmlSchemaPIllegalAttrErr(ctxt,
6233 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6234 NULL, NULL, attr);
6235 }
6236 attr = attr->next;
6237 }
6238 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6239 /*
6240 * minOccurs/maxOccurs.
6241 */
6242 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006243 "(nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006244 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6245 "nonNegativeInteger");
6246 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6247 /*
6248 * Create & parse the wildcard.
6249 */
6250 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6251 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006252 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006253 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006254 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006255 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006256 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006257 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006258 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006259 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006260 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006261 }
6262 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006263 xmlSchemaPContentErr(ctxt,
6264 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6265 NULL, NULL, node, child,
6266 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006267 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006268 /*
6269 * No component if minOccurs==maxOccurs==0.
6270 */
6271 if ((min == 0) && (max == 0)) {
6272 /* Don't free the wildcard, since it's already on the list. */
6273 return (NULL);
6274 }
6275 /*
6276 * Create the particle.
6277 */
6278 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6279 if (particle == NULL)
6280 return (NULL);
6281 particle->annot = annot;
6282 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006283
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006284 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006285}
6286
6287/**
6288 * xmlSchemaParseNotation:
6289 * @ctxt: a schema validation context
6290 * @schema: the schema being built
6291 * @node: a subtree containing XML Schema informations
6292 *
6293 * parse a XML schema Notation declaration
6294 *
6295 * Returns the new structure or NULL in case of error
6296 */
6297static xmlSchemaNotationPtr
6298xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006299 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006300{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006301 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006302 xmlSchemaNotationPtr ret;
6303 xmlNodePtr child = NULL;
6304
6305 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6306 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006307 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006308 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006309 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6310 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006311 return (NULL);
6312 }
6313 ret = xmlSchemaAddNotation(ctxt, schema, name);
6314 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006315 return (NULL);
6316 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006317 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006318
6319 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6320 node, BAD_CAST "id");
6321
6322 if (IS_SCHEMA(child, "annotation")) {
6323 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6324 child = child->next;
6325 }
6326
Daniel Veillard4255d502002-04-16 15:50:10 +00006327 child = node->children;
6328 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006329 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6330 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006331 }
6332 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006333 xmlSchemaPContentErr(ctxt,
6334 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6335 NULL, NULL, node, child,
6336 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006337 }
6338
6339 return (ret);
6340}
6341
6342/**
6343 * xmlSchemaParseAnyAttribute:
6344 * @ctxt: a schema validation context
6345 * @schema: the schema being built
6346 * @node: a subtree containing XML Schema informations
6347 *
6348 * parse a XML schema AnyAttrribute declaration
6349 * *WARNING* this interface is highly subject to change
6350 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006351 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006352 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006353static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006354xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6355 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006356{
Daniel Veillard3646d642004-06-02 19:19:14 +00006357 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006358 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006359 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006360
6361 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6362 return (NULL);
6363
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006364 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6365 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006366 if (ret == NULL) {
6367 return (NULL);
6368 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006369 /*
6370 * Check for illegal attributes.
6371 */
6372 attr = node->properties;
6373 while (attr != NULL) {
6374 if (attr->ns == NULL) {
6375 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6376 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6377 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6378 xmlSchemaPIllegalAttrErr(ctxt,
6379 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6380 NULL, NULL, attr);
6381 }
6382 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6383 xmlSchemaPIllegalAttrErr(ctxt,
6384 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6385 NULL, NULL, attr);
6386 }
6387 attr = attr->next;
6388 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006389 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6390 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006391 /*
6392 * Parse the namespace list.
6393 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006394 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006395 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006396 /*
6397 * And now for the children...
6398 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006399 child = node->children;
6400 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006401 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6402 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006403 }
6404 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006405 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006406 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6407 NULL, NULL, node, child,
6408 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006409 }
6410
6411 return (ret);
6412}
6413
6414
6415/**
6416 * xmlSchemaParseAttribute:
6417 * @ctxt: a schema validation context
6418 * @schema: the schema being built
6419 * @node: a subtree containing XML Schema informations
6420 *
6421 * parse a XML schema Attrribute declaration
6422 * *WARNING* this interface is highly subject to change
6423 *
William M. Bracke7091952004-05-11 15:09:58 +00006424 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006425 */
6426static xmlSchemaAttributePtr
6427xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006428 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006429{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006430 const xmlChar *name, *attrValue;
6431 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006432 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006433 xmlNodePtr child = NULL;
6434 xmlAttrPtr attr, nameAttr;
6435 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006436
6437 /*
6438 * Note that the w3c spec assumes the schema to be validated with schema
6439 * for schemas beforehand.
6440 *
6441 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006442 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006443
6444 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6445 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006446 attr = xmlSchemaGetPropNode(node, "ref");
6447 nameAttr = xmlSchemaGetPropNode(node, "name");
6448
6449 if ((attr == NULL) && (nameAttr == NULL)) {
6450 /*
6451 * 3.2.3 : 3.1
6452 * One of ref or name must be present, but not both
6453 */
6454 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6455 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
6456 "One of the attributes 'ref' or 'name' must be present");
6457 return (NULL);
6458 }
6459 if ((topLevel) || (attr == NULL)) {
6460 if (nameAttr == NULL) {
6461 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6462 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
6463 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006464 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006465 }
6466 } else
6467 isRef = 1;
6468
6469 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006470 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006471 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
6472
6473 /*
6474 * Parse as attribute reference.
6475 */
6476 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6477 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6478 &refPrefix, &ref) != 0) {
6479 return (NULL);
6480 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006481 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006482 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006483 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006484 if (ret == NULL) {
6485 if (repName != NULL)
6486 xmlFree(repName);
6487 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006488 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006489 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6490 ret->node = node;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006491 ret->refNs = refNs;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006492 ret->refPrefix = refPrefix;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006493 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006494 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6495 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006496 /*
6497 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6498 */
6499 if (nameAttr != NULL)
6500 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6501 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6502 "ref", "name");
6503 /*
6504 * Check for illegal attributes.
6505 */
6506 attr = node->properties;
6507 while (attr != NULL) {
6508 if (attr->ns == NULL) {
6509 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6510 xmlStrEqual(attr->name, BAD_CAST "form")) {
6511 /*
6512 * 3.2.3 : 3.2
6513 * If ref is present, then all of <simpleType>,
6514 * form and type must be absent.
6515 */
6516 xmlSchemaPIllegalAttrErr(ctxt,
6517 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
6518 (xmlSchemaTypePtr) ret, attr);
6519 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6520 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6521 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6522 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6523 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6524 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
6525 xmlSchemaPIllegalAttrErr(ctxt,
6526 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6527 &repName, (xmlSchemaTypePtr) ret, attr);
6528 }
6529 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6530 xmlSchemaPIllegalAttrErr(ctxt,
6531 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6532 &repName, (xmlSchemaTypePtr) ret, attr);
6533 }
6534 attr = attr->next;
6535 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006536 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006537 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006538
6539 /*
6540 * Parse as attribute declaration.
6541 */
6542 if (xmlSchemaPValAttrNode(ctxt,
6543 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
6544 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6545 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006546 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006547 /*
6548 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6549 */
6550 /*
6551 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6552 */
6553 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
6554 xmlSchemaPSimpleTypeErr(ctxt,
6555 XML_SCHEMAP_NO_XMLNS,
6556 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006557 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006558 "The value must not match 'xmlns'",
6559 NULL, NULL);
6560 if (repName != NULL)
6561 xmlFree(repName);
6562 return (NULL);
6563 }
6564 /*
6565 * Evaluate the target namespace
6566 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006567 if (topLevel) {
6568 ns = schema->targetNamespace;
6569 } else {
6570 attr = xmlSchemaGetPropNode(node, "form");
6571 if (attr != NULL) {
6572 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6573 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6574 ns = schema->targetNamespace;
6575 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6576 xmlSchemaPSimpleTypeErr(ctxt,
6577 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6578 &repName, NULL, (xmlNodePtr) attr,
6579 NULL, "(qualified | unqualified)",
6580 attrValue, NULL, NULL, NULL);
6581 }
6582 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
6583 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006584 }
6585 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006586 if (ret == NULL) {
6587 if (repName != NULL)
6588 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006589 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006590 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006591 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006592 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006593 if (topLevel)
6594 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
6595 /*
6596 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6597 */
6598 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
6599 xmlSchemaPCustomErr(ctxt,
6600 XML_SCHEMAP_NO_XSI,
6601 &repName, (xmlSchemaTypePtr) ret, node,
6602 "The target namespace must not match '%s'",
6603 xmlSchemaInstanceNs);
6604 }
6605 /*
6606 * Check for illegal attributes.
6607 */
6608 attr = node->properties;
6609 while (attr != NULL) {
6610 if (attr->ns == NULL) {
6611 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6612 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6613 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6614 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6615 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
6616 if ((topLevel) ||
6617 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6618 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
6619 xmlSchemaPIllegalAttrErr(ctxt,
6620 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6621 &repName, (xmlSchemaTypePtr) ret, attr);
6622 }
6623 }
6624 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6625 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6626 &repName, (xmlSchemaTypePtr) ret, attr);
6627 }
6628 attr = attr->next;
6629 }
6630 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
6631 node, "type", &ret->typeNs, NULL, &ret->typeName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006632 }
6633 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6634 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006635 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006636 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006637 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006638 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6639 if (ret->defValue != NULL)
6640 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
6641 /*
6642 * Attribute "default".
6643 */
6644 attr = xmlSchemaGetPropNode(node, "default");
6645 if (attr != NULL) {
6646 /*
6647 * 3.2.3 : 1
6648 * default and fixed must not both be present.
6649 */
6650 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6651 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6652 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6653 } else
6654 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6655 }
6656 if (topLevel == 0) {
6657 /*
6658 * Attribute "use".
6659 */
6660 attr = xmlSchemaGetPropNode(node, "use");
6661 if (attr != NULL) {
6662 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6663 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6664 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6665 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6666 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6667 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6668 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6669 else
6670 xmlSchemaPSimpleTypeErr(ctxt,
6671 XML_SCHEMAP_INVALID_ATTR_USE,
6672 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006673 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006674 attrValue, NULL, NULL, NULL);
6675 } else
6676 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6677 /*
6678 * 3.2.3 : 2
6679 * If default and use are both present, use must have
6680 * the actual value optional.
6681 */
6682 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6683 (ret->defValue != NULL) &&
6684 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
6685 xmlSchemaPSimpleTypeErr(ctxt,
6686 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6687 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006688 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006689 "The value must be 'optional' if the attribute "
6690 "'default' is present as well", NULL, NULL);
6691 }
6692 }
6693 /*
6694 * And now for the children...
6695 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006696 child = node->children;
6697 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006698 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6699 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006700 }
6701 if (isRef) {
6702 if (child != NULL) {
6703 if (IS_SCHEMA(child, "simpleType"))
6704 /*
6705 * 3.2.3 : 3.2
6706 * If ref is present, then all of <simpleType>,
6707 * form and type must be absent.
6708 */
6709 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6710 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6711 "(annotation?)");
6712 else
6713 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6714 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6715 "(annotation?)");
6716 }
6717 } else {
6718 if (IS_SCHEMA(child, "simpleType")) {
6719 if (ret->typeName != NULL) {
6720 /*
6721 * 3.2.3 : 4
6722 * type and <simpleType> must not both be present.
6723 */
6724 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6725 &repName, (xmlSchemaTypePtr) ret, node, child,
6726 "The attribute 'type' and the <simpleType> child "
6727 "are mutually exclusive", NULL);
6728 } else
6729 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6730 child = child->next;
6731 }
6732 if (child != NULL)
6733 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6734 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6735 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006736 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006737 /*
6738 * Cleanup.
6739 */
6740 if (repName != NULL)
6741 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006742 return (ret);
6743}
6744
6745/**
6746 * xmlSchemaParseAttributeGroup:
6747 * @ctxt: a schema validation context
6748 * @schema: the schema being built
6749 * @node: a subtree containing XML Schema informations
6750 *
6751 * parse a XML schema Attribute Group declaration
6752 * *WARNING* this interface is highly subject to change
6753 *
6754 * Returns the attribute group or NULL in case of error.
6755 */
6756static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006757xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006758 xmlSchemaPtr schema, xmlNodePtr node,
6759 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006760{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006761 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006762 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006763 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006764 const xmlChar *oldcontainer;
6765 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006766
6767 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6768 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006769
6770 nameAttr = xmlSchemaGetPropNode(node, "name");
6771 attr = xmlSchemaGetPropNode(node, "ref");
6772 if ((topLevel) || (attr == NULL)) {
6773 /*
6774 * Parse as an attribute group definition.
6775 * Note that those are allowed at top level only.
6776 */
6777 if (nameAttr == NULL) {
6778 xmlSchemaPMissingAttrErr(ctxt,
6779 XML_SCHEMAP_S4S_ATTR_MISSING,
6780 NULL, NULL, node, "name", NULL);
6781 return (NULL);
6782 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006783 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
6784 * (xmlNodePtr) nameAttr);
6785 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006786 /*
6787 * The name is crucial, exit if invalid.
6788 */
6789 if (xmlSchemaPValAttrNode(ctxt,
6790 NULL, NULL, nameAttr,
6791 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6792 return (NULL);
6793 }
6794 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6795 if (ret == NULL)
6796 return (NULL);
6797 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6798 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6799 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006800 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006801 } else {
6802 char buf[50];
6803 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6804
6805 /*
6806 * Parse as an attribute group definition reference.
6807 */
6808 if (attr == NULL) {
6809 xmlSchemaPMissingAttrErr(ctxt,
6810 XML_SCHEMAP_S4S_ATTR_MISSING,
6811 NULL, NULL, node, "ref", NULL);
6812 }
6813 xmlSchemaPValAttrNodeQName(ctxt, schema,
6814 NULL, NULL, attr, &refNs, &refPrefix, &ref);
6815
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006816 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006817 name = (const xmlChar *) buf;
6818 if (name == NULL) {
6819 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6820 "attribute group definition reference", node);
6821 return (NULL);
6822 }
6823 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6824 if (ret == NULL)
6825 return (NULL);
6826 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6827 ret->ref = ref;
6828 ret->refNs = refNs;
6829 /* TODO: Is @refPrefix currently used? */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006830 ret->refPrefix = refPrefix;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006831 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006832 xmlSchemaCheckReference(ctxt, schema, node,
6833 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006834 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006835 /*
6836 * Check for illegal attributes.
6837 */
6838 attr = node->properties;
6839 while (attr != NULL) {
6840 if (attr->ns == NULL) {
6841 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6842 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
6843 (!xmlStrEqual(attr->name, BAD_CAST "id")))
6844 {
6845 xmlSchemaPIllegalAttrErr(ctxt,
6846 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6847 NULL, NULL, attr);
6848 }
6849 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6850 xmlSchemaPIllegalAttrErr(ctxt,
6851 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6852 NULL, NULL, attr);
6853 }
6854 attr = attr->next;
6855 }
6856 /* TODO: Validate "id" ? */
6857 /*
6858 * And now for the children...
6859 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006860 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006861 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006862 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006863 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006864 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6865 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006866 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006867 if (topLevel) {
6868 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
6869 if (IS_SCHEMA(child, "anyAttribute")) {
6870 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6871 child = child->next;
6872 }
6873 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006874 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006875 xmlSchemaPContentErr(ctxt,
6876 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6877 NULL, NULL, node, child, NULL,
6878 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006879 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006880 ctxt->container = oldcontainer;
6881 return (ret);
6882}
6883
6884/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006885 * xmlSchemaPValAttrFormDefault:
6886 * @value: the value
6887 * @flags: the flags to be modified
6888 * @flagQualified: the specific flag for "qualified"
6889 *
6890 * Returns 0 if the value is valid, 1 otherwise.
6891 */
6892static int
6893xmlSchemaPValAttrFormDefault(const xmlChar *value,
6894 int *flags,
6895 int flagQualified)
6896{
6897 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6898 if ((*flags & flagQualified) == 0)
6899 *flags |= flagQualified;
6900 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
6901 return (1);
6902
6903 return (0);
6904}
6905
6906/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006907 * xmlSchemaPValAttrBlockFinal:
6908 * @value: the value
6909 * @flags: the flags to be modified
6910 * @flagAll: the specific flag for "#all"
6911 * @flagExtension: the specific flag for "extension"
6912 * @flagRestriction: the specific flag for "restriction"
6913 * @flagSubstitution: the specific flag for "substitution"
6914 * @flagList: the specific flag for "list"
6915 * @flagUnion: the specific flag for "union"
6916 *
6917 * Validates the value of the attribute "final" and "block". The value
6918 * is converted into the specified flag values and returned in @flags.
6919 *
6920 * Returns 0 if the value is valid, 1 otherwise.
6921 */
6922
6923static int
6924xmlSchemaPValAttrBlockFinal(const xmlChar *value,
6925 int *flags,
6926 int flagAll,
6927 int flagExtension,
6928 int flagRestriction,
6929 int flagSubstitution,
6930 int flagList,
6931 int flagUnion)
6932{
6933 int ret = 0;
6934
6935 /*
6936 * TODO: This does not check for dublicate entries.
6937 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006938 if ((flags == NULL) || (value == NULL))
6939 return (-1);
6940 if (value[0] == 0)
6941 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006942 if (xmlStrEqual(value, BAD_CAST "#all")) {
6943 if (flagAll != -1)
6944 *flags |= flagAll;
6945 else {
6946 if (flagExtension != -1)
6947 *flags |= flagExtension;
6948 if (flagRestriction != -1)
6949 *flags |= flagRestriction;
6950 if (flagSubstitution != -1)
6951 *flags |= flagSubstitution;
6952 if (flagList != -1)
6953 *flags |= flagList;
6954 if (flagUnion != -1)
6955 *flags |= flagUnion;
6956 }
6957 } else {
6958 const xmlChar *end, *cur = value;
6959 xmlChar *item;
6960
6961 do {
6962 while (IS_BLANK_CH(*cur))
6963 cur++;
6964 end = cur;
6965 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6966 end++;
6967 if (end == cur)
6968 break;
6969 item = xmlStrndup(cur, end - cur);
6970 if (xmlStrEqual(item, BAD_CAST "extension")) {
6971 if (flagExtension != -1) {
6972 if ((*flags & flagExtension) == 0)
6973 *flags |= flagExtension;
6974 } else
6975 ret = 1;
6976 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6977 if (flagRestriction != -1) {
6978 if ((*flags & flagRestriction) == 0)
6979 *flags |= flagRestriction;
6980 } else
6981 ret = 1;
6982 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6983 if (flagSubstitution != -1) {
6984 if ((*flags & flagSubstitution) == 0)
6985 *flags |= flagSubstitution;
6986 } else
6987 ret = 1;
6988 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6989 if (flagList != -1) {
6990 if ((*flags & flagList) == 0)
6991 *flags |= flagList;
6992 } else
6993 ret = 1;
6994 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6995 if (flagUnion != -1) {
6996 if ((*flags & flagUnion) == 0)
6997 *flags |= flagUnion;
6998 } else
6999 ret = 1;
7000 } else
7001 ret = 1;
7002 if (item != NULL)
7003 xmlFree(item);
7004 cur = end;
7005 } while ((ret == 0) && (*cur != 0));
7006 }
7007
7008 return (ret);
7009}
7010
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007011static int
7012xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007013 xmlSchemaIDCPtr idc,
7014 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007015 xmlAttrPtr attr,
7016 int isField)
7017{
7018 xmlNodePtr node;
7019
7020 /*
7021 * c-selector-xpath:
7022 * Schema Component Constraint: Selector Value OK
7023 *
7024 * TODO: 1 The {selector} must be a valid XPath expression, as defined
7025 * in [XPath].
7026 */
7027 if (selector == NULL) {
7028 xmlSchemaPErr(ctxt, idc->node,
7029 XML_SCHEMAP_INTERNAL,
7030 "Internal error: xmlSchemaCheckCSelectorXPath, "
7031 "the selector is not specified.\n", NULL, NULL);
7032 return (-1);
7033 }
7034 if (attr == NULL)
7035 node = idc->node;
7036 else
7037 node = (xmlNodePtr) attr;
7038 if (selector->xpath == NULL) {
7039 xmlSchemaPCustomErr(ctxt,
7040 /* TODO: Adjust error code. */
7041 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7042 NULL, NULL, node,
7043 "The XPath expression of the selector is not valid", NULL);
7044 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7045 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007046 const xmlChar **nsArray = NULL;
7047 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007048 /*
7049 * Compile the XPath expression.
7050 */
7051 /*
7052 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007053 * TODO: Call xmlPatterncompile with different options for selector/
7054 * field.
7055 */
7056 nsList = xmlGetNsList(attr->doc, attr->parent);
7057 /*
7058 * Build an array of prefixes and namespaces.
7059 */
7060 if (nsList != NULL) {
7061 int i, count = 0;
7062 xmlNsPtr ns;
7063
7064 for (i = 0; nsList[i] != NULL; i++)
7065 count++;
7066
7067 nsArray = (const xmlChar **) xmlMalloc(
7068 (count * 2 + 1) * sizeof(const xmlChar *));
7069 if (nsArray == NULL) {
7070 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
7071 NULL);
7072 return (-1);
7073 }
7074 for (i = 0; i < count; i++) {
7075 ns = nsList[i];
7076 nsArray[2 * i] = nsList[i]->href;
7077 nsArray[2 * i + 1] = nsList[i]->prefix;
7078 }
7079 nsArray[count * 2] = NULL;
7080 xmlFree(nsList);
7081 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007082 /*
7083 * TODO: Differentiate between "selector" and "field".
7084 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007085 if (isField)
7086 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00007087 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007088 else
7089 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00007090 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007091 if (nsArray != NULL)
7092 xmlFree((xmlChar **) nsArray);
7093
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00007094 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007095 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00007096 /* TODO: Adjust error code? */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007097 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7098 NULL, NULL, node,
7099 "The XPath expression '%s' could not be "
7100 "compiled", selector->xpath);
7101 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007102 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007103 }
7104 return (0);
7105}
7106
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007107#define ADD_ANNOTATION(annot) \
7108 xmlSchemaAnnotPtr cur = item->annot; \
7109 if (item->annot == NULL) { \
7110 item->annot = annot; \
7111 return (annot); \
7112 } \
7113 cur = item->annot; \
7114 if (cur->next != NULL) { \
7115 cur = cur->next; \
7116 } \
7117 cur->next = annot;
7118
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007119/**
7120 * xmlSchemaAssignAnnotation:
7121 * @item: the schema component
7122 * @annot: the annotation
7123 *
7124 * Adds the annotation to the given schema component.
7125 *
7126 * Returns the given annotaion.
7127 */
7128static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007129xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
7130 xmlSchemaAnnotPtr annot)
7131{
7132 if ((annItem == NULL) || (annot == NULL))
7133 return (NULL);
7134 switch (annItem->type) {
7135 case XML_SCHEMA_TYPE_ELEMENT: {
7136 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
7137 ADD_ANNOTATION(annot)
7138 }
7139 break;
7140 case XML_SCHEMA_TYPE_ATTRIBUTE: {
7141 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
7142 ADD_ANNOTATION(annot)
7143 }
7144 break;
7145 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
7146 case XML_SCHEMA_TYPE_ANY: {
7147 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
7148 ADD_ANNOTATION(annot)
7149 }
7150 break;
7151 case XML_SCHEMA_TYPE_PARTICLE:
7152 case XML_SCHEMA_TYPE_IDC_KEY:
7153 case XML_SCHEMA_TYPE_IDC_KEYREF:
7154 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
7155 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
7156 ADD_ANNOTATION(annot)
7157 }
7158 break;
7159 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
7160 xmlSchemaAttributeGroupPtr item =
7161 (xmlSchemaAttributeGroupPtr) annItem;
7162 ADD_ANNOTATION(annot)
7163 }
7164 break;
7165 case XML_SCHEMA_TYPE_NOTATION: {
7166 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7167 ADD_ANNOTATION(annot)
7168 }
7169 break;
7170 case XML_SCHEMA_FACET_MININCLUSIVE:
7171 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7172 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7173 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7174 case XML_SCHEMA_FACET_TOTALDIGITS:
7175 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7176 case XML_SCHEMA_FACET_PATTERN:
7177 case XML_SCHEMA_FACET_ENUMERATION:
7178 case XML_SCHEMA_FACET_WHITESPACE:
7179 case XML_SCHEMA_FACET_LENGTH:
7180 case XML_SCHEMA_FACET_MAXLENGTH:
7181 case XML_SCHEMA_FACET_MINLENGTH: {
7182 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7183 ADD_ANNOTATION(annot)
7184 }
7185 break;
7186 case XML_SCHEMA_TYPE_SIMPLE:
7187 case XML_SCHEMA_TYPE_COMPLEX: {
7188 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7189 ADD_ANNOTATION(annot)
7190 }
7191 break;
7192 case XML_SCHEMA_TYPE_GROUP: {
7193 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7194 ADD_ANNOTATION(annot)
7195 }
7196 break;
7197 case XML_SCHEMA_TYPE_SEQUENCE:
7198 case XML_SCHEMA_TYPE_CHOICE:
7199 case XML_SCHEMA_TYPE_ALL: {
7200 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7201 ADD_ANNOTATION(annot)
7202 }
7203 break;
7204 default:
7205 xmlSchemaPCustomErr(NULL,
7206 XML_SCHEMAP_INTERNAL,
7207 NULL, NULL, NULL,
7208 "Internal error: xmlSchemaAddAnnotation, "
7209 "The item is not a annotated schema component", NULL);
7210 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007211 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007212 return (annot);
7213}
7214
7215/**
7216 * xmlSchemaParseIDCSelectorAndField:
7217 * @ctxt: a schema validation context
7218 * @schema: the schema being built
7219 * @node: a subtree containing XML Schema informations
7220 *
7221 * Parses a XML Schema identity-contraint definition's
7222 * <selector> and <field> elements.
7223 *
7224 * Returns the parsed identity-constraint definition.
7225 */
7226static xmlSchemaIDCSelectPtr
7227xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
7228 xmlSchemaPtr schema,
7229 xmlSchemaIDCPtr idc,
7230 xmlNodePtr node,
7231 int isField)
7232{
7233 xmlSchemaIDCSelectPtr item;
7234 xmlNodePtr child = NULL;
7235 xmlAttrPtr attr;
7236
7237 /*
7238 * Check for illegal attributes.
7239 */
7240 attr = node->properties;
7241 while (attr != NULL) {
7242 if (attr->ns == NULL) {
7243 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7244 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
7245 xmlSchemaPIllegalAttrErr(ctxt,
7246 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7247 NULL, NULL, attr);
7248 }
7249 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7250 xmlSchemaPIllegalAttrErr(ctxt,
7251 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7252 NULL, NULL, attr);
7253 }
7254 attr = attr->next;
7255 }
7256 /*
7257 * Create the item.
7258 */
7259 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7260 if (item == NULL) {
7261 xmlSchemaPErrMemory(ctxt,
7262 "allocating a 'selector' of an identity-constraint definition",
7263 NULL);
7264 return (NULL);
7265 }
7266 memset(item, 0, sizeof(xmlSchemaIDCSelect));
7267 /*
7268 * Attribute "xpath" (mandatory).
7269 */
7270 attr = xmlSchemaGetPropNode(node, "xpath");
7271 if (attr == NULL) {
7272 xmlSchemaPMissingAttrErr(ctxt,
7273 XML_SCHEMAP_S4S_ATTR_MISSING,
7274 NULL, NULL, node,
7275 "name", NULL);
7276 } else {
7277 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7278 /*
7279 * URGENT TODO: "field"s have an other syntax than "selector"s.
7280 */
7281
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007282 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7283 isField) == -1) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007284 xmlSchemaPErr(ctxt,
7285 (xmlNodePtr) attr,
7286 XML_SCHEMAP_INTERNAL,
7287 "Internal error: xmlSchemaParseIDCSelectorAndField, "
7288 "validating the XPath expression of a IDC selector.\n",
7289 NULL, NULL);
7290 }
7291
7292 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007293 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007294 /*
7295 * And now for the children...
7296 */
7297 child = node->children;
7298 if (IS_SCHEMA(child, "annotation")) {
7299 /*
7300 * Add the annotation to the parent IDC.
7301 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007302 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007303 xmlSchemaParseAnnotation(ctxt, schema, child));
7304 child = child->next;
7305 }
7306 if (child != NULL) {
7307 xmlSchemaPContentErr(ctxt,
7308 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7309 NULL, NULL, node, child,
7310 NULL, "(annotation?)");
7311 }
7312
7313 return (item);
7314}
7315
7316/**
7317 * xmlSchemaParseIDC:
7318 * @ctxt: a schema validation context
7319 * @schema: the schema being built
7320 * @node: a subtree containing XML Schema informations
7321 *
7322 * Parses a XML Schema identity-contraint definition.
7323 *
7324 * Returns the parsed identity-constraint definition.
7325 */
7326static xmlSchemaIDCPtr
7327xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
7328 xmlSchemaPtr schema,
7329 xmlNodePtr node,
7330 xmlSchemaTypeType idcCategory,
7331 const xmlChar *targetNamespace)
7332{
7333 xmlSchemaIDCPtr item = NULL;
7334 xmlNodePtr child = NULL;
7335 xmlAttrPtr attr;
7336 const xmlChar *name = NULL;
7337 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7338 int resAdd;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00007339
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007340 /*
7341 * Check for illegal attributes.
7342 */
7343 attr = node->properties;
7344 while (attr != NULL) {
7345 if (attr->ns == NULL) {
7346 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7347 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7348 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7349 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
7350 xmlSchemaPIllegalAttrErr(ctxt,
7351 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7352 NULL, NULL, attr);
7353 }
7354 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7355 xmlSchemaPIllegalAttrErr(ctxt,
7356 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7357 NULL, NULL, attr);
7358 }
7359 attr = attr->next;
7360 }
7361 /*
7362 * Attribute "name" (mandatory).
7363 */
7364 attr = xmlSchemaGetPropNode(node, "name");
7365 if (attr == NULL) {
7366 xmlSchemaPMissingAttrErr(ctxt,
7367 XML_SCHEMAP_S4S_ATTR_MISSING,
7368 NULL, NULL, node,
7369 "name", NULL);
7370 return (NULL);
7371 } else if (xmlSchemaPValAttrNode(ctxt,
7372 NULL, NULL, attr,
7373 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7374 return (NULL);
7375 }
7376 /*
7377 * Create the component.
7378 */
7379 if (schema->idcDef == NULL)
7380 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
7381 if (schema->idcDef == NULL)
7382 return (NULL);
7383
7384 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7385 if (item == NULL) {
7386 xmlSchemaPErrMemory(ctxt,
7387 "allocating an identity-constraint definition", NULL);
7388 return (NULL);
7389 }
7390 /*
7391 * Add the IDC to the list of IDCs on the schema component.
7392 */
7393 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
7394 if (resAdd != 0) {
7395 xmlSchemaPCustomErrExt(ctxt,
7396 XML_SCHEMAP_REDEFINED_TYPE,
7397 NULL, NULL, node,
7398 "An identity-constraint definition with the name '%s' "
7399 "and targetNamespace '%s' does already exist",
7400 name, targetNamespace, NULL);
7401 xmlFree(item);
7402 return (NULL);
7403 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007404 memset(item, 0, sizeof(xmlSchemaIDC));
7405 item->name = name;
7406 item->type = idcCategory;
7407 item->node = node;
7408 /*
7409 * The target namespace of the parent element declaration.
7410 */
7411 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007412 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7413 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007414 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7415 /*
7416 * Attribute "refer" (mandatory).
7417 */
7418 attr = xmlSchemaGetPropNode(node, "refer");
7419 if (attr == NULL) {
7420 xmlSchemaPMissingAttrErr(ctxt,
7421 XML_SCHEMAP_S4S_ATTR_MISSING,
7422 NULL, NULL, node,
7423 "refer", NULL);
7424 } else {
7425 /*
7426 * Create a reference item.
7427 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007428 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
7429 NULL, NULL);
7430 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007431 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007432 xmlSchemaPValAttrNodeQName(ctxt, schema,
7433 NULL, NULL, attr,
7434 &(item->ref->targetNamespace), 0,
7435 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007436 xmlSchemaCheckReference(ctxt, schema, node,
7437 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007438 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007439 }
7440 }
7441 /*
7442 * And now for the children...
7443 */
7444 child = node->children;
7445 if (IS_SCHEMA(child, "annotation")) {
7446 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7447 child = child->next;
7448 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007449 if (child == NULL) {
7450 xmlSchemaPContentErr(ctxt,
7451 XML_SCHEMAP_S4S_ELEM_MISSING,
7452 NULL, NULL, node, child,
7453 "A child element is missing",
7454 "(annotation?, (selector, field+))");
7455 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007456 /*
7457 * Child element <selector>.
7458 */
7459 if (IS_SCHEMA(child, "selector")) {
7460 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
7461 item, child, 0);
7462 child = child->next;
7463 /*
7464 * Child elements <field>.
7465 */
7466 if (IS_SCHEMA(child, "field")) {
7467 do {
7468 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
7469 item, child, 1);
7470 if (field != NULL) {
7471 field->index = item->nbFields;
7472 item->nbFields++;
7473 if (lastField != NULL)
7474 lastField->next = field;
7475 else
7476 item->fields = field;
7477 lastField = field;
7478 }
7479 child = child->next;
7480 } while (IS_SCHEMA(child, "field"));
7481 } else {
7482 xmlSchemaPContentErr(ctxt,
7483 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7484 NULL, NULL, node, child,
7485 NULL, "(annotation?, (selector, field+))");
7486 }
7487 }
7488 if (child != NULL) {
7489 xmlSchemaPContentErr(ctxt,
7490 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7491 NULL, NULL, node, child,
7492 NULL, "(annotation?, (selector, field+))");
7493 }
7494
7495 return (item);
7496}
7497
Daniel Veillardc0826a72004-08-10 14:17:33 +00007498/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007499 * xmlSchemaParseElement:
7500 * @ctxt: a schema validation context
7501 * @schema: the schema being built
7502 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007503 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007504 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007505 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007506 * *WARNING* this interface is highly subject to change
7507 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007508 * Returns the element declaration or a particle; NULL in case
7509 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007510 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007511static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007512xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007513 xmlNodePtr node, int topLevel)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007514{
7515 xmlSchemaElementPtr decl = NULL;
7516 xmlSchemaParticlePtr particle = NULL;
7517 xmlSchemaAnnotPtr annot = NULL;
7518 xmlNodePtr child = NULL;
7519 xmlAttrPtr attr, nameAttr;
7520 int min, max, isRef = 0;
7521 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007522
7523 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7524 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007525
Daniel Veillard4255d502002-04-16 15:50:10 +00007526 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007527 return (NULL);
7528 /*
7529 * If we get a "ref" attribute on a local <element> we will assume it's
7530 * a reference - even if there's a "name" attribute; this seems to be more
7531 * robust.
7532 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007533 nameAttr = xmlSchemaGetPropNode(node, "name");
7534 attr = xmlSchemaGetPropNode(node, "ref");
7535 if ((topLevel) || (attr == NULL)) {
7536 if (nameAttr == NULL) {
7537 xmlSchemaPMissingAttrErr(ctxt,
7538 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007539 NULL, NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007540 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007541 }
7542 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007543 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007544
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007545 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7546 child = node->children;
7547 if (IS_SCHEMA(child, "annotation")) {
7548 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7549 child = child->next;
7550 }
7551 /*
7552 * Skip particle part if a global declaration.
7553 */
7554 if (topLevel)
7555 goto declaration_part;
7556 /*
7557 * The particle part ==================================================
7558 */
7559 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7560 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
7561 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
7562 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7563 if (particle == NULL)
7564 goto return_null;
7565
7566 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7567
7568 if (isRef) {
7569 const xmlChar *refNs = NULL, *ref = NULL;
7570 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007571 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007572 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007573 */
7574 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007575 NULL, NULL, attr, &refNs, NULL, &ref);
7576 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007577 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007578 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007579 */
7580 if (nameAttr != NULL) {
7581 xmlSchemaPMutualExclAttrErr(ctxt,
7582 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007583 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007584 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007585 /*
7586 * Check for illegal attributes.
7587 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007588 attr = node->properties;
7589 while (attr != NULL) {
7590 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007591 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7592 xmlStrEqual(attr->name, BAD_CAST "name") ||
7593 xmlStrEqual(attr->name, BAD_CAST "id") ||
7594 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7595 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7596 {
7597 attr = attr->next;
7598 continue;
7599 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007600 /* SPEC (3.3.3 : 2.2) */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007601 xmlSchemaPCustomAttrErr(ctxt,
7602 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007603 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007604 "Only the attributes 'minOccurs', 'maxOccurs' and "
7605 "'id' are allowed in addition to 'ref'");
7606 break;
7607 }
7608 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7609 xmlSchemaPIllegalAttrErr(ctxt,
7610 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007611 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007612 }
7613 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007614 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007615 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007616 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007617 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007618 if (child != NULL) {
7619 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7620 NULL, NULL, node, child, NULL, "(annotation?)");
7621 }
7622 if ((min == 0) && (max == 0))
7623 goto return_null;
7624 /*
7625 * Create the reference item.
7626 */
7627 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7628 ref, refNs);
7629 if (refer == NULL)
7630 goto return_null;
7631 particle->children = (xmlSchemaTreeItemPtr) refer;
7632 particle->annot = annot;
7633 /*
7634 * Add to assembled items; the reference need to be resolved.
7635 */
7636 if (ctxt->assemble != NULL)
7637 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7638
7639 return ((xmlSchemaBasicItemPtr) particle);
7640 }
7641 /*
7642 * The declaration part ===============================================
7643 */
7644declaration_part:
7645 {
7646 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7647 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7648
7649 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007650 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007651 goto return_null;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007652 /*
7653 * Evaluate the target namespace.
7654 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007655 if (topLevel) {
7656 ns = schema->targetNamespace;
7657 } else {
7658 attr = xmlSchemaGetPropNode(node, "form");
7659 if (attr != NULL) {
7660 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7661 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007662 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007663 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
7664 xmlSchemaPSimpleTypeErr(ctxt,
7665 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007666 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007667 NULL, "(qualified | unqualified)",
7668 attrValue, NULL, NULL, NULL);
7669 }
7670 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7671 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00007672 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007673 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
7674 if (decl == NULL) {
7675 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007676 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007677 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7678 decl->node = node;
7679 decl->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007680 /*
7681 * Check for illegal attributes.
7682 */
William M. Bracke7091952004-05-11 15:09:58 +00007683 attr = node->properties;
7684 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007685 if (attr->ns == NULL) {
7686 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7687 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
7688 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7689 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7690 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7691 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007692 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7693 {
7694 if (topLevel == 0) {
7695 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007696 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007697 (!xmlStrEqual(attr->name, BAD_CAST "form")))
7698 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007699 xmlSchemaPIllegalAttrErr(ctxt,
7700 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7701 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007702 }
7703 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7704 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
7705 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7706
7707 xmlSchemaPIllegalAttrErr(ctxt,
7708 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007709 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007710 }
7711 }
7712 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7713
7714 xmlSchemaPIllegalAttrErr(ctxt,
7715 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007716 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007717 }
7718 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007719 }
William M. Bracke7091952004-05-11 15:09:58 +00007720 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007721 * Extract/validate attributes.
7722 */
7723 if (topLevel) {
7724 /*
7725 * Process top attributes of global element declarations here.
7726 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007727 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7728 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
7729 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7730 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7731 &(decl->substGroupNs), NULL, &(decl->substGroup));
7732 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007733 node, "abstract", 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007734 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007735 /*
7736 * Attribute "final".
7737 */
7738 attr = xmlSchemaGetPropNode(node, "final");
7739 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007740 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7741 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7742 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7743 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007744 } else {
7745 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007746 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007747 -1,
7748 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7749 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
7750 xmlSchemaPSimpleTypeErr(ctxt,
7751 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007752 NULL, (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007753 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007754 attrValue, NULL, NULL, NULL);
7755 }
7756 }
7757 }
7758 /*
7759 * Attribute "block".
7760 */
7761 attr = xmlSchemaGetPropNode(node, "block");
7762 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007763 /*
7764 * Apply default "block" values.
7765 */
7766 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7767 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7768 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7769 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7770 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7771 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007772 } else {
7773 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007774 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007775 -1,
7776 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
7777 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
7778 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7779 xmlSchemaPSimpleTypeErr(ctxt,
7780 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007781 NULL, (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007782 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00007783 "restriction | substitution))", attrValue,
7784 NULL, NULL, NULL);
7785 }
7786 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007787 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007788 node, "nillable", 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007789 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007790
Daniel Veillardc0826a72004-08-10 14:17:33 +00007791 xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007792 NULL, (xmlSchemaTypePtr) decl, node,
7793 "type", &(decl->namedTypeNs), NULL, &(decl->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00007794
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007795 decl->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007796 attr = xmlSchemaGetPropNode(node, "fixed");
7797 if (attr != NULL) {
7798 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007799 if (decl->value != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007800 /*
7801 * 3.3.3 : 1
7802 * default and fixed must not both be present.
7803 */
7804 xmlSchemaPMutualExclAttrErr(ctxt,
7805 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007806 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007807 "default", "fixed");
7808 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007809 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7810 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007811 }
William M. Bracke7091952004-05-11 15:09:58 +00007812 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007813 /*
7814 * And now for the children...
7815 */
7816 oldcontainer = ctxt->container;
7817 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007818 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007819 /*
7820 * 3.3.3 : 3
7821 * "type" and either <simpleType> or <complexType> are mutually
7822 * exclusive
7823 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007824 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007825 xmlSchemaPContentErr(ctxt,
7826 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007827 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007828 "The attribute 'type' and the <complexType> child are "
7829 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007830 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007831 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007832 child = child->next;
7833 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007834 /*
7835 * 3.3.3 : 3
7836 * "type" and either <simpleType> or <complexType> are
7837 * mutually exclusive
7838 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007839 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007840 xmlSchemaPContentErr(ctxt,
7841 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007842 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007843 "The attribute 'type' and the <simpleType> child are "
7844 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007845 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007846 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007847 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007848 }
William M. Bracke7091952004-05-11 15:09:58 +00007849 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007850 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007851 if (IS_SCHEMA(child, "unique")) {
7852 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007853 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007854 } else if (IS_SCHEMA(child, "key")) {
7855 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007856 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007857 } else if (IS_SCHEMA(child, "keyref")) {
7858 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007859 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007860 }
7861 if (lastIDC != NULL)
7862 lastIDC->next = curIDC;
7863 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007864 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007865 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007866 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007867 }
7868 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007869 xmlSchemaPContentErr(ctxt,
7870 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007871 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007872 NULL, "(annotation?, ((simpleType | complexType)?, "
7873 "(unique | key | keyref)*))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007874 }
7875 ctxt->container = oldcontainer;
7876 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007877 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007878 /*
7879 * NOTE: Element Declaration Representation OK 4. will be checked at a
7880 * different layer.
7881 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007882 FREE_AND_NULL(des)
7883 if (topLevel)
7884 return ((xmlSchemaBasicItemPtr) decl);
7885 else {
7886 particle->children = (xmlSchemaTreeItemPtr) decl;
7887 return ((xmlSchemaBasicItemPtr) particle);
7888 }
7889
7890return_null:
7891 FREE_AND_NULL(des)
7892 if (annot != NULL)
7893 xmlSchemaFreeAnnot(annot);
7894 if (particle != NULL)
7895 xmlSchemaFreeParticle(particle);
7896 if (decl != NULL)
7897 xmlSchemaFreeElement(decl);
7898 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007899}
7900
7901/**
7902 * xmlSchemaParseUnion:
7903 * @ctxt: a schema validation context
7904 * @schema: the schema being built
7905 * @node: a subtree containing XML Schema informations
7906 *
7907 * parse a XML schema Union definition
7908 * *WARNING* this interface is highly subject to change
7909 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007910 * Returns -1 in case of internal error, 0 in case of success and a positive
7911 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007912 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007913static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007914xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007915 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007916{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007917 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007918 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007919 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007920 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007921
7922 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007923 return (-1);
7924 /* Not a component, don't create it. */
7925 type = ctxt->ctxtType;
7926 /*
7927 * Mark the simple type as being of variety "union".
7928 */
7929 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007930 /*
7931 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7932 * then the ·simple ur-type definition·."
7933 */
7934 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007935 /*
7936 * Check for illegal attributes.
7937 */
7938 attr = node->properties;
7939 while (attr != NULL) {
7940 if (attr->ns == NULL) {
7941 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7942 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
7943 xmlSchemaPIllegalAttrErr(ctxt,
7944 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007945 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007946 }
7947 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7948 xmlSchemaPIllegalAttrErr(ctxt,
7949 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007950 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007951 }
7952 attr = attr->next;
7953 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007954 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007955 /*
7956 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007957 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007958 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007959 attr = xmlSchemaGetPropNode(node, "memberTypes");
7960 if (attr != NULL) {
7961 const xmlChar *end;
7962 xmlChar *tmp;
7963 const xmlChar *localName, *nsName;
7964 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7965 xmlSchemaQNameRefPtr ref;
7966
7967 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7968 type->ref = cur;
7969 do {
7970 while (IS_BLANK_CH(*cur))
7971 cur++;
7972 end = cur;
7973 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7974 end++;
7975 if (end == cur)
7976 break;
7977 tmp = xmlStrndup(cur, end - cur);
7978 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7979 NULL, attr, BAD_CAST tmp, &nsName, NULL, &localName) == 0) {
7980 /*
7981 * Create the member type link.
7982 */
7983 link = (xmlSchemaTypeLinkPtr)
7984 xmlMalloc(sizeof(xmlSchemaTypeLink));
7985 if (link == NULL) {
7986 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7987 "allocating a type link", NULL);
7988 return (-1);
7989 }
7990 link->type = NULL;
7991 link->next = NULL;
7992 if (lastLink == NULL)
7993 type->memberTypes = link;
7994 else
7995 lastLink->next = link;
7996 lastLink = link;
7997 /*
7998 * Create a reference item.
7999 */
8000 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
8001 localName, nsName);
8002 if (ref == NULL) {
8003 FREE_AND_NULL(tmp)
8004 return (-1);
8005 }
8006 /*
8007 * Assign the reference to the link, it will be resolved
8008 * later during fixup of the union simple type.
8009 */
8010 link->type = (xmlSchemaTypePtr) ref;
8011 }
8012 FREE_AND_NULL(tmp)
8013 cur = end;
8014 } while (*cur != 0);
8015
8016 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008017 /*
8018 * And now for the children...
8019 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008020 child = node->children;
8021 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008022 /*
8023 * Add the annotation to the simple type ancestor.
8024 */
8025 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8026 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008027 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008028 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008029 if (IS_SCHEMA(child, "simpleType")) {
8030 xmlSchemaTypePtr subtype, last = NULL;
8031
8032 /*
8033 * Anchor the member types in the "subtypes" field of the
8034 * simple type.
8035 */
8036 while (IS_SCHEMA(child, "simpleType")) {
8037 subtype = (xmlSchemaTypePtr)
8038 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8039 if (subtype != NULL) {
8040 if (last == NULL) {
8041 type->subtypes = subtype;
8042 last = subtype;
8043 } else {
8044 last->next = subtype;
8045 last = subtype;
8046 }
8047 last->next = NULL;
8048 }
8049 child = child->next;
8050 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008051 }
8052 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008053 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008054 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8055 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
8056 }
8057 if ((attr == NULL) && (type->subtypes == NULL)) {
8058 /*
8059 * src-union-memberTypes-or-simpleTypes
8060 * Either the memberTypes [attribute] of the <union> element must
8061 * be non-empty or there must be at least one simpleType [child].
8062 */
8063 xmlSchemaPCustomErr(ctxt,
8064 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
8065 NULL, NULL, node,
8066 "Either the attribute 'memberTypes' or "
8067 "at least one <simpleType> child must be present", NULL);
8068 }
8069 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00008070}
8071
8072/**
8073 * xmlSchemaParseList:
8074 * @ctxt: a schema validation context
8075 * @schema: the schema being built
8076 * @node: a subtree containing XML Schema informations
8077 *
8078 * parse a XML schema List definition
8079 * *WARNING* this interface is highly subject to change
8080 *
William M. Bracke7091952004-05-11 15:09:58 +00008081 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008082 * 1 in case of success.
8083 */
8084static xmlSchemaTypePtr
8085xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008086 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008087{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008088 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008089 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008090 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008091
8092 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8093 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008094 /* Not a component, don't create it. */
8095 type = ctxt->ctxtType;
8096 /*
8097 * Mark the type as being of variety "list".
8098 */
8099 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008100 /*
8101 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8102 * then the ·simple ur-type definition·."
8103 */
8104 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008105 /*
8106 * Check for illegal attributes.
8107 */
8108 attr = node->properties;
8109 while (attr != NULL) {
8110 if (attr->ns == NULL) {
8111 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8112 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
8113 xmlSchemaPIllegalAttrErr(ctxt,
8114 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008115 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008116 }
8117 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8118 xmlSchemaPIllegalAttrErr(ctxt,
8119 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008120 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008121 }
8122 attr = attr->next;
8123 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008124
8125 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8126
William M. Brack2f2a6632004-08-20 23:09:47 +00008127 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008128 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
8129 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00008130 */
8131 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008132 node, "itemType", &(type->refNs), NULL, &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00008133 /*
8134 * And now for the children...
8135 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008136 child = node->children;
8137 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008138 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8139 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008140 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00008141 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008142 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008143 /*
8144 * src-list-itemType-or-simpleType
8145 * Either the itemType [attribute] or the <simpleType> [child] of
8146 * the <list> element must be present, but not both.
8147 */
8148 if (type->ref != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008149 xmlSchemaPCustomErr(ctxt,
8150 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008151 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00008152 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008153 "are mutually exclusive", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00008154 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008155 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008156 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008157 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008158 } else if (type->ref == NULL) {
8159 xmlSchemaPCustomErr(ctxt,
8160 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
8161 NULL, NULL, node,
8162 "Either the attribute 'itemType' or the <simpleType> child "
8163 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008164 }
8165 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008166 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008167 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8168 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008169 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008170 if ((type->ref == NULL) &&
8171 (type->subtypes == NULL) &&
8172 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
8173 xmlSchemaPCustomErr(ctxt,
8174 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
8175 NULL, NULL, node,
8176 "Either the attribute 'itemType' or the <simpleType> child "
8177 "must be present", NULL);
8178 }
8179 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008180}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008181
Daniel Veillard4255d502002-04-16 15:50:10 +00008182/**
8183 * xmlSchemaParseSimpleType:
8184 * @ctxt: a schema validation context
8185 * @schema: the schema being built
8186 * @node: a subtree containing XML Schema informations
8187 *
8188 * parse a XML schema Simple Type definition
8189 * *WARNING* this interface is highly subject to change
8190 *
William M. Bracke7091952004-05-11 15:09:58 +00008191 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008192 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008193 */
8194static xmlSchemaTypePtr
8195xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008196 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008197{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008198 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008199 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008200 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008201 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008202
8203 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8204 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008205
Daniel Veillardc0826a72004-08-10 14:17:33 +00008206 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008207 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008208 if (attr == NULL) {
8209 xmlSchemaPMissingAttrErr(ctxt,
8210 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008211 NULL, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008212 "name", NULL);
8213 return (NULL);
8214 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008215 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008216 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008217 return (NULL);
8218 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008219 }
8220
8221 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008222 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008223
Daniel Veillard01fa6152004-06-29 17:04:39 +00008224 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008225 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008226 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008227 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008228 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008229 if (type == NULL)
8230 return (NULL);
8231 type->node = node;
8232 type->type = XML_SCHEMA_TYPE_SIMPLE;
8233 /*
8234 * Check for illegal attributes.
8235 */
8236 attr = node->properties;
8237 while (attr != NULL) {
8238 if (attr->ns == NULL) {
8239 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
8240 xmlSchemaPIllegalAttrErr(ctxt,
8241 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008242 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008243 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008244 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8245 xmlSchemaPIllegalAttrErr(ctxt,
8246 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008247 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008248 }
8249 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008250 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008251 } else {
8252 /*
8253 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008254 *
8255 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008256 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008257 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008258 if (type == NULL)
8259 return (NULL);
8260 type->node = node;
8261 type->type = XML_SCHEMA_TYPE_SIMPLE;
8262 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8263 /*
8264 * Check for illegal attributes.
8265 */
8266 attr = node->properties;
8267 while (attr != NULL) {
8268 if (attr->ns == NULL) {
8269 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8270 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008271 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008272 xmlSchemaPIllegalAttrErr(ctxt,
8273 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008274 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008275 }
8276 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8277 xmlSchemaPIllegalAttrErr(ctxt,
8278 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008279 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008280 }
8281 attr = attr->next;
8282 }
8283 /*
8284 * Attribute "final".
8285 */
8286 attr = xmlSchemaGetPropNode(node, "final");
8287 if (attr == NULL) {
8288 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
8289 } else {
8290 attrValue = xmlSchemaGetProp(ctxt, node, "final");
8291 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8292 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
8293 XML_SCHEMAS_TYPE_FINAL_LIST,
8294 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8295
8296 xmlSchemaPSimpleTypeErr(ctxt,
8297 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008298 NULL, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00008299 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008300 attrValue, NULL, NULL, NULL);
8301 }
8302 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008303 }
8304 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008305 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008306 /*
8307 * And now for the children...
8308 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008309 oldCtxtType = ctxt->ctxtType;
8310 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008311 ctxt->ctxtType = type;
8312 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008313 child = node->children;
8314 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008315 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8316 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008317 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008318 if (child == NULL) {
8319 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8320 NULL, type, node, child, NULL,
8321 "(annotation?, (restriction | list | union))");
8322 } else if (IS_SCHEMA(child, "restriction")) {
8323 xmlSchemaParseRestriction(ctxt, schema, child,
8324 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008325 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008326 } else if (IS_SCHEMA(child, "list")) {
8327 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008328 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008329 } else if (IS_SCHEMA(child, "union")) {
8330 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008331 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008332 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008333 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008334 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008335 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008336 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008337 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008338 ctxt->parentItem = oldParentItem;
8339 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008340
Daniel Veillard4255d502002-04-16 15:50:10 +00008341 return (type);
8342}
8343
Daniel Veillard4255d502002-04-16 15:50:10 +00008344/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008345 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008346 * @ctxt: a schema validation context
8347 * @schema: the schema being built
8348 * @node: a subtree containing XML Schema informations
8349 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008350 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008351 * *WARNING* this interface is highly subject to change
8352 *
William M. Bracke7091952004-05-11 15:09:58 +00008353 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008354 * 1 in case of success.
8355 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008356static xmlSchemaTreeItemPtr
8357xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8358 xmlSchemaPtr schema,
8359 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008360{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008361 xmlSchemaParticlePtr item;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008362 xmlNodePtr child = NULL;
8363 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008364 const xmlChar *ref = NULL, *refNs = NULL;
8365 int min, max;
8366
8367 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8368 return (NULL);
8369
8370 attr = xmlSchemaGetPropNode(node, "ref");
8371 if (attr == NULL) {
8372 xmlSchemaPMissingAttrErr(ctxt,
8373 XML_SCHEMAP_S4S_ATTR_MISSING,
8374 NULL, NULL, node,
8375 "ref", NULL);
8376 return (NULL);
8377 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
8378 attr, &refNs, NULL, &ref) != 0) {
8379 return (NULL);
8380 }
8381 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8382 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8383 "(nonNegativeInteger | unbounded)");
8384 /*
8385 * Check for illegal attributes.
8386 */
8387 attr = node->properties;
8388 while (attr != NULL) {
8389 if (attr->ns == NULL) {
8390 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
8391 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8392 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8393 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
8394 xmlSchemaPIllegalAttrErr(ctxt,
8395 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8396 NULL, NULL, attr);
8397 }
8398 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8399 xmlSchemaPIllegalAttrErr(ctxt,
8400 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8401 NULL, NULL, attr);
8402 }
8403 attr = attr->next;
8404 }
8405 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8406 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8407 if (item == NULL)
8408 return (NULL);
8409 /*
8410 * Create a reference item as the term; it will be substituted for
8411 * the model group after the reference has been resolved.
8412 */
8413 item->children = (xmlSchemaTreeItemPtr)
8414 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8415 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8416 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8417 /*
8418 * And now for the children...
8419 */
8420 child = node->children;
8421 /* TODO: Is annotation even allowed for a model group reference? */
8422 if (IS_SCHEMA(child, "annotation")) {
8423 /*
8424 * TODO: What to do exactly with the annotation?
8425 */
8426 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8427 child = child->next;
8428 }
8429 if (child != NULL) {
8430 xmlSchemaPContentErr(ctxt,
8431 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8432 NULL, NULL, node, child, NULL,
8433 "(annotation?)");
8434 }
8435 /*
8436 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8437 */
8438 if ((min == 0) && (max == 0))
8439 return (NULL);
8440 if (ctxt->assemble != NULL)
8441 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8442 return ((xmlSchemaTreeItemPtr) item);
8443}
8444
8445/**
8446 * xmlSchemaParseModelGroupDefinition:
8447 * @ctxt: a schema validation context
8448 * @schema: the schema being built
8449 * @node: a subtree containing XML Schema informations
8450 *
8451 * Parses a XML schema model group definition.
8452 * *WARNING* this interface is highly subject to change
8453 *
8454 * Returns -1 in case of error, 0 if the declaration is improper and
8455 * 1 in case of success.
8456 */
8457static xmlSchemaModelGroupDefPtr
8458xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8459 xmlSchemaPtr schema,
8460 xmlNodePtr node)
8461{
8462 xmlSchemaModelGroupDefPtr item;
8463 xmlNodePtr child = NULL;
8464 xmlAttrPtr attr;
8465 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008466
8467 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008468 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008469
8470 attr = xmlSchemaGetPropNode(node, "name");
8471 if (attr == NULL) {
8472 xmlSchemaPMissingAttrErr(ctxt,
8473 XML_SCHEMAP_S4S_ATTR_MISSING,
8474 NULL, NULL, node,
8475 "name", NULL);
8476 return (NULL);
8477 } else if (xmlSchemaPValAttrNode(ctxt,
8478 NULL, NULL, attr,
8479 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8480 return (NULL);
8481 }
8482 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8483 if (item == NULL)
8484 return (NULL);
8485 /*
8486 * Check for illegal attributes.
8487 */
8488 attr = node->properties;
8489 while (attr != NULL) {
8490 if (attr->ns == NULL) {
8491 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8492 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
8493 xmlSchemaPIllegalAttrErr(ctxt,
8494 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8495 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008496 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008497 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8498 xmlSchemaPIllegalAttrErr(ctxt,
8499 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8500 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008501 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008502 attr = attr->next;
8503 }
8504 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8505 /*
8506 * And now for the children...
8507 */
8508 child = node->children;
8509 if (IS_SCHEMA(child, "annotation")) {
8510 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8511 child = child->next;
8512 }
8513 if (IS_SCHEMA(child, "all")) {
8514 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8515 XML_SCHEMA_TYPE_ALL, 0);
8516 child = child->next;
8517 } else if (IS_SCHEMA(child, "choice")) {
8518 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8519 XML_SCHEMA_TYPE_CHOICE, 0);
8520 child = child->next;
8521 } else if (IS_SCHEMA(child, "sequence")) {
8522 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8523 XML_SCHEMA_TYPE_SEQUENCE, 0);
8524 child = child->next;
8525 }
8526 if (child != NULL) {
8527 xmlSchemaPContentErr(ctxt,
8528 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8529 NULL, NULL, node, child, NULL,
8530 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008531 }
8532
8533 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008534}
8535
8536/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008537 * xmlSchemaCleanupDoc:
8538 * @ctxt: a schema validation context
8539 * @node: the root of the document.
8540 *
8541 * removes unwanted nodes in a schemas document tree
8542 */
8543static void
8544xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8545{
8546 xmlNodePtr delete, cur;
8547
8548 if ((ctxt == NULL) || (root == NULL)) return;
8549
8550 /*
8551 * Remove all the blank text nodes
8552 */
8553 delete = NULL;
8554 cur = root;
8555 while (cur != NULL) {
8556 if (delete != NULL) {
8557 xmlUnlinkNode(delete);
8558 xmlFreeNode(delete);
8559 delete = NULL;
8560 }
8561 if (cur->type == XML_TEXT_NODE) {
8562 if (IS_BLANK_NODE(cur)) {
8563 if (xmlNodeGetSpacePreserve(cur) != 1) {
8564 delete = cur;
8565 }
8566 }
8567 } else if ((cur->type != XML_ELEMENT_NODE) &&
8568 (cur->type != XML_CDATA_SECTION_NODE)) {
8569 delete = cur;
8570 goto skip_children;
8571 }
8572
8573 /*
8574 * Skip to next node
8575 */
8576 if (cur->children != NULL) {
8577 if ((cur->children->type != XML_ENTITY_DECL) &&
8578 (cur->children->type != XML_ENTITY_REF_NODE) &&
8579 (cur->children->type != XML_ENTITY_NODE)) {
8580 cur = cur->children;
8581 continue;
8582 }
8583 }
8584 skip_children:
8585 if (cur->next != NULL) {
8586 cur = cur->next;
8587 continue;
8588 }
8589
8590 do {
8591 cur = cur->parent;
8592 if (cur == NULL)
8593 break;
8594 if (cur == root) {
8595 cur = NULL;
8596 break;
8597 }
8598 if (cur->next != NULL) {
8599 cur = cur->next;
8600 break;
8601 }
8602 } while (cur != NULL);
8603 }
8604 if (delete != NULL) {
8605 xmlUnlinkNode(delete);
8606 xmlFreeNode(delete);
8607 delete = NULL;
8608 }
8609}
8610
William M. Brack2f2a6632004-08-20 23:09:47 +00008611
8612/**
8613 * xmlSchemaImportSchema
8614 *
8615 * @ctxt: a schema validation context
8616 * @schemaLocation: an URI defining where to find the imported schema
8617 *
8618 * import a XML schema
8619 * *WARNING* this interface is highly subject to change
8620 *
8621 * Returns -1 in case of error and 1 in case of success.
8622 */
8623#if 0
8624static xmlSchemaImportPtr
8625xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8626 const xmlChar *schemaLocation)
8627{
8628 xmlSchemaImportPtr import;
8629 xmlSchemaParserCtxtPtr newctxt;
8630
8631 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8632 if (newctxt == NULL) {
8633 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8634 NULL);
8635 return (NULL);
8636 }
8637 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8638 /* Keep the same dictionnary for parsing, really */
8639 xmlDictReference(ctxt->dict);
8640 newctxt->dict = ctxt->dict;
8641 newctxt->includes = 0;
8642 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8643
8644 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8645 ctxt->userData);
8646
8647 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8648 if (import == NULL) {
8649 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8650 NULL);
8651 xmlSchemaFreeParserCtxt(newctxt);
8652 return (NULL);
8653 }
8654
8655 memset(import, 0, sizeof(xmlSchemaImport));
8656 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8657 import->schema = xmlSchemaParse(newctxt);
8658
8659 if (import->schema == NULL) {
8660 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008661 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008662 "Failed to import schema from location \"%s\".\n",
8663 schemaLocation, NULL);
8664
8665 xmlSchemaFreeParserCtxt(newctxt);
8666 /* The schemaLocation is held by the dictionary.
8667 if (import->schemaLocation != NULL)
8668 xmlFree((xmlChar *)import->schemaLocation);
8669 */
8670 xmlFree(import);
8671 return NULL;
8672 }
8673
8674 xmlSchemaFreeParserCtxt(newctxt);
8675 return import;
8676}
8677#endif
8678
8679static void
8680xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8681{
8682 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8683 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8684
8685 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8686 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8687
8688 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8689 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8690 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8691 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8692 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8693 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8694 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8695 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8696
8697 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8698 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8699 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8700 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8701 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8702 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8703}
8704
8705static void
8706xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
8707 xmlSchemaPtr schema,
8708 xmlNodePtr node)
8709{
8710 xmlAttrPtr attr;
8711 const xmlChar *val;
8712
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008713 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8714 if (schema->version == NULL)
8715 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8716 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8717 else
8718 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8719 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8720
William M. Brack2f2a6632004-08-20 23:09:47 +00008721 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
8722 if (attr != NULL) {
8723 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8724 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
8725 XML_SCHEMAS_QUALIF_ELEM) != 0) {
8726 xmlSchemaPSimpleTypeErr(ctxt,
8727 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
8728 NULL, NULL, (xmlNodePtr) attr, NULL,
8729 "(qualified | unqualified)", val, NULL, NULL, NULL);
8730 }
8731 }
8732
8733 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
8734 if (attr != NULL) {
8735 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8736 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
8737 XML_SCHEMAS_QUALIF_ATTR) != 0) {
8738 xmlSchemaPSimpleTypeErr(ctxt,
8739 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
8740 NULL, NULL, (xmlNodePtr) attr, NULL,
8741 "(qualified | unqualified)", val, NULL, NULL, NULL);
8742 }
8743 }
8744
8745 attr = xmlSchemaGetPropNode(node, "finalDefault");
8746 if (attr != NULL) {
8747 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8748 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8749 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8750 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8751 -1,
8752 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8753 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8754 xmlSchemaPSimpleTypeErr(ctxt,
8755 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8756 NULL, NULL, (xmlNodePtr) attr, NULL,
8757 "(#all | List of (extension | restriction | list | union))",
8758 val, NULL, NULL, NULL);
8759 }
8760 }
8761
8762 attr = xmlSchemaGetPropNode(node, "blockDefault");
8763 if (attr != NULL) {
8764 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8765 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8766 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8767 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8768 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8769 xmlSchemaPSimpleTypeErr(ctxt,
8770 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8771 NULL, NULL, (xmlNodePtr) attr, NULL,
8772 "(#all | List of (extension | restriction | substitution))",
8773 val, NULL, NULL, NULL);
8774 }
8775 }
8776}
8777
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008778/**
8779 * xmlSchemaParseSchemaTopLevel:
8780 * @ctxt: a schema validation context
8781 * @schema: the schemas
8782 * @nodes: the list of top level nodes
8783 *
8784 * Returns the internal XML Schema structure built from the resource or
8785 * NULL in case of error
8786 */
8787static void
8788xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8789 xmlSchemaPtr schema, xmlNodePtr nodes)
8790{
8791 xmlNodePtr child;
8792 xmlSchemaAnnotPtr annot;
8793
8794 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8795 return;
8796
8797 child = nodes;
8798 while ((IS_SCHEMA(child, "include")) ||
8799 (IS_SCHEMA(child, "import")) ||
8800 (IS_SCHEMA(child, "redefine")) ||
8801 (IS_SCHEMA(child, "annotation"))) {
8802 if (IS_SCHEMA(child, "annotation")) {
8803 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8804 if (schema->annot == NULL)
8805 schema->annot = annot;
8806 else
8807 xmlSchemaFreeAnnot(annot);
8808 } else if (IS_SCHEMA(child, "import")) {
8809 xmlSchemaParseImport(ctxt, schema, child);
8810 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008811 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008812 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008813 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008814 } else if (IS_SCHEMA(child, "redefine")) {
8815 TODO
8816 }
8817 child = child->next;
8818 }
8819 while (child != NULL) {
8820 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008821 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008822 child = child->next;
8823 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008824 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008825 child = child->next;
8826 } else if (IS_SCHEMA(child, "element")) {
8827 xmlSchemaParseElement(ctxt, schema, child, 1);
8828 child = child->next;
8829 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008830 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008831 child = child->next;
8832 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008833 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008834 child = child->next;
8835 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008836 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008837 child = child->next;
8838 } else if (IS_SCHEMA(child, "notation")) {
8839 xmlSchemaParseNotation(ctxt, schema, child);
8840 child = child->next;
8841 } else {
8842 xmlSchemaPErr2(ctxt, NULL, child,
8843 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008844 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008845 child->name, NULL);
8846 child = child->next;
8847 }
8848 while (IS_SCHEMA(child, "annotation")) {
8849 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8850 if (schema->annot == NULL)
8851 schema->annot = annot;
8852 else
8853 xmlSchemaFreeAnnot(annot);
8854 child = child->next;
8855 }
8856 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008857 ctxt->parentItem = NULL;
8858 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008859}
8860
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008861static xmlSchemaImportPtr
8862xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
8863 xmlHashTablePtr *imports,
8864 const xmlChar *nsName)
8865{
8866 xmlSchemaImportPtr ret;
8867
8868 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008869 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008870 if (*imports == NULL) {
8871 xmlSchemaPCustomErr(ctxt,
8872 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8873 NULL, NULL, (xmlNodePtr) ctxt->doc,
8874 "Internal error: failed to build the import table",
8875 NULL);
8876 return (NULL);
8877 }
8878 }
8879 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8880 if (ret == NULL) {
8881 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8882 return (NULL);
8883 }
8884 memset(ret, 0, sizeof(xmlSchemaImport));
8885 if (nsName == NULL)
8886 nsName = XML_SCHEMAS_NO_NAMESPACE;
8887 xmlHashAddEntry(*imports, nsName, ret);
8888
8889 return (ret);
8890}
8891
8892static int
8893xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008894 xmlSchemaPtr schema,
8895 xmlNodePtr node,
8896 const xmlChar *nsName,
8897 const xmlChar *location,
8898 xmlDocPtr *doc,
8899 const xmlChar **targetNamespace,
8900 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008901{
8902 xmlParserCtxtPtr parserCtxt;
8903 xmlSchemaImportPtr import;
8904 const xmlChar *ns;
8905 xmlNodePtr root;
8906
8907 /*
8908 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8909 * <xsi:noNamespaceSchemaLocation>.
8910 */
8911 *doc = NULL;
8912 /*
8913 * Given that the schemaLocation [attribute] is only a hint, it is open
8914 * to applications to ignore all but the first <import> for a given
8915 * namespace, regardless of the ·actual value· of schemaLocation, but
8916 * such a strategy risks missing useful information when new
8917 * schemaLocations are offered.
8918 *
8919 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8920 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8921 * valid or not.
8922 * We will follow XSV here.
8923 */
8924 if (location == NULL) {
8925 /*
8926 * Schema Document Location Strategy:
8927 *
8928 * 3 Based on the namespace name, identify an existing schema document,
8929 * either as a resource which is an XML document or a <schema> element
8930 * information item, in some local schema repository;
8931 *
8932 * 5 Attempt to resolve the namespace name to locate such a resource.
8933 *
8934 * NOTE: Those stategies are not supported, so we will skip.
8935 */
8936 return (0);
8937 }
8938 if (nsName == NULL)
8939 ns = XML_SCHEMAS_NO_NAMESPACE;
8940 else
8941 ns = nsName;
8942
8943 import = xmlHashLookup(schema->schemasImports, ns);
8944 if (import != NULL) {
8945 /*
8946 * There was a valid resource for the specified namespace already
8947 * defined, so skip.
8948 * TODO: This might be changed someday to allow import of
8949 * components from multiple documents for a single target namespace.
8950 */
8951 return (0);
8952 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008953
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008954 /*
8955 * Schema Document Location Strategy:
8956 *
8957 * 2 Based on the location URI, identify an existing schema document,
8958 * either as a resource which is an XML document or a <schema> element
8959 * information item, in some local schema repository;
8960 *
8961 * 4 Attempt to resolve the location URI, to locate a resource on the
8962 * web which is or contains or references a <schema> element;
8963 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8964 *
8965 */
8966 if ((absolute == 0) && (node != NULL)) {
8967 xmlChar *base, *URI;
8968
8969 base = xmlNodeGetBase(node->doc, node);
8970 if (base == NULL) {
8971 URI = xmlBuildURI(location, node->doc->URL);
8972 } else {
8973 URI = xmlBuildURI(location, base);
8974 xmlFree(base);
8975 }
8976 if (URI != NULL) {
8977 location = xmlDictLookup(ctxt->dict, URI, -1);
8978 xmlFree(URI);
8979 }
8980 }
8981 parserCtxt = xmlNewParserCtxt();
8982 if (parserCtxt == NULL) {
8983 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8984 "allocating a parser context", NULL);
8985 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008986 }
8987
8988 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
8989 xmlDictFree(parserCtxt->dict);
8990 parserCtxt->dict = ctxt->dict;
8991 xmlDictReference(parserCtxt->dict);
8992 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008993
8994 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
8995 NULL, SCHEMAS_PARSE_OPTIONS);
8996
8997 /*
8998 * 2.1 The referent is (a fragment of) a resource which is an
8999 * XML document (see clause 1.1), which in turn corresponds to
9000 * a <schema> element information item in a well-formed information
9001 * set, which in turn corresponds to a valid schema.
9002 * TODO: What to do with the "fragment" stuff?
9003 *
9004 * 2.2 The referent is a <schema> element information item in
9005 * a well-formed information set, which in turn corresponds
9006 * to a valid schema.
9007 * NOTE: 2.2 won't apply, since only XML documents will be processed
9008 * here.
9009 */
9010 if (*doc == NULL) {
9011 xmlErrorPtr lerr;
9012 /*
9013 * It is *not* an error for the application schema reference
9014 * strategy to fail.
9015 *
9016 * If the doc is NULL and the parser error is an IO error we
9017 * will assume that the resource could not be located or accessed.
9018 *
9019 * TODO: Try to find specific error codes to react only on
9020 * localisation failures.
9021 *
9022 * TODO, FIXME: Check the spec: is a namespace added to the imported
9023 * namespaces, even if the schemaLocation did not provide
9024 * a resource? I guess so, since omitting the "schemaLocation"
9025 * attribute, imports a namespace as well.
9026 */
9027 lerr = xmlGetLastError();
9028 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
9029 xmlFreeParserCtxt(parserCtxt);
9030 return(0);
9031 }
9032
9033 xmlSchemaPCustomErr(ctxt,
9034 XML_SCHEMAP_SRC_IMPORT_2_1,
9035 NULL, NULL, node,
9036 "Failed to parse the resource '%s' for import",
9037 location);
9038 xmlFreeParserCtxt(parserCtxt);
9039 return(XML_SCHEMAP_SRC_IMPORT_2_1);
9040 }
9041 xmlFreeParserCtxt(parserCtxt);
9042
9043 root = xmlDocGetRootElement(*doc);
9044 if (root == NULL) {
9045 xmlSchemaPCustomErr(ctxt,
9046 XML_SCHEMAP_SRC_IMPORT_2_1,
9047 NULL, NULL, node,
9048 "The XML document '%s' to be imported has no document "
9049 "element", location);
9050 xmlFreeDoc(*doc);
9051 *doc = NULL;
9052 return (XML_SCHEMAP_SRC_IMPORT_2_1);
9053 }
9054
9055 xmlSchemaCleanupDoc(ctxt, root);
9056
9057 if (!IS_SCHEMA(root, "schema")) {
9058 xmlSchemaPCustomErr(ctxt,
9059 XML_SCHEMAP_SRC_IMPORT_2_1,
9060 NULL, NULL, node,
9061 "The XML document '%s' to be imported is not a XML schema document",
9062 location);
9063 xmlFreeDoc(*doc);
9064 *doc = NULL;
9065 return (XML_SCHEMAP_SRC_IMPORT_2_1);
9066 }
9067 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
9068 /*
9069 * Schema Representation Constraint: Import Constraints and Semantics
9070 */
9071 if (nsName == NULL) {
9072 if (*targetNamespace != NULL) {
9073 xmlSchemaPCustomErr(ctxt,
9074 XML_SCHEMAP_SRC_IMPORT_3_2,
9075 NULL, NULL, node,
9076 "The XML schema to be imported is not expected "
9077 "to have a target namespace; this differs from "
9078 "its target namespace of '%s'", *targetNamespace);
9079 xmlFreeDoc(*doc);
9080 *doc = NULL;
9081 return (XML_SCHEMAP_SRC_IMPORT_3_2);
9082 }
9083 } else {
9084 if (*targetNamespace == NULL) {
9085 xmlSchemaPCustomErr(ctxt,
9086 XML_SCHEMAP_SRC_IMPORT_3_1,
9087 NULL, NULL, node,
9088 "The XML schema to be imported is expected to have a target "
9089 "namespace of '%s'", nsName);
9090 xmlFreeDoc(*doc);
9091 *doc = NULL;
9092 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9093 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
9094 xmlSchemaPCustomErrExt(ctxt,
9095 XML_SCHEMAP_SRC_IMPORT_3_1,
9096 NULL, NULL, node,
9097 "The XML schema to be imported is expected to have a "
9098 "target namespace of '%s'; this differs from "
9099 "its target namespace of '%s'",
9100 nsName, *targetNamespace, NULL);
9101 xmlFreeDoc(*doc);
9102 *doc = NULL;
9103 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9104 }
9105 }
9106
9107 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
9108 if (import == NULL) {
9109 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
9110 NULL, NULL, NULL,
9111 "Internal error: xmlSchemaAcquireSchemaDoc, "
9112 "failed to build import table", NULL);
9113 xmlFreeDoc(*doc);
9114 *doc = NULL;
9115 return (-1);
9116 }
9117 import->schemaLocation = location;
9118 import->doc = *doc;
9119 return (0);
9120}
William M. Brack2f2a6632004-08-20 23:09:47 +00009121
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009122static void
9123xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9124 xmlSchemaPtr schema,
9125 const xmlChar *targetNamespace,
9126 xmlNodePtr node)
9127{
9128 const xmlChar *oldURL, **oldLocImps, *oldTNS;
9129 int oldFlags, oldNumLocImps, oldSizeLocImps;
9130
9131 /*
9132 * Save and reset the context & schema.
9133 */
9134 oldURL = pctxt->URL;
9135 /* TODO: Is using the doc->URL here correct? */
9136 pctxt->URL = node->doc->URL;
9137 oldLocImps = pctxt->localImports;
9138 pctxt->localImports = NULL;
9139 oldNumLocImps = pctxt->nbLocalImports;
9140 pctxt->nbLocalImports = 0;
9141 oldSizeLocImps = pctxt->sizeLocalImports;
9142 pctxt->sizeLocalImports = 0;
9143 oldFlags = schema->flags;
9144 xmlSchemaClearSchemaDefaults(schema);
9145 oldTNS = schema->targetNamespace;
9146 schema->targetNamespace = targetNamespace;
9147 /*
9148 * Parse the schema.
9149 */
9150 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9151 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9152 /*
9153 * Restore the context & schema.
9154 */
9155 schema->flags = oldFlags;
9156 schema->targetNamespace = oldTNS;
9157 if (pctxt->localImports != NULL)
9158 xmlFree((xmlChar *) pctxt->localImports);
9159 pctxt->localImports = oldLocImps;
9160 pctxt->nbLocalImports = oldNumLocImps;
9161 pctxt->sizeLocalImports = oldSizeLocImps;
9162 pctxt->URL = oldURL;
9163}
9164
William M. Brack2f2a6632004-08-20 23:09:47 +00009165/**
9166 * xmlSchemaParseImport:
9167 * @ctxt: a schema validation context
9168 * @schema: the schema being built
9169 * @node: a subtree containing XML Schema informations
9170 *
9171 * parse a XML schema Import definition
9172 * *WARNING* this interface is highly subject to change
9173 *
9174 * Returns 0 in case of success, a positive error code if
9175 * not valid and -1 in case of an internal error.
9176 */
9177static int
9178xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9179 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009180{
9181 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009182 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009183 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009184 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009185 xmlAttrPtr attr;
9186 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009187 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009188
9189 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9190 return (-1);
9191
9192 /*
9193 * Check for illegal attributes.
9194 */
9195 attr = node->properties;
9196 while (attr != NULL) {
9197 if (attr->ns == NULL) {
9198 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9199 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9200 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
9201 xmlSchemaPIllegalAttrErr(ctxt,
9202 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9203 NULL, NULL, attr);
9204 }
9205 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9206 xmlSchemaPIllegalAttrErr(ctxt,
9207 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9208 NULL, NULL, attr);
9209 }
9210 attr = attr->next;
9211 }
9212 /*
9213 * Extract and validate attributes.
9214 */
9215 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9216 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009217 &namespaceName) != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009218 xmlSchemaPSimpleTypeErr(ctxt,
9219 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9220 NULL, NULL, node,
9221 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009222 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009223 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9224 }
9225
9226 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9227 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
9228 &schemaLocation) != 0) {
9229 xmlSchemaPSimpleTypeErr(ctxt,
9230 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9231 NULL, NULL, node,
9232 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009233 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009234 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
9235 }
9236 /*
9237 * And now for the children...
9238 */
9239 child = node->children;
9240 if (IS_SCHEMA(child, "annotation")) {
9241 /*
9242 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009243 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009244 */
9245 child = child->next;
9246 }
9247 if (child != NULL) {
9248 xmlSchemaPContentErr(ctxt,
9249 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9250 NULL, NULL, node, child, NULL,
9251 "(annotation?)");
9252 }
9253 /*
9254 * Apply additional constraints.
9255 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009256 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009257 /*
9258 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9259 * must not match the ·actual value· of the enclosing <schema>'s
9260 * targetNamespace [attribute].
9261 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009262 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009263 xmlSchemaPCustomErr(ctxt,
9264 XML_SCHEMAP_SRC_IMPORT_1_1,
9265 NULL, NULL, node,
9266 "The value of the attribute 'namespace' must not match "
9267 "the target namespace '%s' of the importing schema",
9268 schema->targetNamespace);
9269 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9270 }
9271 } else {
9272 /*
9273 * 1.2 If the namespace [attribute] is not present, then the enclosing
9274 * <schema> must have a targetNamespace [attribute].
9275 */
9276 if (schema->targetNamespace == NULL) {
9277 xmlSchemaPCustomErr(ctxt,
9278 XML_SCHEMAP_SRC_IMPORT_1_2,
9279 NULL, NULL, node,
9280 "The attribute 'namespace' must be existent if "
9281 "the importing schema has no target namespace",
9282 NULL);
9283 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9284 }
9285 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009286 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009287 * Add the namespace to the list of locally imported namespace.
9288 */
9289 if (ctxt->localImports == NULL) {
9290 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
9291 sizeof(const xmlChar*));
9292 ctxt->sizeLocalImports = 10;
9293 ctxt->nbLocalImports = 0;
9294 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9295 ctxt->sizeLocalImports *= 2;
9296 ctxt->localImports = (const xmlChar **) xmlRealloc(
9297 (xmlChar **) ctxt->localImports,
9298 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9299 }
9300 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9301 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009302 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009303 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009304 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009305 schemaLocation, &doc, &targetNamespace, 0);
9306 if (ret != 0) {
9307 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009308 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009309 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009310 } else if (doc != NULL) {
9311 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9312 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009313 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009314
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009315 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009316}
9317
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009318/**
9319 * xmlSchemaParseInclude:
9320 * @ctxt: a schema validation context
9321 * @schema: the schema being built
9322 * @node: a subtree containing XML Schema informations
9323 *
9324 * parse a XML schema Include definition
9325 *
William M. Bracke7091952004-05-11 15:09:58 +00009326 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009327 * 1 in case of success.
9328 */
9329static int
9330xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9331 xmlNodePtr node)
9332{
9333 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009334 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009335 xmlDocPtr doc = NULL;
9336 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009337 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009338 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009339 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009340 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009341
9342
9343 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9344 return (-1);
9345
9346 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009347 * Check for illegal attributes.
9348 */
9349 attr = node->properties;
9350 while (attr != NULL) {
9351 if (attr->ns == NULL) {
9352 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9353 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
9354 xmlSchemaPIllegalAttrErr(ctxt,
9355 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9356 NULL, NULL, attr);
9357 }
9358 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9359 xmlSchemaPIllegalAttrErr(ctxt,
9360 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9361 NULL, NULL, attr);
9362 }
9363 attr = attr->next;
9364 }
9365 /*
9366 * Extract and validate attributes.
9367 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009368 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009369 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009370 * Preliminary step, extract the URI-Reference for the include and
9371 * make an URI from the base.
9372 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009373 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9374 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009375 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009376 xmlChar *uri = NULL;
9377
9378 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9379 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009380 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009381 base = xmlNodeGetBase(node->doc, node);
9382 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009383 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009384 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009385 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009386 xmlFree(base);
9387 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009388 if (uri == NULL) {
9389 xmlSchemaPErr(ctxt,
9390 node,
9391 XML_SCHEMAP_INTERNAL,
9392 "Internal error: xmlSchemaParseInclude, "
9393 "could not build an URI from the schemaLocation.\n",
9394 NULL, NULL);
9395 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009396 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009397 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9398 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009399 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009400 xmlSchemaPMissingAttrErr(ctxt,
9401 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9402 NULL, NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009403 goto exit_invalid;
9404 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009405 /*
9406 * And now for the children...
9407 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009408 child = node->children;
9409 while (IS_SCHEMA(child, "annotation")) {
9410 /*
9411 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009412 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009413 */
9414 child = child->next;
9415 }
9416 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009417 xmlSchemaPContentErr(ctxt,
9418 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9419 NULL, NULL, node, child, NULL,
9420 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009421 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009422 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009423 * Report self-inclusion.
9424 */
9425 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9426 xmlSchemaPCustomErr(ctxt,
9427 XML_SCHEMAP_SRC_INCLUDE,
9428 NULL, NULL, node,
9429 "The schema document '%s' cannot include itself.",
9430 schemaLocation);
9431 return (XML_SCHEMAP_SRC_INCLUDE);
9432 }
9433 /*
9434 * Check if this one was already processed to avoid incorrect
9435 * duplicate component errors and infinite circular inclusion.
9436 */
9437 include = schema->includes;
9438 while (include != NULL) {
9439 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9440 targetNamespace = include->origTargetNamespace;
9441 if (targetNamespace == NULL) {
9442 /*
9443 * Chameleon include: skip only if it was build for
9444 * the targetNamespace of the including schema.
9445 */
9446 if (xmlStrEqual(schema->targetNamespace,
9447 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009448 goto check_targetNamespace;
9449 }
9450 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009451 goto check_targetNamespace;
9452 }
9453 }
9454 include = include->next;
9455 }
9456 /*
9457 * First step is to parse the input document into an DOM/Infoset
9458 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009459 */
9460 parserCtxt = xmlNewParserCtxt();
9461 if (parserCtxt == NULL) {
9462 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9463 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009464 goto exit_failure;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009465 }
9466
9467 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9468 xmlDictFree(parserCtxt->dict);
9469 parserCtxt->dict = ctxt->dict;
9470 xmlDictReference(parserCtxt->dict);
9471 }
9472
9473 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
9474 NULL, SCHEMAS_PARSE_OPTIONS);
9475 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009476 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009477 /*
9478 * TODO: It is not an error for the ·actual value· of the
9479 * schemaLocation [attribute] to fail to resolve it all, in which
9480 * case no corresponding inclusion is performed.
9481 * So do we need a warning report here?
9482 */
9483 xmlSchemaPCustomErr(ctxt,
9484 XML_SCHEMAP_FAILED_LOAD,
9485 NULL, NULL, node,
9486 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009487 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009488 }
9489
9490 /*
9491 * Then extract the root of the schema
9492 */
9493 root = xmlDocGetRootElement(doc);
9494 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009495 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009496 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009497 NULL, NULL, node,
9498 "The included document '%s' has no document "
9499 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009500 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009501 }
9502
9503 /*
9504 * Remove all the blank text nodes
9505 */
9506 xmlSchemaCleanupDoc(ctxt, root);
9507
9508 /*
9509 * Check the schemas top level element
9510 */
9511 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009512 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009513 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009514 NULL, NULL, node,
9515 "The document '%s' to be included is not a schema document",
9516 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009517 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009518 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009519
William M. Brack2f2a6632004-08-20 23:09:47 +00009520 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009521 /*
9522 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9523 * value· is identical to the ·actual value· of the targetNamespace
9524 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9525 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009526check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009527 if (targetNamespace != NULL) {
9528 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009529 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009530 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009531 NULL, NULL, node,
9532 "The target namespace of the included schema "
9533 "'%s' has to be absent, since the including schema "
9534 "has no target namespace",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009535 schemaLocation);
9536 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009537 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9538 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009539 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009540 NULL, NULL, node,
9541 "The target namespace '%s' of the included schema '%s' "
9542 "differs from '%s' of the including schema",
9543 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009544 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009545 }
9546 } else if (schema->targetNamespace != NULL) {
9547 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
9548 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
9549 } else
9550 wasConvertingNs = 1;
9551 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009552
9553 if (include != NULL)
9554 goto exit;
9555
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009556 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009557 * URGENT TODO: If the schema is a chameleon-include then copy the
9558 * components into the including schema and modify the targetNamespace
9559 * of those components, do nothing otherwise.
9560 * NOTE: This is currently worked-around by compiling the chameleon
9561 * for every destinct including targetNamespace; thus not performant at
9562 * the moment.
9563 * TODO: Check when the namespace in wildcards for chameleons needs
9564 * to be converted: before we built wildcard intersections or after.
9565 */
9566 /*
9567 * Register the include.
9568 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009569 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9570 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009571 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9572 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009573 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009574 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009575 include->next = schema->includes;
9576 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009577 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009578 * TODO: Use the resolved URI for the this location, since it might
9579 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009580 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009581 include->schemaLocation = schemaLocation;
9582 include->doc = doc;
9583 /*
9584 * In case of chameleons, the original target namespace will differ
9585 * from the resulting namespace.
9586 */
9587 include->origTargetNamespace = targetNamespace;
9588 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009589#ifdef DEBUG_INCLUDES
9590 if (targetNamespace != schema->targetNamespace)
9591 xmlGenericError(xmlGenericErrorContext,
9592 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9593 " into TNS '%s'\n", schemaLocation,
9594 targetNamespace, schema->targetNamespace);
9595 else
9596 xmlGenericError(xmlGenericErrorContext,
9597 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9598 targetNamespace);
9599#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009600 /*
9601 * Compile the included schema.
9602 */
9603 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9604
9605exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009606 /*
9607 * Remove the converting flag.
9608 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009609 if ((wasConvertingNs == 0) &&
9610 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009611 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009612 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009613
9614exit_invalid:
9615 if (doc != NULL) {
9616 if (include != NULL)
9617 include->doc = NULL;
9618 xmlFreeDoc(doc);
9619 }
9620 return (ctxt->err);
9621
9622exit_failure:
9623 if (doc != NULL) {
9624 if (include != NULL)
9625 include->doc = NULL;
9626 xmlFreeDoc(doc);
9627 }
9628 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009629}
9630
9631/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009632 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009633 * @ctxt: a schema validation context
9634 * @schema: the schema being built
9635 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009636 * @type: the "compositor" type
9637 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009638 *
9639 * parse a XML schema Sequence definition
9640 * *WARNING* this interface is highly subject to change
9641 *
William M. Bracke7091952004-05-11 15:09:58 +00009642 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009643 * 1 in case of success.
9644 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009645static xmlSchemaTreeItemPtr
9646xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9647 xmlNodePtr node, xmlSchemaTypeType type,
9648 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009649{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009650 xmlSchemaModelGroupPtr item;
9651 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009652 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009653 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009654 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009655 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009656
9657 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009658 return (NULL);
9659 /*
9660 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009661 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009662 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9663 if (item == NULL)
9664 return (NULL);
9665
9666 if (withParticle) {
9667 if (type == XML_SCHEMA_TYPE_ALL) {
9668 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
9669 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
9670 } else {
9671 /* choice + sequence */
9672 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
9673 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9674 "(nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009675 }
9676 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009677 /*
9678 * Create a particle
9679 */
9680 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9681 if (particle == NULL)
9682 return (NULL);
9683 particle->children = (xmlSchemaTreeItemPtr) item;
9684 /*
9685 * Check for illegal attributes.
9686 */
9687 attr = node->properties;
9688 while (attr != NULL) {
9689 if (attr->ns == NULL) {
9690 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9691 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9692 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
9693 xmlSchemaPIllegalAttrErr(ctxt,
9694 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9695 NULL, NULL, attr);
9696 }
9697 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009698 xmlSchemaPIllegalAttrErr(ctxt,
9699 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009700 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009701 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009702 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009703 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009704 } else {
9705 /*
9706 * Check for illegal attributes.
9707 */
9708 attr = node->properties;
9709 while (attr != NULL) {
9710 if (attr->ns == NULL) {
9711 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9712 xmlSchemaPIllegalAttrErr(ctxt,
9713 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9714 NULL, NULL, attr);
9715 }
9716 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9717 xmlSchemaPIllegalAttrErr(ctxt,
9718 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9719 NULL, NULL, attr);
9720 }
9721 attr = attr->next;
9722 }
9723
William M. Brack2f2a6632004-08-20 23:09:47 +00009724 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009725
William M. Brack2f2a6632004-08-20 23:09:47 +00009726 /*
9727 * Extract and validate attributes.
9728 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009729 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009730 /*
9731 * And now for the children...
9732 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009733 child = node->children;
9734 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009735 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009736 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009737 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009738 oldcontainer = ctxt->container;
9739 ctxt->container = container;
9740 if (type == XML_SCHEMA_TYPE_ALL) {
9741 xmlSchemaParticlePtr part, last = NULL;
9742
9743 while (IS_SCHEMA(child, "element")) {
9744 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9745 schema, child, 0);
9746 if (part != NULL) {
9747 if (part->minOccurs > 1)
9748 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
9749 NULL, NULL, child,
9750 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9751 if (part->maxOccurs > 1)
9752 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
9753 NULL, NULL, child,
9754 "Invalid value for maxOccurs (must be 0 or 1)",
9755 NULL);
9756 if (last == NULL)
9757 item->children = (xmlSchemaTreeItemPtr) part;
9758 else
9759 last->next = (xmlSchemaTreeItemPtr) part;
9760 last = part;
9761 }
9762 child = child->next;
9763 }
9764 if (child != NULL) {
9765 xmlSchemaPContentErr(ctxt,
9766 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9767 NULL, NULL, node, child, NULL,
9768 "(annotation?, (annotation?, element*)");
9769 }
9770 } else {
9771 /* choice + sequence */
9772 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9773
9774 while ((IS_SCHEMA(child, "element")) ||
9775 (IS_SCHEMA(child, "group")) ||
9776 (IS_SCHEMA(child, "any")) ||
9777 (IS_SCHEMA(child, "choice")) ||
9778 (IS_SCHEMA(child, "sequence"))) {
9779
9780 if (IS_SCHEMA(child, "element")) {
9781 part = (xmlSchemaTreeItemPtr)
9782 xmlSchemaParseElement(ctxt, schema, child, 0);
9783 } else if (IS_SCHEMA(child, "group")) {
9784 part =
9785 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9786 } else if (IS_SCHEMA(child, "any")) {
9787 part = (xmlSchemaTreeItemPtr)
9788 xmlSchemaParseAny(ctxt, schema, child);
9789 } else if (IS_SCHEMA(child, "choice")) {
9790 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9791 XML_SCHEMA_TYPE_CHOICE, 1);
9792 } else if (IS_SCHEMA(child, "sequence")) {
9793 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9794 XML_SCHEMA_TYPE_SEQUENCE, 1);
9795 }
9796 if (part != NULL) {
9797 if (last == NULL)
9798 item->children = part;
9799 else
9800 last->next = part;
9801 last = part;
9802 }
9803 child = child->next;
9804 }
9805 if (child != NULL) {
9806 xmlSchemaPContentErr(ctxt,
9807 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9808 NULL, NULL, node, child, NULL,
9809 "(annotation?, (element | group | choice | sequence | any)*)");
9810 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009811 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009812 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009813 if (withParticle) {
9814 if ((min == 0) && (max == 0))
9815 return (NULL);
9816 else
9817 return ((xmlSchemaTreeItemPtr) particle);
9818 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009819 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009820}
9821
9822/**
9823 * xmlSchemaParseRestriction:
9824 * @ctxt: a schema validation context
9825 * @schema: the schema being built
9826 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009827 *
9828 * parse a XML schema Restriction definition
9829 * *WARNING* this interface is highly subject to change
9830 *
9831 * Returns the type definition or NULL in case of error
9832 */
9833static xmlSchemaTypePtr
9834xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009835 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009836{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009837 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009838 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009839 char buf[30];
9840 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009841 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009842
9843 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9844 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009845 /* Not a component, don't create it. */
9846 type = ctxt->ctxtType;
9847 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
9848
9849 /*
9850 * TODO: Is the container needed at all? the anonymous
9851 * items inside should generate unique names already.
9852 */
9853 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
9854 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009855 /*
9856 * Check for illegal attributes.
9857 */
9858 attr = node->properties;
9859 while (attr != NULL) {
9860 if (attr->ns == NULL) {
9861 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9862 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
9863 xmlSchemaPIllegalAttrErr(ctxt,
9864 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009865 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009866 }
9867 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9868 xmlSchemaPIllegalAttrErr(ctxt,
9869 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009870 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009871 }
9872 attr = attr->next;
9873 }
9874 /*
9875 * Extract and validate attributes.
9876 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009877 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009878 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009879 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009880 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009881 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009882 NULL, NULL, node, "base",
9883 &(type->baseNs), NULL,
9884 &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009885 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009886 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009887 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009888 XML_SCHEMAP_S4S_ATTR_MISSING,
William M. Brack2f2a6632004-08-20 23:09:47 +00009889 NULL, type, node, "base", NULL);
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009890 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009891 /*
9892 * And now for the children...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009893 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009894 child = node->children;
9895 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009896 /*
9897 * Add the annotation to the simple type ancestor.
9898 */
9899 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9900 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009901 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009902 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009903 oldcontainer = ctxt->container;
9904 ctxt->container = container;
9905 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9906 /*
9907 * Corresponds to <simpleType><restriction><simpleType>.
9908 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009909 if (IS_SCHEMA(child, "simpleType")) {
9910 if (type->base != NULL) {
9911 /*
9912 * src-restriction-base-or-simpleType
9913 * Either the base [attribute] or the simpleType [child] of the
9914 * <restriction> element must be present, but not both.
9915 */
9916 xmlSchemaPContentErr(ctxt,
9917 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009918 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009919 "The attribute 'base' and the <simpleType> child are "
9920 "mutually exclusive", NULL);
9921 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009922 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009923 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009924 }
9925 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009926 } else if (type->base == NULL) {
9927 xmlSchemaPContentErr(ctxt,
9928 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9929 NULL, NULL, node, child,
9930 "Either the attribute 'base' or a <simpleType> child "
9931 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009932 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009933 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9934 /*
9935 * Corresponds to <complexType><complexContent><restriction>...
9936 * followed by:
9937 *
9938 * Model groups <all>, <choice> and <sequence>.
9939 */
9940 if (IS_SCHEMA(child, "all")) {
9941 type->subtypes = (xmlSchemaTypePtr)
9942 xmlSchemaParseModelGroup(ctxt, schema, child,
9943 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009944 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009945 } else if (IS_SCHEMA(child, "choice")) {
9946 type->subtypes = (xmlSchemaTypePtr)
9947 xmlSchemaParseModelGroup(ctxt,
9948 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9949 child = child->next;
9950 } else if (IS_SCHEMA(child, "sequence")) {
9951 type->subtypes = (xmlSchemaTypePtr)
9952 xmlSchemaParseModelGroup(ctxt, schema, child,
9953 XML_SCHEMA_TYPE_SEQUENCE, 1);
9954 child = child->next;
9955 /*
9956 * Model group reference <group>.
9957 */
9958 } else if (IS_SCHEMA(child, "group")) {
9959 type->subtypes = (xmlSchemaTypePtr)
9960 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9961 child = child->next;
9962 }
9963 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
9964 xmlSchemaTypePtr contType, baseType = NULL;
9965 /*
9966 * Corresponds to <complexType><simpleContent><restriction>...
9967 *
9968 * SPEC (content type):
9969 * "1 If the type definition ·resolved· to by the ·actual value· of
9970 * the base [attribute] is a complex type definition whose own
9971 * {content type} is a simple type definition and the <restriction>
9972 * alternative is chosen, then starting from either" ...
9973 *
9974 * "1.1 the simple type definition corresponding to the <simpleType>
9975 * among the [children] of <restriction> if there is one;"
9976 */
9977 if (IS_SCHEMA(child, "simpleType")) {
9978
9979 baseType = (xmlSchemaTypePtr)
9980 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9981 if (baseType == NULL)
9982 return (NULL);
9983 child = child->next;
9984 }
9985 /*
9986 * SPEC
9987 * "... a simple type definition which restricts the simple type
9988 * definition identified in clause 1.1 or clause 1.2 with a set
9989 * of facet components"
9990 *
9991 * Create the anonymous simple type, which will be the content type
9992 * of the complex type.
9993 * Note that we will use the same node as for the <restriction> to
9994 * have it somehow anchored in the schema doc.
9995 */
9996 snprintf(buf, 29, "#scST%d", ctxt->counter++ + 1);
9997 contType = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf,
9998 container, node);
9999 if (contType == NULL)
10000 return (NULL);
10001 contType->node = node;
10002 contType->type = XML_SCHEMA_TYPE_SIMPLE;
10003 contType->baseType = baseType;
10004 type->contentTypeDef = contType;
William M. Brack2f2a6632004-08-20 23:09:47 +000010005 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010006
10007 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
10008 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
10009 xmlSchemaFacetPtr facet, lastfacet = NULL;
10010 xmlSchemaTypePtr facetHolder;
10011
10012 if (parentType == XML_SCHEMA_TYPE_SIMPLE)
10013 facetHolder = type;
10014 else
10015 facetHolder = type->contentTypeDef;
10016 /*
10017 * Corresponds to <complexType><simpleContent><restriction>...
10018 * <simpleType><restriction>...
10019 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010020
Daniel Veillard01fa6152004-06-29 17:04:39 +000010021 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010022 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010023 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010024 /*
10025 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
10026 * Simple Type Definition Schema Representation Constraint:
10027 * *Single Facet Value*
10028 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010029 while ((IS_SCHEMA(child, "minInclusive")) ||
10030 (IS_SCHEMA(child, "minExclusive")) ||
10031 (IS_SCHEMA(child, "maxInclusive")) ||
10032 (IS_SCHEMA(child, "maxExclusive")) ||
10033 (IS_SCHEMA(child, "totalDigits")) ||
10034 (IS_SCHEMA(child, "fractionDigits")) ||
10035 (IS_SCHEMA(child, "pattern")) ||
10036 (IS_SCHEMA(child, "enumeration")) ||
10037 (IS_SCHEMA(child, "whiteSpace")) ||
10038 (IS_SCHEMA(child, "length")) ||
10039 (IS_SCHEMA(child, "maxLength")) ||
10040 (IS_SCHEMA(child, "minLength"))) {
10041 facet = xmlSchemaParseFacet(ctxt, schema, child);
10042 if (facet != NULL) {
10043 if (lastfacet == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010044 facetHolder->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010045 else
10046 lastfacet->next = facet;
10047 lastfacet = facet;
10048 lastfacet->next = NULL;
10049 }
10050 child = child->next;
10051 }
10052 /*
10053 * Create links for derivation and validation.
10054 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010055 if (facetHolder->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010056 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
10057
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010058 facet = facetHolder->facets;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010059 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010060 facetLink = (xmlSchemaFacetLinkPtr)
10061 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000010062 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010063 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010064 xmlFree(facetLink);
10065 return (NULL);
10066 }
10067 facetLink->facet = facet;
10068 facetLink->next = NULL;
10069 if (lastFacetLink == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010070 facetHolder->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010071 else
10072 lastFacetLink->next = facetLink;
10073 lastFacetLink = facetLink;
10074 facet = facet->next;
10075 } while (facet != NULL);
10076 }
10077 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010078 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
10079 /*
10080 * Attribute uses/declarations.
10081 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010082 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010083 /*
10084 * Attribute wildcard.
10085 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010086 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010087 type->attributeWildcard =
10088 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010089 child = child->next;
10090 }
10091 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010092 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010093 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010094 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010095 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10096 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010097 "annotation?, (group | all | choice | sequence)?, "
10098 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010099 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010100 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010101 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10102 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010103 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10104 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10105 "length | minLength | maxLength | enumeration | whiteSpace | "
10106 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10107 } else {
10108 /* Simple type */
10109 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010110 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10111 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010112 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10113 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10114 "length | minLength | maxLength | enumeration | whiteSpace | "
10115 "pattern)*))");
10116 }
10117 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010118 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010119 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010120}
10121
10122/**
10123 * xmlSchemaParseExtension:
10124 * @ctxt: a schema validation context
10125 * @schema: the schema being built
10126 * @node: a subtree containing XML Schema informations
10127 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010128 * Parses an <extension>, which is found inside a
10129 * <simpleContent> or <complexContent>.
10130 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010131 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010132 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010133 */
10134static xmlSchemaTypePtr
10135xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010136 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010137{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010138 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010139 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010140 char buf[30];
10141 const xmlChar *oldcontainer, *container;
10142 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010143
10144 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10145 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010146 /* Not a component, don't create it. */
10147 type = ctxt->ctxtType;
10148 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010149
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010150 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10151 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10152 /*
10153 * Check for illegal attributes.
10154 */
10155 attr = node->properties;
10156 while (attr != NULL) {
10157 if (attr->ns == NULL) {
10158 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10159 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
10160 xmlSchemaPIllegalAttrErr(ctxt,
10161 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10162 NULL, NULL, attr);
10163 }
10164 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10165 xmlSchemaPIllegalAttrErr(ctxt,
10166 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10167 NULL, NULL, attr);
10168 }
10169 attr = attr->next;
10170 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010171
10172 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010173
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010174 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010175 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010176 */
10177 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010178 NULL, NULL, node, "base", &(type->baseNs), NULL,
10179 &(type->base)) == 0) && (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010180 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010181 XML_SCHEMAP_S4S_ATTR_MISSING,
10182 NULL, NULL, node, "base", NULL);
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010183 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010184 /*
10185 * And now for the children...
10186 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010187 child = node->children;
10188 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010189 /*
10190 * Add the annotation to the type ancestor.
10191 */
10192 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10193 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010194 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010195 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010196 oldcontainer = ctxt->container;
10197 ctxt->container = container;
10198 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10199 /*
10200 * Corresponds to <complexType><complexContent><extension>... and:
10201 *
10202 * Model groups <all>, <choice>, <sequence> and <group>.
10203 */
10204 if (IS_SCHEMA(child, "all")) {
10205 type->subtypes = (xmlSchemaTypePtr)
10206 xmlSchemaParseModelGroup(ctxt, schema,
10207 child, XML_SCHEMA_TYPE_ALL, 1);
10208 child = child->next;
10209 } else if (IS_SCHEMA(child, "choice")) {
10210 type->subtypes = (xmlSchemaTypePtr)
10211 xmlSchemaParseModelGroup(ctxt, schema,
10212 child, XML_SCHEMA_TYPE_CHOICE, 1);
10213 child = child->next;
10214 } else if (IS_SCHEMA(child, "sequence")) {
10215 type->subtypes = (xmlSchemaTypePtr)
10216 xmlSchemaParseModelGroup(ctxt, schema,
10217 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10218 child = child->next;
10219 } else if (IS_SCHEMA(child, "group")) {
10220 type->subtypes = (xmlSchemaTypePtr)
10221 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10222 child = child->next;
10223 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010224 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010225 if (child != NULL) {
10226 /*
10227 * Attribute uses/declarations.
10228 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010229 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010230 /*
10231 * Attribute wildcard.
10232 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010233 if (IS_SCHEMA(child, "anyAttribute")) {
10234 ctxt->ctxtType->attributeWildcard =
10235 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10236 child = child->next;
10237 }
10238 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010239 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010240 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10241 /* Complex content extension. */
10242 xmlSchemaPContentErr(ctxt,
10243 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10244 NULL, NULL, node, child, NULL,
10245 "(annotation?, ((group | all | choice | sequence)?, "
10246 "((attribute | attributeGroup)*, anyAttribute?)))");
10247 } else {
10248 /* Simple content extension. */
10249 xmlSchemaPContentErr(ctxt,
10250 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10251 NULL, NULL, node, child, NULL,
10252 "(annotation?, ((attribute | attributeGroup)*, "
10253 "anyAttribute?))");
10254 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010255 }
10256 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010257 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010258}
10259
10260/**
10261 * xmlSchemaParseSimpleContent:
10262 * @ctxt: a schema validation context
10263 * @schema: the schema being built
10264 * @node: a subtree containing XML Schema informations
10265 *
10266 * parse a XML schema SimpleContent definition
10267 * *WARNING* this interface is highly subject to change
10268 *
10269 * Returns the type definition or NULL in case of error
10270 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010271static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010272xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10273 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010274{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010275 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010276 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010277 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010278
10279 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010280 return (-1);
10281 /* Not a component, don't create it. */
10282 type = ctxt->ctxtType;
10283 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10284 /*
10285 * Check for illegal attributes.
10286 */
10287 attr = node->properties;
10288 while (attr != NULL) {
10289 if (attr->ns == NULL) {
10290 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
10291 xmlSchemaPIllegalAttrErr(ctxt,
10292 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10293 NULL, NULL, attr);
10294 }
10295 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10296 xmlSchemaPIllegalAttrErr(ctxt,
10297 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10298 NULL, NULL, attr);
10299 }
10300 attr = attr->next;
10301 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010302
10303 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010304
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010305 /*
10306 * And now for the children...
10307 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010308 child = node->children;
10309 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010310 /*
10311 * Add the annotation to the complex type ancestor.
10312 */
10313 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10314 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010315 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010316 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010317 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010318 xmlSchemaParseRestriction(ctxt, schema, child,
10319 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010320 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010321 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010322 xmlSchemaParseExtension(ctxt, schema, child,
10323 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010324 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010325 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010326 if (child != NULL) {
10327 xmlSchemaPContentErr(ctxt,
10328 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10329 NULL, NULL, node, child, NULL,
10330 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010331 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010332 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010333}
10334
10335/**
10336 * xmlSchemaParseComplexContent:
10337 * @ctxt: a schema validation context
10338 * @schema: the schema being built
10339 * @node: a subtree containing XML Schema informations
10340 *
10341 * parse a XML schema ComplexContent definition
10342 * *WARNING* this interface is highly subject to change
10343 *
10344 * Returns the type definition or NULL in case of error
10345 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010346static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010347xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10348 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010349{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010350 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010351 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010352 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010353
10354 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010355 return (-1);
10356 /* Not a component, don't create it. */
10357 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010358 /*
10359 * Check for illegal attributes.
10360 */
10361 attr = node->properties;
10362 while (attr != NULL) {
10363 if (attr->ns == NULL) {
10364 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10365 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
10366 {
10367 xmlSchemaPIllegalAttrErr(ctxt,
10368 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10369 NULL, NULL, attr);
10370 }
10371 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10372 xmlSchemaPIllegalAttrErr(ctxt,
10373 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10374 NULL, NULL, attr);
10375 }
10376 attr = attr->next;
10377 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010378
10379 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10380
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010381 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010382 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010383 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010384 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10385 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10386 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010387 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010388 child = node->children;
10389 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010390 /*
10391 * Add the annotation to the complex type ancestor.
10392 */
10393 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10394 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010395 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010396 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010397 if (IS_SCHEMA(child, "restriction")) {
10398 xmlSchemaParseRestriction(ctxt, schema, child,
10399 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010400 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010401 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010402 xmlSchemaParseExtension(ctxt, schema, child,
10403 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010404 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010405 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010406 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010407 xmlSchemaPContentErr(ctxt,
10408 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10409 NULL, NULL, node, child,
10410 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010411 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010412 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010413}
10414
10415/**
10416 * xmlSchemaParseComplexType:
10417 * @ctxt: a schema validation context
10418 * @schema: the schema being built
10419 * @node: a subtree containing XML Schema informations
10420 *
10421 * parse a XML schema Complex Type definition
10422 * *WARNING* this interface is highly subject to change
10423 *
10424 * Returns the type definition or NULL in case of error
10425 */
10426static xmlSchemaTypePtr
10427xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010428 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010429{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010430 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010431 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010432 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010433 xmlAttrPtr attr;
10434 const xmlChar *attrValue;
10435 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010436 char buf[40];
10437
Daniel Veillard4255d502002-04-16 15:50:10 +000010438
10439 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10440 return (NULL);
10441
Daniel Veillard01fa6152004-06-29 17:04:39 +000010442 ctxtType = ctxt->ctxtType;
10443
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010444 if (topLevel) {
10445 attr = xmlSchemaGetPropNode(node, "name");
10446 if (attr == NULL) {
10447 xmlSchemaPMissingAttrErr(ctxt,
10448 XML_SCHEMAP_S4S_ATTR_MISSING,
10449 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
10450 "name", NULL);
10451 return (NULL);
10452 } else if (xmlSchemaPValAttrNode(ctxt,
10453 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
10454 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10455 return (NULL);
10456 }
10457 }
10458
10459 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010460 /*
10461 * Parse as local complex type definition.
10462 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010463 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010464 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10465 if (type == NULL)
10466 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010467 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010468 type->node = node;
10469 type->type = XML_SCHEMA_TYPE_COMPLEX;
10470 /*
10471 * TODO: We need the target namespace.
10472 */
10473 } else {
10474 /*
10475 * Parse as global complex type definition.
10476 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010477 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010478 if (type == NULL)
10479 return (NULL);
10480 type->node = node;
10481 type->type = XML_SCHEMA_TYPE_COMPLEX;
10482 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
10483 /*
10484 * Set defaults.
10485 */
10486 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010487 }
10488 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010489 /*
10490 * Handle attributes.
10491 */
10492 attr = node->properties;
10493 while (attr != NULL) {
10494 if (attr->ns == NULL) {
10495 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10496 /*
10497 * Attribute "id".
10498 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010499 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10500 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010501 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10502 /*
10503 * Attribute "mixed".
10504 */
10505 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10506 (xmlNodePtr) attr))
10507 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10508 } else if (topLevel) {
10509 /*
10510 * Attributes of global complex type definitions.
10511 */
10512 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10513 /* Pass. */
10514 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10515 /*
10516 * Attribute "abstract".
10517 */
10518 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10519 (xmlNodePtr) attr))
10520 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10521 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10522 /*
10523 * Attribute "final".
10524 */
10525 attrValue = xmlSchemaGetNodeContent(ctxt,
10526 (xmlNodePtr) attr);
10527 if (xmlSchemaPValAttrBlockFinal(attrValue,
10528 &(type->flags),
10529 -1,
10530 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10531 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10532 -1, -1, -1) != 0)
10533 {
10534 xmlSchemaPSimpleTypeErr(ctxt,
10535 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10536 &des, type, (xmlNodePtr) attr,
10537 NULL,
10538 "(#all | List of (extension | restriction))",
10539 attrValue, NULL, NULL, NULL);
10540 }
10541 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10542 /*
10543 * Attribute "block".
10544 */
10545 attrValue = xmlSchemaGetNodeContent(ctxt,
10546 (xmlNodePtr) attr);
10547 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
10548 -1,
10549 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
10550 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
10551 -1, -1, -1) != 0) {
10552 xmlSchemaPSimpleTypeErr(ctxt,
10553 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10554 &des, type, (xmlNodePtr) attr,
10555 NULL,
10556 "(#all | List of (extension | restriction)) ",
10557 attrValue, NULL, NULL, NULL);
10558 }
10559 } else {
10560 xmlSchemaPIllegalAttrErr(ctxt,
10561 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10562 &des, type, attr);
10563 }
10564 } else {
10565 xmlSchemaPIllegalAttrErr(ctxt,
10566 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10567 &des, type, attr);
10568 }
10569 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10570 xmlSchemaPIllegalAttrErr(ctxt,
10571 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10572 &des, type, attr);
10573 }
10574 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010575 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010576 if (xmlSchemaGetPropNode(node, "block") == NULL) {
10577 /*
10578 * Apply default "block" values.
10579 */
10580 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10581 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10582 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10583 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10584 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010585 /*
10586 * And now for the children...
10587 */
10588 oldcontainer = ctxt->container;
10589 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010590 child = node->children;
10591 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010592 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10593 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010594 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010595 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010596 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010597 /*
10598 * 3.4.3 : 2.2
10599 * Specifying mixed='true' when the <simpleContent>
10600 * alternative is chosen has no effect
10601 */
William M. Bracke7091952004-05-11 15:09:58 +000010602 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10603 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010604 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010605 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010606 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010607 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10608 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010609 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010610 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010611 /*
10612 * SPEC
10613 * "...the third alternative (neither <simpleContent> nor
10614 * <complexContent>) is chosen. This case is understood as shorthand
10615 * for complex content restricting the ·ur-type definition·, and the
10616 * details of the mappings should be modified as necessary.
10617 */
10618 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10619 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010620 /*
10621 * Parse model groups.
10622 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010623 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010624 type->subtypes = (xmlSchemaTypePtr)
10625 xmlSchemaParseModelGroup(ctxt, schema, child,
10626 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010627 child = child->next;
10628 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010629 type->subtypes = (xmlSchemaTypePtr)
10630 xmlSchemaParseModelGroup(ctxt, schema, child,
10631 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010632 child = child->next;
10633 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010634 type->subtypes = (xmlSchemaTypePtr)
10635 xmlSchemaParseModelGroup(ctxt, schema, child,
10636 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010637 child = child->next;
10638 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010639 type->subtypes = (xmlSchemaTypePtr)
10640 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010641 child = child->next;
10642 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010643 /*
10644 * Parse attribute decls/refs.
10645 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010646 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010647 /*
10648 * Parse attribute wildcard.
10649 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010650 if (IS_SCHEMA(child, "anyAttribute")) {
10651 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10652 child = child->next;
10653 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010654 }
10655 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010656 xmlSchemaPContentErr(ctxt,
10657 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10658 &des, type, node, child,
10659 NULL, "(annotation?, (simpleContent | complexContent | "
10660 "((group | all | choice | sequence)?, ((attribute | "
10661 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010662 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010663 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010664 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010665 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010666 return (type);
10667}
10668
Daniel Veillard4255d502002-04-16 15:50:10 +000010669/**
10670 * xmlSchemaParseSchema:
10671 * @ctxt: a schema validation context
10672 * @node: a subtree containing XML Schema informations
10673 *
10674 * parse a XML schema definition from a node set
10675 * *WARNING* this interface is highly subject to change
10676 *
10677 * Returns the internal XML Schema structure built from the resource or
10678 * NULL in case of error
10679 */
10680static xmlSchemaPtr
10681xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10682{
10683 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010684 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010685 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010686 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010687
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010688 /*
10689 * This one is called by xmlSchemaParse only and is used if
10690 * the schema to be parsed was specified via the API; i.e. not
10691 * automatically by the validated instance document.
10692 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010693 if ((ctxt == NULL) || (node == NULL))
10694 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010695 nberrors = ctxt->nberrors;
10696 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010697 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010698 xmlSchemaImportPtr import;
10699
Daniel Veillard4255d502002-04-16 15:50:10 +000010700 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010701 if (schema == NULL)
10702 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010703 /*
10704 * Disable build of list of items.
10705 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010706 attr = xmlSchemaGetPropNode(node, "targetNamespace");
10707 if (attr != NULL) {
10708 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
10709 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10710 /*
10711 * TODO: Should we proceed with an invalid target namespace?
10712 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010713 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
10714 } else {
10715 schema->targetNamespace = NULL;
10716 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010717 /*
10718 * Add the current ns name and location to the import table;
10719 * this is needed to have a consistent mechanism, regardless
10720 * if all schemata are constructed dynamically fired by the
10721 * instance or if the schema to be used was specified via
10722 * the API.
10723 */
10724 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10725 schema->targetNamespace);
10726 if (import == NULL) {
10727 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10728 NULL, NULL, (xmlNodePtr) ctxt->doc,
10729 "Internal error: xmlSchemaParseSchema, "
10730 "failed to add an import entry", NULL);
10731 xmlSchemaFree(schema);
10732 schema = NULL;
10733 return (NULL);
10734 }
10735 import->schemaLocation = ctxt->URL;
10736 /*
10737 * NOTE: We won't set the doc here, otherwise it will be freed
10738 * if the import struct is freed.
10739 * import->doc = ctxt->doc;
10740 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010741 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010742 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10743 } else {
10744 xmlDocPtr doc;
10745
10746 doc = node->doc;
10747
10748 if ((doc != NULL) && (doc->URL != NULL)) {
10749 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10750 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010751 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010752 } else {
10753 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10754 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010755 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010756 }
10757 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010758 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010759 if (ctxt->nberrors != 0) {
10760 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010761 xmlSchemaFree(schema);
10762 schema = NULL;
10763 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010764 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010765 if (schema != NULL)
10766 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010767 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010768#ifdef DEBUG
10769 if (schema == NULL)
10770 xmlGenericError(xmlGenericErrorContext,
10771 "xmlSchemaParse() failed\n");
10772#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010773 return (schema);
10774}
10775
10776/************************************************************************
10777 * *
10778 * Validating using Schemas *
10779 * *
10780 ************************************************************************/
10781
10782/************************************************************************
10783 * *
10784 * Reading/Writing Schemas *
10785 * *
10786 ************************************************************************/
10787
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010788#if 0 /* Will be enabled if it is clear what options are needed. */
10789/**
10790 * xmlSchemaParserCtxtSetOptions:
10791 * @ctxt: a schema parser context
10792 * @options: a combination of xmlSchemaParserOption
10793 *
10794 * Sets the options to be used during the parse.
10795 *
10796 * Returns 0 in case of success, -1 in case of an
10797 * API error.
10798 */
10799static int
10800xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10801 int options)
10802
10803{
10804 int i;
10805
10806 if (ctxt == NULL)
10807 return (-1);
10808 /*
10809 * WARNING: Change the start value if adding to the
10810 * xmlSchemaParseOption.
10811 */
10812 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10813 if (options & 1<<i) {
10814 return (-1);
10815 }
10816 }
10817 ctxt->options = options;
10818 return (0);
10819}
10820
10821/**
10822 * xmlSchemaValidCtxtGetOptions:
10823 * @ctxt: a schema parser context
10824 *
10825 * Returns the option combination of the parser context.
10826 */
10827static int
10828xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
10829
10830{
10831 if (ctxt == NULL)
10832 return (-1);
10833 else
10834 return (ctxt->options);
10835}
10836
10837 void *curItems; /* used for dynamic addition of schemata */
10838 int nbCurItems; /* used for dynamic addition of schemata */
10839 int sizeCurItems; /* used for dynamic addition of schemata */
10840
10841#endif
10842
Daniel Veillard4255d502002-04-16 15:50:10 +000010843/**
10844 * xmlSchemaNewParserCtxt:
10845 * @URL: the location of the schema
10846 *
10847 * Create an XML Schemas parse context for that file/resource expected
10848 * to contain an XML Schemas file.
10849 *
10850 * Returns the parser context or NULL in case of error
10851 */
10852xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010853xmlSchemaNewParserCtxt(const char *URL)
10854{
Daniel Veillard4255d502002-04-16 15:50:10 +000010855 xmlSchemaParserCtxtPtr ret;
10856
10857 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010858 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010859
10860 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10861 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010862 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010863 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010864 return (NULL);
10865 }
10866 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010867 ret->dict = xmlDictCreate();
10868 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010869 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010870 return (ret);
10871}
10872
10873/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010874 * xmlSchemaNewParserCtxtUseDict:
10875 * @URL: the location of the schema
10876 * @dict: the dictionary to be used
10877 *
10878 * Create an XML Schemas parse context for that file/resource expected
10879 * to contain an XML Schemas file.
10880 *
10881 * Returns the parser context or NULL in case of error
10882 */
10883static xmlSchemaParserCtxtPtr
10884xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
10885{
10886 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010887 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010888 if (URL == NULL)
10889 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010890 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010891
10892 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10893 if (ret == NULL) {
10894 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10895 NULL);
10896 return (NULL);
10897 }
10898 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10899 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010900 xmlDictReference(dict);
10901 if (URL != NULL)
10902 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010903 ret->includes = 0;
10904 return (ret);
10905}
10906
10907
10908/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010909 * xmlSchemaNewMemParserCtxt:
10910 * @buffer: a pointer to a char array containing the schemas
10911 * @size: the size of the array
10912 *
10913 * Create an XML Schemas parse context for that memory buffer expected
10914 * to contain an XML Schemas file.
10915 *
10916 * Returns the parser context or NULL in case of error
10917 */
10918xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010919xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10920{
Daniel Veillard6045c902002-10-09 21:13:59 +000010921 xmlSchemaParserCtxtPtr ret;
10922
10923 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010924 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010925
10926 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10927 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010928 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010929 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010930 return (NULL);
10931 }
10932 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10933 ret->buffer = buffer;
10934 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010935 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010936 return (ret);
10937}
10938
10939/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010940 * xmlSchemaNewDocParserCtxt:
10941 * @doc: a preparsed document tree
10942 *
10943 * Create an XML Schemas parse context for that document.
10944 * NB. The document may be modified during the parsing process.
10945 *
10946 * Returns the parser context or NULL in case of error
10947 */
10948xmlSchemaParserCtxtPtr
10949xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10950{
10951 xmlSchemaParserCtxtPtr ret;
10952
10953 if (doc == NULL)
10954 return (NULL);
10955
10956 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10957 if (ret == NULL) {
10958 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10959 NULL);
10960 return (NULL);
10961 }
10962 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10963 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010964 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010965 /* The application has responsibility for the document */
10966 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010967
10968 return (ret);
10969}
10970
10971/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010972 * xmlSchemaFreeParserCtxt:
10973 * @ctxt: the schema parser context
10974 *
10975 * Free the resources associated to the schema parser context
10976 */
10977void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010978xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10979{
Daniel Veillard4255d502002-04-16 15:50:10 +000010980 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010981 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010982 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010983 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010984 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010985 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010986 xmlFree(ctxt->assemble);
10987 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010988 if (ctxt->vctxt != NULL) {
10989 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10990 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010991 if (ctxt->localImports != NULL)
10992 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010993 if (ctxt->substGroups != NULL)
10994 xmlHashFree(ctxt->substGroups,
10995 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010996 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010997 xmlFree(ctxt);
10998}
10999
11000/************************************************************************
11001 * *
11002 * Building the content models *
11003 * *
11004 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011005
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011006
11007static void
11008xmlSchemaWalkSubstGroups(xmlSchemaParserCtxtPtr pctxt,
11009 xmlSchemaSubstGroupPtr substGroup,
11010 xmlAutomataStatePtr startState,
11011 xmlAutomataStatePtr endState)
11012{
11013 xmlSchemaElementPtr member;
11014 xmlSchemaSubstGroupPtr sg;
11015 int i;
11016
11017 for (i = 0; i < substGroup->members->nbItems; i++) {
11018 member = (xmlSchemaElementPtr) substGroup->members->items[i];
11019 if ((member->flags & XML_SCHEMAS_ELEM_ABSTRACT) == 0) {
11020 xmlAutomataNewEpsilon(pctxt->am,
11021 xmlAutomataNewTransition2(pctxt->am,
11022 startState, NULL,
11023 member->name, member->targetNamespace, member),
11024 endState);
11025 }
11026 if (member->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
11027 sg = xmlSchemaGetElementSubstitutionGroup(pctxt, member);
11028 if (sg != NULL)
11029 xmlSchemaWalkSubstGroups(pctxt, sg, startState, endState);
11030 }
11031 }
11032}
11033
11034static void
11035xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
11036 xmlSchemaParticlePtr particle,
11037 xmlSchemaSubstGroupPtr substGroup)
11038{
11039 xmlAutomataStatePtr start;
11040 xmlSchemaElementPtr elemDecl;
11041 xmlAutomataStatePtr end;
11042
11043 elemDecl = (xmlSchemaElementPtr) particle->children;
11044 /*
11045 * Wrap the substitution group with a CHOICE.
11046 */
11047 start = pctxt->state;
11048 end = xmlAutomataNewState(pctxt->am);
11049
11050 if (particle->maxOccurs == 1) {
11051 /*
11052 * NOTE that we put the declaration in, even if it's abstract,
11053 */
11054 xmlAutomataNewEpsilon(pctxt->am,
11055 xmlAutomataNewTransition2(pctxt->am,
11056 start, NULL,
11057 elemDecl->name, elemDecl->targetNamespace, elemDecl),
11058 end);
11059 xmlSchemaWalkSubstGroups(pctxt, substGroup, start, end);
11060 } else {
11061 int counter;
11062 xmlAutomataStatePtr hop;
11063 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11064 UNBOUNDED : particle->maxOccurs - 1;
11065 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
11066
11067 counter =
11068 xmlAutomataNewCounter(pctxt->am, minOccurs,
11069 maxOccurs);
11070 hop = xmlAutomataNewState(pctxt->am);
11071
11072 xmlAutomataNewEpsilon(pctxt->am,
11073 xmlAutomataNewTransition2(pctxt->am,
11074 start, NULL,
11075 elemDecl->name, elemDecl->targetNamespace, elemDecl),
11076 hop);
11077
11078 xmlSchemaWalkSubstGroups(pctxt, substGroup, start, hop);
11079
11080 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
11081 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
11082 }
11083 if (particle->minOccurs == 0)
11084 xmlAutomataNewEpsilon(pctxt->am, start, end);
11085 pctxt->state = end;
11086}
11087
11088static void
11089xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
11090 xmlSchemaParticlePtr particle)
11091{
11092 xmlSchemaSubstGroupPtr substGroup;
11093
11094 substGroup = xmlSchemaGetElementSubstitutionGroup(ctxt,
11095 (xmlSchemaElementPtr) particle->children);
11096 if (substGroup != NULL) {
11097 /*
11098 * Substitution groups.
11099 */
11100 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, substGroup);
11101 } else {
11102 xmlSchemaElementPtr elemDecl;
11103 xmlAutomataStatePtr start;
11104
11105 elemDecl = (xmlSchemaElementPtr) particle->children;
11106
11107 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
11108 return;
11109 if (particle->maxOccurs == 1) {
11110 start = ctxt->state;
11111 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11112 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11113 } else if ((particle->maxOccurs >= UNBOUNDED) && (particle->minOccurs < 2)) {
11114 /* Special case. */
11115 start = ctxt->state;
11116 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11117 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11118 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
11119 } else {
11120 int counter;
11121 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11122 UNBOUNDED : particle->maxOccurs - 1;
11123 int minOccurs = particle->minOccurs < 1 ?
11124 0 : particle->minOccurs - 1;
11125
11126 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
11127 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11128 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11129 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11130 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
11131 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
11132 NULL, counter);
11133 }
11134 if (particle->minOccurs == 0)
11135 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
11136 }
11137}
11138
Daniel Veillard4255d502002-04-16 15:50:10 +000011139/**
11140 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011141 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011142 * @particle: the particle component
11143 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011144 *
11145 * Generate the automata sequence needed for that type
11146 */
11147static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011148xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt,
11149 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011150 const xmlChar * name)
11151{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011152 if (particle == NULL) {
11153 xmlSchemaPErr(ctxt, NULL,
11154 XML_SCHEMAP_INTERNAL,
11155 "Internal error: xmlSchemaBuildAContentModel, "
11156 "particle is NULL.\n", NULL, NULL);
11157 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011158 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011159 if (particle->children == NULL) {
11160 xmlSchemaPErr(ctxt, GET_NODE(particle),
11161 XML_SCHEMAP_INTERNAL,
11162 "Internal error: xmlSchemaBuildAContentModel, "
11163 "no term on particle.\n", NULL, NULL);
11164 return;
11165 }
11166
11167 switch (particle->children->type) {
11168 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011169 xmlAutomataStatePtr start, end;
11170 xmlSchemaWildcardPtr wild;
11171 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011172
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011173 wild = (xmlSchemaWildcardPtr) particle->children;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011174
11175 start = ctxt->state;
11176 end = xmlAutomataNewState(ctxt->am);
11177
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011178 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011179 if (wild->any == 1) {
11180 /*
11181 * We need to add both transitions:
11182 *
11183 * 1. the {"*", "*"} for elements in a namespace.
11184 */
11185 ctxt->state =
11186 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011187 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011188 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11189 /*
11190 * 2. the {"*"} for elements in no namespace.
11191 */
11192 ctxt->state =
11193 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011194 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011195 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11196
11197 } else if (wild->nsSet != NULL) {
11198 ns = wild->nsSet;
11199 do {
11200 ctxt->state = start;
11201 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011202 ctxt->state, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011203 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11204 ns = ns->next;
11205 } while (ns != NULL);
11206
11207 } else if (wild->negNsSet != NULL) {
11208 xmlAutomataStatePtr deadEnd;
11209
11210 deadEnd = xmlAutomataNewState(ctxt->am);
11211 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011212 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011213 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011214 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011215 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11216 }
11217 } else {
11218 int counter;
11219 xmlAutomataStatePtr hop;
11220 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011221 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011222 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011223 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011224
11225 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11226 hop = xmlAutomataNewState(ctxt->am);
11227 if (wild->any == 1) {
11228 ctxt->state =
11229 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011230 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011231 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11232 ctxt->state =
11233 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011234 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011235 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11236 } else if (wild->nsSet != NULL) {
11237 ns = wild->nsSet;
11238 do {
11239 ctxt->state =
11240 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011241 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011242 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11243 ns = ns->next;
11244 } while (ns != NULL);
11245
11246 } else if (wild->negNsSet != NULL) {
11247 xmlAutomataStatePtr deadEnd;
11248
11249 deadEnd = xmlAutomataNewState(ctxt->am);
11250 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011251 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011252 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011253 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011254 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11255 }
11256 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
11257 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
11258 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011259 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011260 xmlAutomataNewEpsilon(ctxt->am, start, end);
11261 }
11262 ctxt->state = end;
11263 break;
11264 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011265 case XML_SCHEMA_TYPE_ELEMENT:
11266 xmlSchemaBuildContentModelForElement(ctxt, particle);
11267 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011268 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011269 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011270
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011271 /*
11272 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011273 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011274 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011275 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11276 sub = particle->children->children;
11277 while (sub != NULL) {
11278 xmlSchemaBuildAContentModel(ctxt,
11279 (xmlSchemaParticlePtr) sub, name);
11280 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011281 }
11282 } else {
11283 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011284
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011285 if (particle->maxOccurs >= UNBOUNDED) {
11286 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011287 xmlAutomataStatePtr tmp;
11288 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011289
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011290 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011291 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011292 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011293
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011294 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011295 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011296
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011297 sub = particle->children->children;
11298 while (sub != NULL) {
11299 xmlSchemaBuildAContentModel(ctxt,
11300 (xmlSchemaParticlePtr) sub, name);
11301 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011302 }
11303 tmp = ctxt->state;
11304 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11305 oldstate, counter);
11306 ctxt->state =
11307 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11308 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011309
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011310 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011311 sub = particle->children->children;
11312 while (sub != NULL) {
11313 xmlSchemaBuildAContentModel(ctxt,
11314 (xmlSchemaParticlePtr) sub, name);
11315 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011316 }
11317 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11318 oldstate);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011319 if (particle->minOccurs == 0) {
11320 xmlAutomataNewEpsilon(ctxt->am,
11321 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011322 }
11323 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011324 } else if ((particle->maxOccurs > 1)
11325 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011326 xmlAutomataStatePtr tmp;
11327 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011328
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011329 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011330 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011331 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011332
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011333 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011334 particle->minOccurs - 1,
11335 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011336
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011337 sub = particle->children->children;
11338 while (sub != NULL) {
11339 xmlSchemaBuildAContentModel(ctxt,
11340 (xmlSchemaParticlePtr) sub, name);
11341 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011342 }
11343 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011344 xmlAutomataNewCountedTrans(ctxt->am,
11345 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011346 ctxt->state =
11347 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11348 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011349 if (particle->minOccurs == 0) {
11350 xmlAutomataNewEpsilon(ctxt->am,
11351 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011352 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011353 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011354 sub = particle->children->children;
11355 while (sub != NULL) {
11356 xmlSchemaBuildAContentModel(ctxt,
11357 (xmlSchemaParticlePtr) sub, name);
11358 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011359 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011360 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011361 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11362 ctxt->state);
11363 }
11364 }
11365 }
11366 break;
11367 }
11368 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011369 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011370 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011371
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011372 start = ctxt->state;
11373 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011374
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011375 /*
11376 * iterate over the subtypes and remerge the end with an
11377 * epsilon transition
11378 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011379 if (particle->maxOccurs == 1) {
11380 sub = particle->children->children;
11381 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011382 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011383 xmlSchemaBuildAContentModel(ctxt,
11384 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011385 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011386 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011387 }
11388 } else {
11389 int counter;
11390 xmlAutomataStatePtr hop;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011391 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11392 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011393 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011394 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011395
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011396 /*
11397 * use a counter to keep track of the number of transtions
11398 * which went through the choice.
11399 */
11400 counter =
11401 xmlAutomataNewCounter(ctxt->am, minOccurs,
11402 maxOccurs);
11403 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011404
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011405 sub = particle->children->children;
11406 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011407 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011408 xmlSchemaBuildAContentModel(ctxt,
11409 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011410 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011411 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011412 }
11413 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
11414 counter);
11415 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
11416 counter);
11417 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011418 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011419 xmlAutomataNewEpsilon(ctxt->am, start, end);
11420 }
11421 ctxt->state = end;
11422 break;
11423 }
11424 case XML_SCHEMA_TYPE_ALL:{
11425 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011426 xmlSchemaParticlePtr sub;
11427 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011428 int lax;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011429
11430 sub = (xmlSchemaParticlePtr) particle->children->children;
11431 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011432 break;
11433 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011434 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011435 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011436
11437 elemDecl = (xmlSchemaElementPtr) sub->children;
11438 if (elemDecl == NULL) {
11439 xmlSchemaPErr(ctxt, NULL,
11440 XML_SCHEMAP_INTERNAL,
11441 "Internal error: xmlSchemaBuildAContentModel, "
11442 "<element> particle a NULL term.\n", NULL, NULL);
11443 return;
11444 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011445 /*
11446 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011447 * {particles} of the group must be 0 or 1; this is
11448 * already ensured during the parse of the content of
11449 * <all>.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011450 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011451 if ((sub->minOccurs == 1) &&
11452 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011453 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
11454 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011455 elemDecl->name,
11456 elemDecl->targetNamespace,
11457 1, 1, elemDecl);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011458 } else if ((sub->minOccurs == 0) &&
11459 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011460
11461 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
11462 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011463 elemDecl->name,
11464 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011465 0,
11466 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011467 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011468 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011469 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011470 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011471 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011472 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011473 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011474 break;
11475 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011476 default:
11477 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011478 "Internal error: xmlSchemaBuildAContentModel, found "
11479 "unexpected term of type %d in content model of complex "
11480 "type '%s'.\n",
11481 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011482 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011483 }
11484}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011485
Daniel Veillard4255d502002-04-16 15:50:10 +000011486/**
11487 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011488 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011489 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011490 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011491 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011492 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011493 */
11494static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011495xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011496 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011497 const xmlChar * name)
11498{
Daniel Veillard4255d502002-04-16 15:50:10 +000011499 xmlAutomataStatePtr start;
11500
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011501 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11502 (type->contModel != NULL) ||
11503 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11504 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011505 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011506
11507#ifdef DEBUG_CONTENT
11508 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011509 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011510#endif
11511
Daniel Veillard4255d502002-04-16 15:50:10 +000011512 ctxt->am = xmlNewAutomata();
11513 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011514 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011515 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011516 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011517 }
11518 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011519 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011520 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011521 type->contModel = xmlAutomataCompile(ctxt->am);
11522 if (type->contModel == NULL) {
11523 xmlSchemaPCustomErr(ctxt,
11524 XML_SCHEMAP_INTERNAL,
11525 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011526 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011527 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011528 xmlSchemaPCustomErr(ctxt,
11529 XML_SCHEMAP_NOT_DETERMINISTIC,
11530 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011531 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011532 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011533 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011534#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011535 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011536 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011537 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011538#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011539 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011540 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011541 xmlFreeAutomata(ctxt->am);
11542 ctxt->am = NULL;
11543}
11544
11545/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011546 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011547 * @elem: the schema element context
11548 * @ctxt: the schema parser context
11549 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011550 * Resolves the references of an element declaration
11551 * or particle, which has an element declaration as it's
11552 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011553 */
11554static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011555xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011556 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011557 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011558 const xmlChar * context ATTRIBUTE_UNUSED,
11559 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011560{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011561 if ((ctxt == NULL) || (elemDecl == NULL) ||
11562 ((elemDecl != NULL) && (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011563 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011564 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011565
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011566 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011567 xmlSchemaTypePtr type;
11568
11569 /* (type definition) ... otherwise the type definition ·resolved·
11570 * to by the ·actual value· of the type [attribute] ...
11571 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011572 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
11573 elemDecl->namedTypeNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011574 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011575 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011576 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011577 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
11578 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011579 XML_SCHEMA_TYPE_BASIC, "type definition");
11580 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011581 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011582 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011583 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011584 xmlSchemaElementPtr substHead;
11585
Daniel Veillardc0826a72004-08-10 14:17:33 +000011586 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011587 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
11588 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011589 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011590 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11591 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011592 if (substHead == NULL) {
11593 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011594 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011595 NULL, (xmlSchemaTypePtr) elemDecl, NULL,
11596 "substitutionGroup", elemDecl->substGroup,
11597 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011598 } else {
11599 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011600 if ((substHead->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
11601 substHead->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
11602 /*
11603 * Set the "substitution group affiliation".
11604 * NOTE that now we use the "refDecl" field for this.
11605 */
11606 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011607 /*
11608 * (type definition)...otherwise the {type definition} of the
11609 * element declaration ·resolved· to by the ·actual value· of
11610 * the substitutionGroup [attribute], if present
11611 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011612 if (elemDecl->subtypes == NULL)
11613 elemDecl->subtypes = substHead->subtypes;
11614 xmlSchemaAddElementSubstitutionMember(ctxt, substHead, elemDecl);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011615 }
11616 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011617 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11618 (elemDecl->substGroup == NULL))
11619 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011620}
11621
11622/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011623 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011624 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011625 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011626 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011627 * Checks and builds the "member type definitions" property of the union
11628 * simple type. This handles part (1), part (2) is done in
11629 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11630 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011631 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011632 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011633static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011634xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11635 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011636{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011637
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011638 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011639 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011640
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011641 /*
11642 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
Daniel Veillard01fa6152004-06-29 17:04:39 +000011643 * define the explicit members as the type definitions ·resolved·
11644 * to by the items in the ·actual value· of the memberTypes [attribute],
11645 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011646 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011647 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011648 /*
11649 * Resolve references.
11650 */
11651 link = type->memberTypes;
11652 lastLink = NULL;
11653 while (link != NULL) {
11654 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011655
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011656 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11657 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11658
11659 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11660 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11661 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
11662 NULL, type, type->node, "memberTypes",
11663 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11664 /*
11665 * Remove the member type link.
11666 */
11667 if (lastLink == NULL)
11668 type->memberTypes = link->next;
11669 else
11670 lastLink->next = link->next;
11671 newLink = link;
11672 link = link->next;
11673 xmlFree(newLink);
11674 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011675 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011676 lastLink = link;
11677 link = link->next;
11678 }
11679 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011680 /*
11681 * Add local simple types,
11682 */
11683 memberType = type->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011684 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011685 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11686 if (link == NULL) {
11687 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11688 return (-1);
11689 }
11690 link->type = memberType;
11691 link->next = NULL;
11692 if (lastLink == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011693 type->memberTypes = link;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011694 else
11695 lastLink->next = link;
11696 lastLink = link;
11697 memberType = memberType->next;
11698 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011699 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011700}
11701
Daniel Veillard4255d502002-04-16 15:50:10 +000011702/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011703 * xmlSchemaIsDerivedFromBuiltInType:
11704 * @ctxt: the schema parser context
11705 * @type: the type definition
11706 * @valType: the value type
11707 *
11708 *
11709 * Returns 1 if the type has the given value type, or
11710 * is derived from such a type.
11711 */
William M. Brack803812b2004-06-03 02:11:24 +000011712static int
Daniel Veillard3646d642004-06-02 19:19:14 +000011713xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
11714 xmlSchemaTypePtr type, int valType)
11715{
11716 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011717 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011718 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011719 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011720 return(1);
11721 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
11722 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
11723 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
11724 ((xmlSchemaAttributePtr) type)->subtypes, valType));
11725 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
11726 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
11727 if (type->baseType != NULL)
11728 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
11729 valType));
11730 } else if ((type->subtypes != NULL) &&
11731 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
11732 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11733 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
11734 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
11735 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
11736 valType));
11737 }
11738
11739 return (0);
11740}
11741
11742/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011743 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011744 * @type: the simpleType definition
11745 *
11746 * Returns the primitive type of the given type or
11747 * NULL in case of error.
11748 */
11749static xmlSchemaTypePtr
11750xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11751{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011752
Daniel Veillard01fa6152004-06-29 17:04:39 +000011753 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011754 /*
11755 * Note that anySimpleType is actually not a primitive type
11756 * but we need that here.
11757 */
11758 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11759 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011760 return (type);
11761 type = type->baseType;
11762 }
11763
11764 return (NULL);
11765}
11766
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011767#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011768/**
11769 * xmlSchemaGetBuiltInTypeAncestor:
11770 * @type: the simpleType definition
11771 *
11772 * Returns the primitive type of the given type or
11773 * NULL in case of error.
11774 */
11775static xmlSchemaTypePtr
11776xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11777{
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011778 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
11779 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))
11780 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011781 while (type != NULL) {
11782 if (type->type == XML_SCHEMA_TYPE_BASIC)
11783 return (type);
11784 type = type->baseType;
11785 }
11786
11787 return (NULL);
11788}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011789#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011790
Daniel Veillard01fa6152004-06-29 17:04:39 +000011791/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011792 * xmlSchemaBuildAttributeUsesOwned:
11793 * @ctxt: the schema parser context
11794 * @type: the complex type definition
11795 * @cur: the attribute declaration list
11796 * @lastUse: the top of the attribute use list
11797 *
11798 * Builds the attribute uses list on the given complex type.
11799 * This one is supposed to be called by
11800 * xmlSchemaBuildAttributeValidation only.
11801 */
11802static int
11803xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
11804 xmlSchemaAttributePtr cur,
11805 xmlSchemaAttributeLinkPtr *uses,
11806 xmlSchemaAttributeLinkPtr *lastUse)
11807{
11808 xmlSchemaAttributeLinkPtr tmp;
11809 while (cur != NULL) {
11810 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
11811 /*
11812 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11813 * to by the ·actual value·s of the ref [attribute] of the
11814 * <attributeGroup> [children], if any."
11815 */
11816 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11817 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
11818 lastUse) == -1) {
11819 return (-1);
11820 }
11821 } else {
11822 /* W3C: "1 The set of attribute uses corresponding to the
11823 * <attribute> [children], if any."
11824 */
11825 tmp = (xmlSchemaAttributeLinkPtr)
11826 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11827 if (tmp == NULL) {
11828 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11829 return (-1);
11830 }
11831 tmp->attr = cur;
11832 tmp->next = NULL;
11833 if (*uses == NULL)
11834 *uses = tmp;
11835 else
11836 (*lastUse)->next = tmp;
11837 *lastUse = tmp;
11838 }
11839 cur = cur->next;
11840 }
11841 return (0);
11842}
11843
Daniel Veillard50355f02004-06-08 17:52:16 +000011844/**
11845 * xmlSchemaCloneWildcardNsConstraints:
11846 * @ctxt: the schema parser context
11847 * @dest: the destination wildcard
11848 * @source: the source wildcard
11849 *
11850 * Clones the namespace constraints of source
11851 * and assignes them to dest.
11852 * Returns -1 on internal error, 0 otherwise.
11853 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011854static int
11855xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11856 xmlSchemaWildcardPtr *dest,
11857 xmlSchemaWildcardPtr source)
11858{
11859 xmlSchemaWildcardNsPtr cur, tmp, last;
11860
11861 if ((source == NULL) || (*dest == NULL))
11862 return(-1);
11863 (*dest)->any = source->any;
11864 cur = source->nsSet;
11865 last = NULL;
11866 while (cur != NULL) {
11867 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11868 if (tmp == NULL)
11869 return(-1);
11870 tmp->value = cur->value;
11871 if (last == NULL)
11872 (*dest)->nsSet = tmp;
11873 else
11874 last->next = tmp;
11875 last = tmp;
11876 cur = cur->next;
11877 }
11878 if ((*dest)->negNsSet != NULL)
11879 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
11880 if (source->negNsSet != NULL) {
11881 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11882 if ((*dest)->negNsSet == NULL)
11883 return(-1);
11884 (*dest)->negNsSet->value = source->negNsSet->value;
11885 } else
11886 (*dest)->negNsSet = NULL;
11887 return(0);
11888}
11889
Daniel Veillard50355f02004-06-08 17:52:16 +000011890/**
11891 * xmlSchemaUnionWildcards:
11892 * @ctxt: the schema parser context
11893 * @completeWild: the first wildcard
11894 * @curWild: the second wildcard
11895 *
11896 * Unions the namespace constraints of the given wildcards.
11897 * @completeWild will hold the resulting union.
11898 * Returns a positive error code on failure, -1 in case of an
11899 * internal error, 0 otherwise.
11900 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011901static int
11902xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
11903 xmlSchemaWildcardPtr completeWild,
11904 xmlSchemaWildcardPtr curWild)
11905{
11906 xmlSchemaWildcardNsPtr cur, curB, tmp;
11907
11908 /*
11909 * 1 If O1 and O2 are the same value, then that value must be the
11910 * value.
11911 */
11912 if ((completeWild->any == curWild->any) &&
11913 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11914 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
11915
11916 if ((completeWild->negNsSet == NULL) ||
11917 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
11918
11919 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011920 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011921
11922 /*
11923 * Check equality of sets.
11924 */
11925 cur = completeWild->nsSet;
11926 while (cur != NULL) {
11927 found = 0;
11928 curB = curWild->nsSet;
11929 while (curB != NULL) {
11930 if (cur->value == curB->value) {
11931 found = 1;
11932 break;
11933 }
11934 curB = curB->next;
11935 }
11936 if (!found)
11937 break;
11938 cur = cur->next;
11939 }
11940 if (found)
11941 return(0);
11942 } else
11943 return(0);
11944 }
11945 }
11946 /*
11947 * 2 If either O1 or O2 is any, then any must be the value
11948 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011949 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011950 if (completeWild->any == 0) {
11951 completeWild->any = 1;
11952 if (completeWild->nsSet != NULL) {
11953 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11954 completeWild->nsSet = NULL;
11955 }
11956 if (completeWild->negNsSet != NULL) {
11957 xmlFree(completeWild->negNsSet);
11958 completeWild->negNsSet = NULL;
11959 }
11960 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011961 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011962 }
11963 /*
11964 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
11965 * then the union of those sets must be the value.
11966 */
11967 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
11968 int found;
11969 xmlSchemaWildcardNsPtr start;
11970
11971 cur = curWild->nsSet;
11972 start = completeWild->nsSet;
11973 while (cur != NULL) {
11974 found = 0;
11975 curB = start;
11976 while (curB != NULL) {
11977 if (cur->value == curB->value) {
11978 found = 1;
11979 break;
11980 }
11981 curB = curB->next;
11982 }
11983 if (!found) {
11984 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11985 if (tmp == NULL)
11986 return (-1);
11987 tmp->value = cur->value;
11988 tmp->next = completeWild->nsSet;
11989 completeWild->nsSet = tmp;
11990 }
11991 cur = cur->next;
11992 }
11993
11994 return(0);
11995 }
11996 /*
11997 * 4 If the two are negations of different values (namespace names
11998 * or ·absent·), then a pair of not and ·absent· must be the value.
11999 */
12000 if ((completeWild->negNsSet != NULL) &&
12001 (curWild->negNsSet != NULL) &&
12002 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
12003 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000012004
12005 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012006 }
12007 /*
12008 * 5.
12009 */
12010 if (((completeWild->negNsSet != NULL) &&
12011 (completeWild->negNsSet->value != NULL) &&
12012 (curWild->nsSet != NULL)) ||
12013 ((curWild->negNsSet != NULL) &&
12014 (curWild->negNsSet->value != NULL) &&
12015 (completeWild->nsSet != NULL))) {
12016
12017 int nsFound, absentFound = 0;
12018
12019 if (completeWild->nsSet != NULL) {
12020 cur = completeWild->nsSet;
12021 curB = curWild->negNsSet;
12022 } else {
12023 cur = curWild->nsSet;
12024 curB = completeWild->negNsSet;
12025 }
12026 nsFound = 0;
12027 while (cur != NULL) {
12028 if (cur->value == NULL)
12029 absentFound = 1;
12030 else if (cur->value == curB->value)
12031 nsFound = 1;
12032 if (nsFound && absentFound)
12033 break;
12034 cur = cur->next;
12035 }
12036
12037 if (nsFound && absentFound) {
12038 /*
12039 * 5.1 If the set S includes both the negated namespace
12040 * name and ·absent·, then any must be the value.
12041 */
12042 completeWild->any = 1;
12043 if (completeWild->nsSet != NULL) {
12044 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12045 completeWild->nsSet = NULL;
12046 }
12047 if (completeWild->negNsSet != NULL) {
12048 xmlFree(completeWild->negNsSet);
12049 completeWild->negNsSet = NULL;
12050 }
12051 } else if (nsFound && (!absentFound)) {
12052 /*
12053 * 5.2 If the set S includes the negated namespace name
12054 * but not ·absent·, then a pair of not and ·absent· must
12055 * be the value.
12056 */
12057 if (completeWild->nsSet != NULL) {
12058 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12059 completeWild->nsSet = NULL;
12060 }
12061 if (completeWild->negNsSet == NULL) {
12062 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12063 if (completeWild->negNsSet == NULL)
12064 return (-1);
12065 }
12066 completeWild->negNsSet->value = NULL;
12067 } else if ((!nsFound) && absentFound) {
12068 /*
12069 * 5.3 If the set S includes ·absent· but not the negated
12070 * namespace name, then the union is not expressible.
12071 */
12072 xmlSchemaPErr(ctxt, completeWild->node,
12073 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012074 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000012075 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012076 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012077 } else if ((!nsFound) && (!absentFound)) {
12078 /*
12079 * 5.4 If the set S does not include either the negated namespace
12080 * name or ·absent·, then whichever of O1 or O2 is a pair of not
12081 * and a namespace name must be the value.
12082 */
12083 if (completeWild->negNsSet == NULL) {
12084 if (completeWild->nsSet != NULL) {
12085 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12086 completeWild->nsSet = NULL;
12087 }
12088 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12089 if (completeWild->negNsSet == NULL)
12090 return (-1);
12091 completeWild->negNsSet->value = curWild->negNsSet->value;
12092 }
12093 }
12094 return (0);
12095 }
12096 /*
12097 * 6.
12098 */
12099 if (((completeWild->negNsSet != NULL) &&
12100 (completeWild->negNsSet->value == NULL) &&
12101 (curWild->nsSet != NULL)) ||
12102 ((curWild->negNsSet != NULL) &&
12103 (curWild->negNsSet->value == NULL) &&
12104 (completeWild->nsSet != NULL))) {
12105
12106 if (completeWild->nsSet != NULL) {
12107 cur = completeWild->nsSet;
12108 } else {
12109 cur = curWild->nsSet;
12110 }
12111 while (cur != NULL) {
12112 if (cur->value == NULL) {
12113 /*
12114 * 6.1 If the set S includes ·absent·, then any must be the
12115 * value.
12116 */
12117 completeWild->any = 1;
12118 if (completeWild->nsSet != NULL) {
12119 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12120 completeWild->nsSet = NULL;
12121 }
12122 if (completeWild->negNsSet != NULL) {
12123 xmlFree(completeWild->negNsSet);
12124 completeWild->negNsSet = NULL;
12125 }
12126 return (0);
12127 }
12128 cur = cur->next;
12129 }
12130 if (completeWild->negNsSet == NULL) {
12131 /*
12132 * 6.2 If the set S does not include ·absent·, then a pair of not
12133 * and ·absent· must be the value.
12134 */
12135 if (completeWild->nsSet != NULL) {
12136 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12137 completeWild->nsSet = NULL;
12138 }
12139 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12140 if (completeWild->negNsSet == NULL)
12141 return (-1);
12142 completeWild->negNsSet->value = NULL;
12143 }
12144 return (0);
12145 }
12146 return (0);
12147
12148}
12149
Daniel Veillard50355f02004-06-08 17:52:16 +000012150/**
12151 * xmlSchemaIntersectWildcards:
12152 * @ctxt: the schema parser context
12153 * @completeWild: the first wildcard
12154 * @curWild: the second wildcard
12155 *
12156 * Intersects the namespace constraints of the given wildcards.
12157 * @completeWild will hold the resulting intersection.
12158 * Returns a positive error code on failure, -1 in case of an
12159 * internal error, 0 otherwise.
12160 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012161static int
12162xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
12163 xmlSchemaWildcardPtr completeWild,
12164 xmlSchemaWildcardPtr curWild)
12165{
William M. Brack803812b2004-06-03 02:11:24 +000012166 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012167
12168 /*
12169 * 1 If O1 and O2 are the same value, then that value must be the
12170 * value.
12171 */
12172 if ((completeWild->any == curWild->any) &&
12173 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12174 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
12175
12176 if ((completeWild->negNsSet == NULL) ||
12177 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
12178
12179 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012180 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012181
12182 /*
12183 * Check equality of sets.
12184 */
12185 cur = completeWild->nsSet;
12186 while (cur != NULL) {
12187 found = 0;
12188 curB = curWild->nsSet;
12189 while (curB != NULL) {
12190 if (cur->value == curB->value) {
12191 found = 1;
12192 break;
12193 }
12194 curB = curB->next;
12195 }
12196 if (!found)
12197 break;
12198 cur = cur->next;
12199 }
12200 if (found)
12201 return(0);
12202 } else
12203 return(0);
12204 }
12205 }
12206 /*
12207 * 2 If either O1 or O2 is any, then the other must be the value.
12208 */
12209 if ((completeWild->any != curWild->any) && (completeWild->any)) {
12210 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12211 return(-1);
12212 return(0);
12213 }
12214 /*
12215 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12216 * name or ·absent·) and the other is a set of (namespace names or
12217 * ·absent·), then that set, minus the negated value if it was in
12218 * the set, minus ·absent· if it was in the set, must be the value.
12219 */
12220 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12221 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12222 const xmlChar *neg;
12223
12224 if (completeWild->nsSet == NULL) {
12225 neg = completeWild->negNsSet->value;
12226 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12227 return(-1);
12228 } else
12229 neg = curWild->negNsSet->value;
12230 /*
12231 * Remove absent and negated.
12232 */
12233 prev = NULL;
12234 cur = completeWild->nsSet;
12235 while (cur != NULL) {
12236 if (cur->value == NULL) {
12237 if (prev == NULL)
12238 completeWild->nsSet = cur->next;
12239 else
12240 prev->next = cur->next;
12241 xmlFree(cur);
12242 break;
12243 }
12244 prev = cur;
12245 cur = cur->next;
12246 }
12247 if (neg != NULL) {
12248 prev = NULL;
12249 cur = completeWild->nsSet;
12250 while (cur != NULL) {
12251 if (cur->value == neg) {
12252 if (prev == NULL)
12253 completeWild->nsSet = cur->next;
12254 else
12255 prev->next = cur->next;
12256 xmlFree(cur);
12257 break;
12258 }
12259 prev = cur;
12260 cur = cur->next;
12261 }
12262 }
12263
12264 return(0);
12265 }
12266 /*
12267 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
12268 * then the intersection of those sets must be the value.
12269 */
12270 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
12271 int found;
12272
12273 cur = completeWild->nsSet;
12274 prev = NULL;
12275 while (cur != NULL) {
12276 found = 0;
12277 curB = curWild->nsSet;
12278 while (curB != NULL) {
12279 if (cur->value == curB->value) {
12280 found = 1;
12281 break;
12282 }
12283 curB = curB->next;
12284 }
12285 if (!found) {
12286 if (prev == NULL)
12287 completeWild->nsSet = cur->next;
12288 else
12289 prev->next = cur->next;
12290 tmp = cur->next;
12291 xmlFree(cur);
12292 cur = tmp;
12293 continue;
12294 }
12295 prev = cur;
12296 cur = cur->next;
12297 }
12298
12299 return(0);
12300 }
12301 /* 5 If the two are negations of different namespace names,
12302 * then the intersection is not expressible
12303 */
12304 if ((completeWild->negNsSet != NULL) &&
12305 (curWild->negNsSet != NULL) &&
12306 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
12307 (completeWild->negNsSet->value != NULL) &&
12308 (curWild->negNsSet->value != NULL)) {
12309
12310 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012311 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000012312 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012313 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012314 }
12315 /*
12316 * 6 If the one is a negation of a namespace name and the other
12317 * is a negation of ·absent·, then the one which is the negation
12318 * of a namespace name must be the value.
12319 */
12320 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12321 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
12322 (completeWild->negNsSet->value == NULL)) {
12323 completeWild->negNsSet->value = curWild->negNsSet->value;
12324 }
12325 return(0);
12326}
12327
Daniel Veillard50355f02004-06-08 17:52:16 +000012328/**
12329 * xmlSchemaIsWildcardNsConstraintSubset:
12330 * @ctxt: the schema parser context
12331 * @wildA: the first wildcard
12332 * @wildB: the second wildcard
12333 *
12334 * Returns 1 if the namespace constraint of @wildA is an intensional
12335 * subset of @wildB, 0 otherwise.
12336 */
12337static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000012338xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
12339 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000012340{
Daniel Veillard3646d642004-06-02 19:19:14 +000012341
Daniel Veillard50355f02004-06-08 17:52:16 +000012342 /*
12343 * Schema Component Constraint: Wildcard Subset
12344 */
12345 /*
12346 * 1 super must be any.
12347 */
12348 if (wildB->any)
12349 return (1);
12350 /*
12351 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12352 * 2.2 super must be a pair of not and the same value.
12353 */
12354 if ((wildA->negNsSet != NULL) &&
12355 (wildB->negNsSet != NULL) &&
12356 (wildA->negNsSet->value == wildA->negNsSet->value))
12357 return (1);
12358 /*
12359 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
12360 */
12361 if (wildA->nsSet != NULL) {
12362 /*
12363 * 3.2.1 super must be the same set or a superset thereof.
12364 */
12365 if (wildB->nsSet != NULL) {
12366 xmlSchemaWildcardNsPtr cur, curB;
12367 int found = 0;
12368
12369 cur = wildA->nsSet;
12370 while (cur != NULL) {
12371 found = 0;
12372 curB = wildB->nsSet;
12373 while (curB != NULL) {
12374 if (cur->value == curB->value) {
12375 found = 1;
12376 break;
12377 }
12378 curB = curB->next;
12379 }
12380 if (!found)
12381 return (0);
12382 cur = cur->next;
12383 }
12384 if (found)
12385 return (1);
12386 } else if (wildB->negNsSet != NULL) {
12387 xmlSchemaWildcardNsPtr cur;
12388 /*
12389 * 3.2.2 super must be a pair of not and a namespace name or
12390 * ·absent· and that value must not be in sub's set.
12391 */
12392 cur = wildA->nsSet;
12393 while (cur != NULL) {
12394 if (cur->value == wildB->negNsSet->value)
12395 return (0);
12396 cur = cur->next;
12397 }
12398 return (1);
12399 }
12400 }
12401 return (0);
12402}
12403
12404/**
12405 * xmlSchemaBuildCompleteAttributeWildcard:
12406 * @ctxt: the schema parser context
12407 * @attrs: the attribute list
12408 * @completeWild: the resulting complete wildcard
12409 *
12410 * Returns -1 in case of an internal error, 0 otherwise.
12411 */
12412static int
12413xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
12414 xmlSchemaAttributePtr attrs,
12415 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000012416{
12417 while (attrs != NULL) {
12418 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12419 xmlSchemaAttributeGroupPtr group;
12420
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012421 group = (xmlSchemaAttributeGroupPtr) attrs;
12422 /*
12423 * Handle attribute group references.
12424 */
12425 if (group->ref != NULL) {
12426 if (group->refItem == NULL) {
12427 /*
12428 * TODO: Should we raise a warning here?
12429 */
12430 /*
12431 * The referenced attribute group definition could not
12432 * be resolved beforehand, so skip.
12433 */
12434 attrs = attrs->next;
12435 continue;
12436 } else
12437 group = group->refItem;
12438 }
12439 /*
12440 * For every attribute group definition, an intersected wildcard
12441 * will be created (assumed that a wildcard exists on the
12442 * particular attr. gr. def. or on any contained attr. gr. def
12443 * at all).
12444 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12445 * that the intersection will be performed only once.
12446 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012447 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12448 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012449 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
12450 group->attributes, &group->attributeWildcard) == -1)
12451 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012452 }
12453 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
12454 }
12455 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012456 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012457 /*
12458 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012459 *
12460 * Although the complete wildcard might not correspond to any
12461 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012462 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012463 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12464 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12465 group->attributeWildcard->node);
Daniel Veillard50355f02004-06-08 17:52:16 +000012466 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
12467 completeWild, group->attributeWildcard) == -1)
12468 return (-1);
12469 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012470 (*completeWild)->node = group->attributeWildcard->node;
12471 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012472 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012473 }
12474 }
12475 attrs = attrs->next;
12476 }
12477
Daniel Veillard50355f02004-06-08 17:52:16 +000012478 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012479}
12480
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012481static int
12482xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12483 int *fixed,
12484 const xmlChar **value,
12485 xmlSchemaValPtr *val)
12486{
12487 *fixed = 0;
12488 *value = NULL;
12489 if (val != 0)
12490 *val = NULL;
12491
12492 if (item->defValue == NULL)
12493 item = item->refDecl;
12494
12495 if (item == NULL)
12496 return (0);
12497
12498 if (item->defValue != NULL) {
12499 *value = item->defValue;
12500 if (val != 0)
12501 *val = item->defVal;
12502 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12503 *fixed = 1;
12504 return (1);
12505 }
12506 return (0);
12507}
Daniel Veillard3646d642004-06-02 19:19:14 +000012508/**
12509 * xmlSchemaMatchesWildcardNs:
12510 * @wild: the wildcard
12511 * @ns: the namespace
12512 *
12513 *
12514 * Returns 1 if the given namespace matches the wildcard,
12515 * 0 otherwise.
12516 */
12517static int
12518xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
12519{
12520 if (wild == NULL)
12521 return(0);
12522
12523 if (wild->any)
12524 return(1);
12525 else if (wild->nsSet != NULL) {
12526 xmlSchemaWildcardNsPtr cur;
12527
12528 cur = wild->nsSet;
12529 while (cur != NULL) {
12530 if (xmlStrEqual(cur->value, ns))
12531 return(1);
12532 cur = cur->next;
12533 }
12534 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
12535 (!xmlStrEqual(wild->negNsSet->value, ns)))
12536 return(1);
12537
12538 return(0);
12539}
12540
12541/**
12542 * xmlSchemaBuildAttributeValidation:
12543 * @ctxt: the schema parser context
12544 * @type: the complex type definition
12545 *
12546 *
12547 * Builds the wildcard and the attribute uses on the given complex type.
12548 * Returns -1 if an internal error occurs, 0 otherwise.
12549 */
12550static int
12551xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
12552{
12553 xmlSchemaTypePtr baseType = NULL;
12554 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000012555 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012556 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012557 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000012558 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012559 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012560 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012561
Daniel Veillard01fa6152004-06-29 17:04:39 +000012562 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012563 /*
12564 * Complex Type Definition with complex content Schema Component.
12565 *
12566 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012567 * TODO: Add checks for absent referenced attribute declarations and
12568 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012569 */
12570 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012571 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012572 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000012573 "attribute uses already builded.\n",
12574 NULL, NULL);
12575 return (-1);
12576 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012577 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012578 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012579 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012580 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012581 type->name, NULL);
12582 return (-1);
12583 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012584 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012585 if (baseType == anyType)
12586 baseIsAnyType = 1;
12587 /*
12588 * Inherit the attribute uses of the base type.
12589 */
12590 /*
12591 * NOTE: It is allowed to "extend" the anyType complex type.
12592 */
12593 if (!baseIsAnyType) {
12594 if (baseType != NULL) {
12595 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
12596 tmp = (xmlSchemaAttributeLinkPtr)
12597 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12598 if (tmp == NULL) {
12599 xmlSchemaPErrMemory(ctxt,
12600 "building attribute uses of complexType", NULL);
12601 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012602 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012603 tmp->attr = cur->attr;
12604 tmp->next = NULL;
12605 if (type->attributeUses == NULL) {
12606 type->attributeUses = tmp;
12607 } else
12608 lastBaseUse->next = tmp;
12609 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012610 }
12611 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012612 }
12613 if ((type->subtypes != NULL) &&
12614 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
12615 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012616 /*
12617 * type --> (<simpleContent>|<complexContent>)
12618 * --> (<restriction>|<extension>) --> attributes
12619 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012620 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012621 } else {
12622 /* Short hand form of the complexType. */
12623 attrs = type->attributes;
12624 }
12625 /*
12626 * Handle attribute wildcards.
12627 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012628 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
12629 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012630 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012631 * NOTE: During the parse time, the wildcard is created on the complexType
12632 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012633 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012634 if (err == -1) {
12635 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
12636 "Internal error: xmlSchemaBuildAttributeValidation: "
12637 "failed to build an intersected attribute wildcard.\n",
12638 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012639 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012640 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012641
12642 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12643 ((baseIsAnyType) ||
12644 ((baseType != NULL) &&
12645 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12646 (baseType->attributeWildcard != NULL)))) {
12647 if (type->attributeWildcard != NULL) {
12648 /*
12649 * Union the complete wildcard with the base wildcard.
12650 */
12651 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
12652 baseType->attributeWildcard) == -1)
12653 return (-1);
12654 } else {
12655 /*
12656 * Just inherit the wildcard.
12657 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012658 /*
12659 * NOTE: This is the only case where an attribute
12660 * wildcard is shared.
12661 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012662 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012663 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012664 }
12665
12666 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12667 if (type->attributeWildcard != NULL) {
12668 /*
12669 * Derivation Valid (Restriction, Complex)
12670 * 4.1 The {base type definition} must also have one.
12671 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012672 if (baseType->attributeWildcard == NULL) {
12673 xmlSchemaPCustomErr(ctxt,
12674 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
12675 NULL, type, NULL,
12676 "The type has an attribute wildcard, "
12677 "but the base type %s does not have one",
12678 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12679 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012680 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012681 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012682 type->attributeWildcard, baseType->attributeWildcard) == 0) {
12683 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012684 xmlSchemaPCustomErr(ctxt,
12685 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
12686 NULL, type, NULL,
12687 "The attribute wildcard is not a valid "
12688 "subset of the wildcard in the base type %s",
12689 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12690 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012691 return (1);
12692 }
12693 /* 4.3 Unless the {base type definition} is the ·ur-type
12694 * definition·, the complex type definition's {attribute
12695 * wildcard}'s {process contents} must be identical to or
12696 * stronger than the {base type definition}'s {attribute
12697 * wildcard}'s {process contents}, where strict is stronger
12698 * than lax is stronger than skip.
12699 */
12700 if ((type->baseType != anyType) &&
12701 (type->attributeWildcard->processContents <
12702 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012703 xmlSchemaPCustomErr(ctxt,
12704 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
12705 NULL, type, NULL,
12706 "The 'process contents' of the attribute wildcard is weaker than "
12707 "the one in the base type %s",
12708 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12709 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012710 return (1);
12711 }
12712 }
12713 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12714 /*
12715 * Derivation Valid (Extension)
12716 * At this point the type and the base have both, either
12717 * no wildcard or a wildcard.
12718 */
12719 if ((baseType->attributeWildcard != NULL) &&
12720 (baseType->attributeWildcard != type->attributeWildcard)) {
12721 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012722 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012723 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012724 xmlSchemaPCustomErr(ctxt,
12725 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
12726 NULL, type, NULL,
12727 "The attribute wildcard is not a valid "
12728 "superset of the one in the base type %s",
12729 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12730 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012731 return (1);
12732 }
12733 }
12734 }
12735
Daniel Veillard3646d642004-06-02 19:19:14 +000012736 /*
12737 * Gather attribute uses defined by this type.
12738 */
12739 if (attrs != NULL) {
12740 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
12741 &uses, &lastUse) == -1) {
12742 return (-1);
12743 }
12744 }
12745 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
12746 * "Two distinct attribute declarations in the {attribute uses} must
12747 * not have identical {name}s and {target namespace}s."
12748 *
12749 * For "extension" this is done further down.
12750 */
12751 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
12752 cur = uses;
12753 while (cur != NULL) {
12754 tmp = cur->next;
12755 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012756 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12757 xmlSchemaGetAttrName(tmp->attr))) &&
12758 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
12759 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12760
12761 xmlSchemaPAttrUseErr(ctxt,
12762 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12763 NULL, type, NULL, cur->attr,
12764 "Duplicate attribute use %s specified",
12765 xmlSchemaFormatNsUriLocal(&str,
12766 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12767 xmlSchemaGetAttrName(tmp->attr))
12768 );
12769 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012770 break;
12771 }
12772 tmp = tmp->next;
12773 }
12774 cur = cur->next;
12775 }
12776 }
12777 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12778 /*
12779 * Derive by restriction.
12780 */
12781 if (baseIsAnyType) {
12782 type->attributeUses = uses;
12783 } else {
12784 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012785 const xmlChar *bEffValue;
12786 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012787
12788 cur = uses;
12789 while (cur != NULL) {
12790 found = 0;
12791 base = type->attributeUses;
12792 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012793 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12794 xmlSchemaGetAttrName(base->attr)) &&
12795 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
12796 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012797
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012798 found = 1;
12799
Daniel Veillard3646d642004-06-02 19:19:14 +000012800 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12801 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12802 /*
12803 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000012804 */
12805 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012806 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012807 NULL, type, NULL, cur->attr,
12808 "The 'optional' use is inconsistent with a matching "
12809 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012810 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12811 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12812 /*
12813 * derivation-ok-restriction 3
12814 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012815 xmlSchemaPCustomErr(ctxt,
12816 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12817 NULL, type, NULL,
12818 "A matching attribute use for the 'required' "
12819 "attribute use %s of the base type is missing",
12820 xmlSchemaFormatNsUriLocal(&str,
12821 xmlSchemaGetAttrTargetNsURI(base->attr),
12822 xmlSchemaGetAttrName(base->attr)));
12823 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012824 } else {
12825 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012826 * 2.1.3 [Definition:] Let the effective value
12827 * constraint of an attribute use be its {value
12828 * constraint}, if present, otherwise its {attribute
12829 * declaration}'s {value constraint} .
12830 */
12831 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
12832 &bEffValue, 0);
12833 /*
12834 * 2.1.3 ... one of the following must be true
12835 *
12836 * 2.1.3.1 B's ·effective value constraint· is
12837 * ·absent· or default.
12838 */
12839 if ((bEffValue != NULL) &&
12840 (effFixed == 1)) {
12841 const xmlChar *rEffValue = NULL;
12842
12843 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
12844 &rEffValue, 0);
12845 /*
12846 * 2.1.3.2 R's ·effective value constraint· is
12847 * fixed with the same string as B's.
12848 */
12849 if ((effFixed == 0) ||
12850 (! xmlStrEqual(rEffValue, bEffValue))) {
12851 xmlSchemaPAttrUseErr(ctxt,
12852 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12853 NULL, type, NULL, cur->attr,
12854 "The effective value constraint of the "
12855 "attribute use is inconsistent with "
12856 "its correspondent of the base type",
12857 NULL);
12858 }
12859 }
12860 /*
12861 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
12862 */
12863 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012864 * Override the attribute use.
12865 */
12866 base->attr = cur->attr;
12867 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012868
Daniel Veillard3646d642004-06-02 19:19:14 +000012869 break;
12870 }
12871 base = base->next;
12872 }
12873
12874 if (!found) {
12875 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12876 /*
12877 * derivation-ok-restriction 2.2
12878 */
12879 if ((type->attributeWildcard != NULL) &&
12880 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
12881 cur->attr->targetNamespace))
12882 found = 1;
12883
12884 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012885 xmlSchemaPAttrUseErr(ctxt,
12886 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12887 NULL, type, NULL, cur->attr,
12888 "Neither a matching attribute use, "
12889 "nor a matching wildcard in the base type does exist",
12890 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012891 } else {
12892 /*
12893 * Add the attribute use.
12894 *
12895 * Note that this may lead to funny derivation error reports, if
12896 * multiple equal attribute uses exist; but this is not
12897 * allowed anyway, and it will be reported beforehand.
12898 */
12899 tmp = cur;
12900 if (prev != NULL)
12901 prev->next = cur->next;
12902 else
12903 uses = cur->next;
12904 cur = cur->next;
12905 if (type->attributeUses == NULL) {
12906 type->attributeUses = tmp;
12907 } else
12908 lastBaseUse->next = tmp;
12909 lastBaseUse = tmp;
12910
12911 continue;
12912 }
12913 }
12914 }
12915 prev = cur;
12916 cur = cur->next;
12917 }
12918 if (uses != NULL)
12919 xmlSchemaFreeAttributeUseList(uses);
12920 }
12921 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12922 /*
12923 * The spec allows only appending, and not other kinds of extensions.
12924 *
12925 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
12926 */
12927 if (uses != NULL) {
12928 if (type->attributeUses == NULL) {
12929 type->attributeUses = uses;
12930 } else
12931 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012932 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012933 } else {
12934 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000012935 * Derive implicitely from the ur-type.
12936 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012937 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012938 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012939 /*
12940 * 3.4.6 -> Complex Type Definition Properties Correct
12941 */
12942 if (type->attributeUses != NULL) {
12943 cur = type->attributeUses;
12944 prev = NULL;
12945 while (cur != NULL) {
12946 /*
12947 * 4. Two distinct attribute declarations in the {attribute uses} must
12948 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012949 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012950 * Note that this was already done for "restriction" and types derived from
12951 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012952 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012953 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12954 tmp = cur->next;
12955 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012956 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12957 xmlSchemaGetAttrName(tmp->attr))) &&
12958 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
12959 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012960
Daniel Veillardc0826a72004-08-10 14:17:33 +000012961 xmlSchemaPAttrUseErr(ctxt,
12962 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12963 NULL, type, NULL, tmp->attr,
12964 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012965 break;
12966 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012967 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012968 }
12969 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012970 /*
12971 * 5. Two distinct attribute declarations in the {attribute uses} must
12972 * not have {type definition}s which are or are derived from ID.
12973 */
12974 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012975 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012976 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012977 xmlSchemaPAttrUseErr(ctxt,
12978 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12979 NULL, type, NULL, cur->attr,
12980 "There must not exist more than one attribute use, "
12981 "declared of type 'ID' or derived from it",
12982 NULL);
12983 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000012984 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012985 id = cur;
12986 }
12987 /*
12988 * Remove "prohibited" attribute uses. The reason this is done at this late
12989 * stage is to be able to catch dublicate attribute uses. So we had to keep
12990 * prohibited uses in the list as well.
12991 */
12992 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12993 tmp = cur;
12994 if (prev == NULL)
12995 type->attributeUses = cur->next;
12996 else
12997 prev->next = cur->next;
12998 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012999 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000013000 } else {
13001 prev = cur;
13002 cur = cur->next;
13003 }
13004 }
13005 }
13006 /*
13007 * TODO: This check should be removed if we are 100% sure of
13008 * the base type attribute uses already being built.
13009 */
13010 if ((baseType != NULL) && (!baseIsAnyType) &&
13011 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013012 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013013 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013014 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013015 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000013016 baseType->name, NULL);
13017 }
13018 return (0);
13019}
13020
13021/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013022 * xmlSchemaTypeFinalContains:
13023 * @schema: the schema
13024 * @type: the type definition
13025 * @final: the final
13026 *
13027 * Evaluates if a type definition contains the given "final".
13028 * This does take "finalDefault" into account as well.
13029 *
13030 * Returns 1 if the type does containt the given "final",
13031 * 0 otherwise.
13032 */
13033static int
13034xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
13035{
13036 int tfinal = final, tflags = type->flags;
13037
13038 if (type == NULL)
13039 return (0);
13040 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
13041 switch (final) {
13042 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
13043 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
13044 break;
13045 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
13046 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
13047 break;
13048 case XML_SCHEMAS_TYPE_FINAL_LIST:
13049 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
13050 break;
13051 case XML_SCHEMAS_TYPE_FINAL_UNION:
13052 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
13053 break;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013054 default:
13055 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013056 }
13057 tflags = schema->flags;
13058 }
13059 if (tflags & tfinal)
13060 return (1);
13061 else
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013062 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013063}
13064
13065/**
13066 * xmlSchemaGetUnionSimpleTypeMemberTypes:
13067 * @type: the Union Simple Type
13068 *
13069 * Returns a list of member types of @type if existing,
13070 * returns NULL otherwise.
13071 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013072static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000013073xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
13074{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013075 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013076 if (type->memberTypes != NULL)
13077 return (type->memberTypes);
13078 else
13079 type = type->baseType;
13080 }
13081 return (NULL);
13082}
13083
13084/**
13085 * xmlSchemaGetListSimpleTypeItemType:
13086 * @type: the simple type definition
13087 *
13088 * Returns the item type definition of the list simple type.
13089 */
13090static xmlSchemaTypePtr
13091xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
13092{
13093 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
13094 return (NULL);
13095 /*
13096 * Note: In libxml2, the built-in types do not reflect
13097 * the datatype hierarchy (yet?) - we have to treat them
13098 * in a special way.
13099 */
13100 if (type->type == XML_SCHEMA_TYPE_BASIC)
13101 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013102 return (type->subtypes);
13103}
13104
13105
13106static int
13107xmlSchemaGetParticleTotalRangeMin(xmlSchemaTreeItemPtr particle)
13108{
13109 if ((particle->children == NULL) ||
13110 ( ((xmlSchemaParticlePtr) particle)->minOccurs == 0))
13111 return (0);
13112 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13113 int min = 0, cur;
13114 xmlSchemaTreeItemPtr part = particle->children->children;
13115
13116 if (part == NULL)
13117 return (0);
13118 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13119 (part->children->type == XML_SCHEMA_TYPE_ANY))
13120 min = ((xmlSchemaParticlePtr) part)->minOccurs;
13121 else
13122 min = xmlSchemaGetParticleTotalRangeMin(part);
13123 if (min == 0)
13124 return (0);
13125 part = part->next;
13126 while (part != NULL) {
13127 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13128 (part->children->type == XML_SCHEMA_TYPE_ANY))
13129 cur = ((xmlSchemaParticlePtr) part)->minOccurs;
13130 else
13131 cur = xmlSchemaGetParticleTotalRangeMin(part);
13132 if (cur == 0)
13133 return (0);
13134 if (min > cur)
13135 min = cur;
13136 part = part->next;
13137 }
13138 return (((xmlSchemaParticlePtr) particle)->minOccurs * min);
13139 } else {
13140 /* <all> and <sequence> */
13141 int sum = 0;
13142 xmlSchemaTreeItemPtr part = particle->children->children;
13143
13144 if (part == NULL)
13145 return (0);
13146 do {
13147 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13148 (part->children->type == XML_SCHEMA_TYPE_ANY))
13149 sum += ((xmlSchemaParticlePtr) part)->minOccurs;
13150 else
13151 sum += xmlSchemaGetParticleTotalRangeMin(part);
13152 part = part->next;
13153 } while (part != NULL);
13154 return (((xmlSchemaParticlePtr) particle)->minOccurs * sum);
13155 }
13156}
13157
13158
13159static int
13160xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13161{
13162 if ((particle == NULL) || (particle->minOccurs == 0) ||
13163 (particle->children == NULL))
13164 return (1);
13165
13166 if (IS_MODEL_GROUP(particle->children)) {
13167 if (xmlSchemaGetParticleTotalRangeMin(
13168 (xmlSchemaTreeItemPtr) particle) == 0)
13169 return (1);
13170 }
13171 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013172}
13173
13174/**
13175 * xmlSchemaCheckCOSSTDerivedOK:
13176 * @type: the derived simple type definition
13177 * @baseType: the base type definition
13178 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013179 * Schema Component Constraint:
13180 * Type Derivation OK (Simple) (cos-st-derived-OK)
13181 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000013182 * Checks wheter @type can be validly
13183 * derived from @baseType.
13184 *
13185 * Returns 0 on success, an positive error code otherwise.
13186 */
13187static int
13188xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
13189 xmlSchemaTypePtr type,
13190 xmlSchemaTypePtr baseType,
13191 int subset)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013192{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013193 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013194 * 1 They are the same type definition.
13195 * TODO: The identy check might have to be more complex than this.
13196 */
13197 if (type == baseType)
13198 return (0);
13199 /*
13200 * 2.1 restriction is not in the subset, or in the {final}
13201 * of its own {base type definition};
13202 */
13203 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
13204 (xmlSchemaTypeFinalContains(schema,
13205 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13206 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
13207 }
13208 /* 2.2 */
13209 if (type->baseType == baseType) {
13210 /*
13211 * 2.2.1 D's ·base type definition· is B.
13212 */
13213 return (0);
13214 }
13215 /*
13216 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13217 * and is validly derived from B given the subset, as defined by this
13218 * constraint.
13219 */
13220 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
13221 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
13222 return (0);
13223 }
13224 /*
13225 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
13226 * definition·.
13227 */
13228 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
13229 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
13230 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
13231 return (0);
13232 }
13233 /*
13234 * 2.2.4 B's {variety} is union and D is validly derived from a type
13235 * definition in B's {member type definitions} given the subset, as
13236 * defined by this constraint.
13237 *
13238 * NOTE: This seems not to involve built-in types, since there is no
13239 * built-in Union Simple Type.
13240 */
13241 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13242 xmlSchemaTypeLinkPtr cur;
13243
13244 cur = baseType->memberTypes;
13245 while (cur != NULL) {
13246 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
13247 cur->type, subset) == 0)
13248 return (0);
13249 cur = cur->next;
13250 }
13251 }
13252
13253 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13254}
13255
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013256/**
13257 * xmlSchemaCheckTypeDefCircularInternal:
13258 * @pctxt: the schema parser context
13259 * @ctxtType: the type definition
13260 * @ancestor: an ancestor of @ctxtType
13261 *
13262 * Checks st-props-correct (2) + ct-props-correct (3).
13263 * Circular type definitions are not allowed.
13264 *
13265 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13266 * circular, 0 otherwise.
13267 */
13268static int
13269xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13270 xmlSchemaTypePtr ctxtType,
13271 xmlSchemaTypePtr ancestor)
13272{
13273 int ret;
13274
13275 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13276 return (0);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013277
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013278 if (ctxtType == ancestor) {
13279 xmlSchemaPCustomErr(pctxt,
13280 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13281 NULL, ctxtType, GET_NODE(ctxtType),
13282 "The definition is circular", NULL);
13283 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13284 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013285 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13286 /*
13287 * Avoid inifinite recursion on circular types not yet checked.
13288 */
13289 return (0);
13290 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013291 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13292 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13293 ancestor->baseType);
13294 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13295 return (ret);
13296}
13297
13298/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013299 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013300 * @item: the complex/simple type definition
13301 * @ctxt: the parser context
13302 * @name: the name
13303 *
13304 * Checks for circular type definitions.
13305 */
13306static void
13307xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
13308 xmlSchemaParserCtxtPtr ctxt,
13309 const xmlChar * name ATTRIBUTE_UNUSED)
13310{
13311 if ((item == NULL) ||
13312 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13313 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13314 return;
13315 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13316
13317}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013318
13319/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013320 * xmlSchemaResolveTypeDefs:
13321 * @item: the complex/simple type definition
13322 * @ctxt: the parser context
13323 * @name: the name
13324 *
13325 * Checks for circular type definitions.
13326 */
13327static void
13328xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
13329 xmlSchemaParserCtxtPtr ctxt,
13330 const xmlChar * name ATTRIBUTE_UNUSED)
13331{
13332 if (typeDef == NULL)
13333 return;
13334
13335 if (IS_SIMPLE_TYPE(typeDef)) {
13336 if (typeDef->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13337 /*
13338 * Resolve the memberTypes.
13339 */
13340 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13341 return;
13342 } else if (typeDef->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13343 /*
13344 * Resolve the itemType.
13345 */
13346 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13347 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13348 typeDef->ref, typeDef->refNs);
13349 if ((typeDef->subtypes == NULL) ||
13350 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13351 typeDef->subtypes = NULL;
13352 xmlSchemaPResCompAttrErr(ctxt,
13353 XML_SCHEMAP_SRC_RESOLVE,
13354 NULL, typeDef, typeDef->node,
13355 "itemType", typeDef->ref, typeDef->refNs,
13356 XML_SCHEMA_TYPE_SIMPLE, NULL);
13357 }
13358 }
13359 return;
13360 }
13361 }
13362 /*
13363 * Resolve the base type.
13364 */
13365 if (typeDef->baseType == NULL) {
13366 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13367 typeDef->base, typeDef->baseNs);
13368 if (typeDef->baseType == NULL) {
13369 xmlSchemaPResCompAttrErr(ctxt,
13370 XML_SCHEMAP_SRC_RESOLVE,
13371 NULL, typeDef, typeDef->node,
13372 "base", typeDef->base, typeDef->baseNs,
13373 XML_SCHEMA_TYPE_SIMPLE, NULL);
13374 return;
13375 }
13376 }
13377}
13378
13379
13380
13381/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013382 * xmlSchemaCheckSTPropsCorrect:
13383 * @ctxt: the schema parser context
13384 * @type: the simple type definition
13385 *
13386 * Checks st-props-correct.
13387 *
13388 * Returns 0 if the properties are correct,
13389 * if not, a positive error code and -1 on internal
13390 * errors.
13391 */
13392static int
13393xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
13394 xmlSchemaTypePtr type)
13395{
13396 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13397 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013398 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013399
Daniel Veillardc0826a72004-08-10 14:17:33 +000013400 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013401 /*
13402 * Schema Component Constraint: Simple Type Definition Properties Correct
13403 *
13404 * NOTE: This is somehow redundant, since we actually built a simple type
13405 * to have all the needed information; this acts as an self test.
13406 */
13407 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13408 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013409 /* Base type: If the datatype has been ·derived· by ·restriction·
13410 * then the Simple Type Definition component from which it is ·derived·,
13411 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
13412 */
13413 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013414 /*
13415 * TODO: Think about: "modulo the impact of Missing
13416 * Sub-components (§5.3)."
13417 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013418 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013419 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013420 NULL, type, NULL,
13421 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013422 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013423
Daniel Veillard01fa6152004-06-29 17:04:39 +000013424 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013425 if (! IS_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,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013428 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013429 "The base type '%s' is not a simple type",
13430 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013431 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013432 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13433 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013434 if ((baseType->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
13435 ((type->flags &
13436 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13437 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
13438 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013439 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013440 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013441 NULL, type, NULL,
13442 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013443 "the simple ur-type definition as base type, not '%s'",
13444 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013445 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013446 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13447 }
13448 /*
13449 * Variety: One of {atomic, list, union}.
13450 */
13451 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13452 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
13453 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013454 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013455 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013456 NULL, type, NULL,
13457 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013458 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13459 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013460 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013461
13462 /*
13463 * 3 The {final} of the {base type definition} must not contain restriction.
13464 */
13465 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
13466 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13467 xmlSchemaPCustomErr(ctxt,
13468 XML_SCHEMAP_ST_PROPS_CORRECT_3,
13469 NULL, type, NULL,
13470 "The 'final' of its base type '%s' must not contain "
13471 "'restriction'",
13472 xmlSchemaGetComponentQName(&str, baseType));
13473 FREE_AND_NULL(str)
13474 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
13475 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013476
13477 /*
13478 * 2 All simple type definitions must be derived ultimately from the ·simple
13479 * ur-type definition (so· circular definitions are disallowed). That is, it
13480 * must be possible to reach a built-in primitive datatype or the ·simple
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013481 * ur-type definition· by repeatedly following the {base type definition}.
13482 *
13483 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013484 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013485 return (0);
13486}
13487
13488/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013489 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013490 * @ctxt: the schema parser context
13491 * @type: the simple type definition
13492 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013493 * Schema Component Constraint:
13494 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13495
13496 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013497 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013498 *
13499 * Returns -1 on internal errors, 0 if the type is validly derived,
13500 * a positive error code otherwise.
13501 */
13502static int
13503xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013504 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013505{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013506 xmlChar *str = NULL;
13507
Daniel Veillard01fa6152004-06-29 17:04:39 +000013508 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
13509 xmlSchemaPErr(ctxt, type->node,
13510 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013511 "xmlSchemaCheckCOSSTRestricts: The given "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013512 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013513 type->name, NULL);
13514 return (-1);
13515 }
13516
13517 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
13518 xmlSchemaTypePtr primitive;
13519 /*
13520 * 1.1 The {base type definition} must be an atomic simple
13521 * type definition or a built-in primitive datatype.
13522 */
13523 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013524 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013525 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013526 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013527 "The base type '%s' is not an atomic simple type",
13528 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013529 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013530 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13531 }
13532 /* 1.2 The {final} of the {base type definition} must not contain
13533 * restriction.
13534 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013535 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013536 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13537 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013538 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013539 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013540 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013541 "The final of its base type '%s' must not contain 'restriction'",
13542 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013543 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013544 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13545 }
13546
13547 /*
13548 * 1.3.1 DF must be an allowed constraining facet for the {primitive
13549 * type definition}, as specified in the appropriate subsection of 3.2
13550 * Primitive datatypes.
13551 */
13552 if (type->facets != NULL) {
13553 xmlSchemaFacetPtr facet;
13554 int ok = 1;
13555
13556 primitive = xmlSchemaGetPrimitiveType(type);
13557 if (primitive == NULL) {
13558 xmlSchemaPErr(ctxt, type->node,
13559 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013560 "xmlSchemaCheckCOSSTRestricts: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013561 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013562 type->name, NULL);
13563 return (-1);
13564 }
13565 facet = type->facets;
13566 do {
13567 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013568 ok = 0;
13569 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013570 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013571 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013572 }
13573 facet = facet->next;
13574 } while (facet != NULL);
13575 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013576 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013577 }
13578 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013579 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13580 * of the {base type definition} (call this BF),then the DF's {value}
13581 * must be a valid restriction of BF's {value} as defined in
13582 * [XML Schemas: Datatypes]."
13583 *
13584 * NOTE (1.3.2) Facet derivation constraints are currently handled in
13585 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013586 */
13587 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13588 xmlSchemaTypePtr itemType = NULL;
13589
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013590 itemType = type->subtypes;
13591 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013592 xmlSchemaPErr(ctxt, type->node,
13593 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013594 "Internal error: xmlSchemaCheckCOSSTRestricts: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013595 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013596 type->name, NULL);
13597 return (-1);
13598 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013599 if (IS_NOT_TYPEFIXED(itemType))
13600 xmlSchemaTypeFixup(itemType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013601 /*
13602 * 2.1 The {item type definition} must have a {variety} of atomic or
13603 * union (in which case all the {member type definitions}
13604 * must be atomic).
13605 */
13606 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13607 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013608 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013609 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013610 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013611 "The item type '%s' does not have a variety of atomic or union",
13612 xmlSchemaGetComponentQName(&str, itemType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013613 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013614 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13615 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13616 xmlSchemaTypeLinkPtr member;
13617
13618 member = itemType->memberTypes;
13619 while (member != NULL) {
13620 if ((member->type->flags &
13621 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013622 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013623 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013624 NULL, type, NULL,
13625 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013626 "member type '%s' of this item type is not atomic",
13627 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013628 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013629 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13630 }
13631 member = member->next;
13632 }
13633 }
13634
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013635 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013636 xmlSchemaFacetPtr facet;
13637 /*
13638 * This is the case if we have: <simpleType><list ..
13639 */
13640 /*
13641 * 2.3.1
13642 * 2.3.1.1 The {final} of the {item type definition} must not
13643 * contain list.
13644 */
13645 if (xmlSchemaTypeFinalContains(ctxt->schema,
13646 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013647 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013648 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013649 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013650 "The final of its item type '%s' must not contain 'list'",
13651 xmlSchemaGetComponentQName(&str, itemType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013652 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013653 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13654 }
13655 /*
13656 * 2.3.1.2 The {facets} must only contain the whiteSpace
13657 * facet component.
13658 */
13659 if (type->facets != NULL) {
13660 facet = type->facets;
13661 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013662 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13663 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013664 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013665 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013666 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13667 }
13668 facet = facet->next;
13669 } while (facet != NULL);
13670 }
13671 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013672 * MABY TODO: (Hmm, not really) Datatypes states:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013673 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13674 * whose ·lexical space· allows space (such as string or anyURI)or
13675 * a ·union· datatype any of whose {member type definitions}'s
13676 * ·lexical space· allows space.
13677 */
13678 } else {
13679 /*
13680 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013681 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013682 */
13683 /*
13684 * 2.3.2
13685 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13686 */
13687 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013688 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013689 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013690 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013691 "The base type '%s' must be a list type",
13692 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013693 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013694 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13695 }
13696 /*
13697 * 2.3.2.2 The {final} of the {base type definition} must not
13698 * contain restriction.
13699 */
13700 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13701 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013702 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013703 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013704 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013705 "The 'final' of the base type '%s' must not contain 'restriction'",
13706 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013707 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013708 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13709 }
13710 /*
13711 * 2.3.2.3 The {item type definition} must be validly derived
13712 * from the {base type definition}'s {item type definition} given
13713 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13714 */
13715 {
13716 xmlSchemaTypePtr baseItemType;
13717
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013718 baseItemType = type->baseType->subtypes;
13719 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013720 xmlSchemaPErr(ctxt, type->node,
13721 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013722 "Internal error: xmlSchemaCheckCOSSTRestricts, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013723 "List simple type '%s': Failed to "
13724 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013725 type->name, type->baseType->name);
13726 return (-1);
13727 }
13728 if ((itemType != baseItemType) &&
13729 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
13730 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013731 xmlChar *strBIT = NULL, *strBT = NULL;
13732 xmlSchemaPCustomErrExt(ctxt,
13733 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
13734 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013735 "The item type '%s' is not validly derived from the "
13736 "item type '%s' of the base type '%s'",
13737 xmlSchemaGetComponentQName(&str, itemType),
13738 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13739 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013740
13741 FREE_AND_NULL(str)
13742 FREE_AND_NULL(strBIT)
13743 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013744 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13745 }
13746 }
13747
13748 if (type->facets != NULL) {
13749 xmlSchemaFacetPtr facet;
13750 int ok = 1;
13751 /*
13752 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
13753 * and enumeration facet components are allowed among the {facets}.
13754 */
13755 facet = type->facets;
13756 do {
13757 switch (facet->type) {
13758 case XML_SCHEMA_FACET_LENGTH:
13759 case XML_SCHEMA_FACET_MINLENGTH:
13760 case XML_SCHEMA_FACET_MAXLENGTH:
13761 case XML_SCHEMA_FACET_WHITESPACE:
13762 /*
13763 * TODO: 2.5.1.2 List datatypes
13764 * The value of ·whiteSpace· is fixed to the value collapse.
13765 */
13766 case XML_SCHEMA_FACET_PATTERN:
13767 case XML_SCHEMA_FACET_ENUMERATION:
13768 break;
13769 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013770 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013771 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013772 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013773 /*
13774 * We could return, but it's nicer to report all
13775 * invalid facets.
13776 */
13777 ok = 0;
13778 }
13779 }
13780 facet = facet->next;
13781 } while (facet != NULL);
13782 if (ok == 0)
13783 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13784 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013785 * SPEC (2.3.2.5) (same as 1.3.2)
13786 *
13787 * NOTE (2.3.2.5) This is currently done in
13788 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013789 */
13790 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013791 }
13792 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13793 /*
13794 * 3.1 The {member type definitions} must all have {variety} of
13795 * atomic or list.
13796 */
13797 xmlSchemaTypeLinkPtr member;
13798
13799 member = type->memberTypes;
13800 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013801 if (IS_NOT_TYPEFIXED(member->type))
13802 xmlSchemaTypeFixup(member->type, ctxt, NULL);
13803
Daniel Veillard01fa6152004-06-29 17:04:39 +000013804 if (((member->type->flags &
13805 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13806 ((member->type->flags &
13807 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013808 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013809 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013810 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013811 "The member type '%s' is neither an atomic, nor a list type",
13812 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013813 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013814 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13815 }
13816 member = member->next;
13817 }
13818 /*
13819 * 3.3.1 If the {base type definition} is the ·simple ur-type
13820 * definition·
13821 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013822 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013823 /*
13824 * 3.3.1.1 All of the {member type definitions} must have a
13825 * {final} which does not contain union.
13826 */
13827 member = type->memberTypes;
13828 while (member != NULL) {
13829 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
13830 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013831 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013832 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013833 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013834 "The 'final' of member type '%s' contains 'union'",
13835 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013836 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013837 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13838 }
13839 member = member->next;
13840 }
13841 /*
13842 * 3.3.1.2 The {facets} must be empty.
13843 */
13844 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013845 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013846 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013847 NULL, type, NULL,
13848 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013849 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13850 }
13851 } else {
13852 /*
13853 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013854 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013855 */
13856 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013857 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013858 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013859 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013860 "The base type '%s' is not a union type",
13861 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013862 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013863 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13864 }
13865 /*
13866 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13867 */
13868 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13869 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013870 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013871 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013872 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013873 "The 'final' of its base type '%s' must not contain 'restriction'",
13874 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013875 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013876 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13877 }
13878 /*
13879 * 3.3.2.3 The {member type definitions}, in order, must be validly
13880 * derived from the corresponding type definitions in the {base
13881 * type definition}'s {member type definitions} given the empty set,
13882 * as defined in Type Derivation OK (Simple) (§3.14.6).
13883 */
13884 {
13885 xmlSchemaTypeLinkPtr baseMember;
13886
13887 /*
13888 * OPTIMIZE: if the type is restricting, it has no local defined
13889 * member types and inherits the member types of the base type;
13890 * thus a check for equality can be skipped.
13891 */
13892 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013893 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000013894 * union simple type can have other member types as the member
13895 * types of it's base type. This check seems not necessary with
13896 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013897 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013898 */
13899 if (type->memberTypes != NULL) {
13900 member = type->memberTypes;
13901 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
13902 if ((member == NULL) && (baseMember != NULL)) {
13903 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013904 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013905 "Internal error: xmlSchemaCheckCOSSTRestricts, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013906 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013907 "of member types in the base type\n",
13908 type->name, NULL);
13909 }
13910 while (member != NULL) {
13911 if (baseMember == NULL) {
13912 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013913 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013914 "Internal error: "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013915 "xmlSchemaCheckCOSSTRestricts "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013916 "(3.3.2.3), union simple type '%s', unequal number "
13917 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013918 type->name, NULL);
13919 }
13920 if ((member->type != baseMember->type) &&
13921 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
13922 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013923 xmlChar *strBMT = NULL, *strBT = NULL;
13924
13925 xmlSchemaPCustomErrExt(ctxt,
13926 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13927 NULL, type, NULL,
13928 "The member type %s is not validly derived from its "
13929 "corresponding member type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013930 xmlSchemaGetComponentQName(&str, member->type),
13931 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13932 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013933 FREE_AND_NULL(str)
13934 FREE_AND_NULL(strBMT)
13935 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013936 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
13937 }
13938 member = member->next;
13939 baseMember = baseMember->next;
13940 }
13941 }
13942 }
13943 /*
13944 * 3.3.2.4 Only pattern and enumeration facet components are
13945 * allowed among the {facets}.
13946 */
13947 if (type->facets != NULL) {
13948 xmlSchemaFacetPtr facet;
13949 int ok = 1;
13950
13951 facet = type->facets;
13952 do {
13953 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13954 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013955 xmlSchemaPIllegalFacetListUnionErr(ctxt,
13956 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
13957 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013958 ok = 0;
13959 }
13960 facet = facet->next;
13961 } while (facet != NULL);
13962 if (ok == 0)
13963 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
13964
13965 }
13966 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013967 * SPEC (3.3.2.5) (same as 1.3.2)
13968 *
13969 * NOTE (3.3.2.5) This is currently done in
13970 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013971 */
13972 }
13973 }
13974
13975 return (0);
13976}
13977
13978/**
13979 * xmlSchemaCheckSRCSimpleType:
13980 * @ctxt: the schema parser context
13981 * @type: the simple type definition
13982 *
13983 * Checks crc-simple-type constraints.
13984 *
13985 * Returns 0 if the constraints are satisfied,
13986 * if not a positive error code and -1 on internal
13987 * errors.
13988 */
13989static int
13990xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
13991 xmlSchemaTypePtr type)
13992{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013993 /*
13994 * src-simple-type.1 The corresponding simple type definition, if any,
13995 * must satisfy the conditions set out in Constraints on Simple Type
13996 * Definition Schema Components (§3.14.6).
13997 */
13998 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
13999 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
14000 /*
14001 * TODO: Removed this, since it got annoying to get an
14002 * extra error report, if anything failed until now.
14003 * Enable this if needed.
14004 */
14005 /*
14006 xmlSchemaPErr(ctxt, type->node,
14007 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014008 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000014009 "on simple type definitions.\n",
14010 type->name, NULL);
14011 */
14012 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
14013 }
14014
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014015 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014016 /*
14017 * src-simple-type.2 If the <restriction> alternative is chosen,
14018 * either it must have a base [attribute] or a <simpleType> among its
14019 * [children], but not both.
14020 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014021 /*
14022 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014023 * NOTE: This is checked in the parse function of <restriction>.
William M. Brack2f2a6632004-08-20 23:09:47 +000014024 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014025 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014026 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
14027 * an itemType [attribute] or a <simpleType> among its [children],
14028 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014029 *
14030 * REMOVED: This is checked in the parse function of <list>.
14031 */
14032 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014033 xmlSchemaTypeLinkPtr member;
14034 xmlSchemaTypePtr ancestor, anySimpleType;
14035
14036 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14037
14038 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
14039 * the <union> alternative is chosen, there must not be any entries
14040 * in the memberTypes [attribute] at any depth which resolve to the
14041 * component corresponding to the <simpleType>.
14042 */
14043 member = type->memberTypes;
14044 while (member != NULL) {
14045 ancestor = member->type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014046 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
14047 if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014048 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014049 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014050 NULL, type, NULL,
14051 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014052 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014053 }
14054 if (IS_NOT_TYPEFIXED(ancestor))
14055 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
14056 if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014057 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014058 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000014059 * type as item type, which in turn has a list ST as member
14060 * type, we will assume this here as well, since this check
14061 * was not yet performed.
14062 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014063 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014064
Daniel Veillard01fa6152004-06-29 17:04:39 +000014065 ancestor = ancestor->baseType;
14066 }
14067 member = member->next;
14068 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014069 }
14070
14071 return (0);
14072}
14073
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014074#if 0 /* Not yet used code for ST schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000014075static int
14076xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
14077 const xmlChar * value,
14078 xmlSchemaTypePtr type,
14079 int fireErrors)
14080{
14081 int ret;
14082 /*
14083 * 3.14.4 Simple Type Definition Validation Rules
14084 * Validation Rule: String Valid
14085 */
14086 /*
14087 * 1 It is schema-valid with respect to that definition as defined
14088 * by Datatype Valid in [XML Schemas: Datatypes].
14089 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014090 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
14091 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000014092 return (ret);
14093 /*
14094 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
14095 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
14096 * the string must be a ·declared entity name·.
14097 */
14098 /*
14099 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
14100 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
14101 * then every whitespace-delimited substring of the string must be a ·declared
14102 * entity name·.
14103 */
14104 /*
14105 * 2.3 otherwise no further condition applies.
14106 */
14107
14108 return (0);
14109}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014110#endif
14111
William M. Brack2f2a6632004-08-20 23:09:47 +000014112
14113static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014114xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
14115{
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000014116 if (vctxt->pctxt == NULL) {
14117 if (vctxt->schema != NULL)
14118 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
14119 else
14120 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014121 if (vctxt->pctxt == NULL) {
14122 xmlSchemaVErr(vctxt, NULL,
14123 XML_SCHEMAV_INTERNAL,
14124 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
14125 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000014126 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014127 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014128 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014129 /* TODO: Pass user data. */
14130 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
14131 }
14132 return (0);
14133}
14134
14135static int
14136xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
14137{
14138 if (ctxt->vctxt == NULL) {
14139 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
14140 if (ctxt->vctxt == NULL) {
14141 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014142 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014143 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
14144 "failed to create a temp. validation context.\n",
14145 NULL, NULL);
14146 return (-1);
14147 }
14148 /* TODO: Pass user data. */
14149 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
14150 }
14151 return (0);
14152}
14153
14154/**
14155 * xmlSchemaCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014156 * @pctxt: the schema parser context
14157 * @vctxt: the temporary schema validation context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014158 * @type: the simple type definition
14159 * @value: the default value
14160 * @node: an optional node (the holder of the value)
14161 *
14162 * Checks the "cos-valid-default" constraints.
14163 *
14164 * Returns 0 if the constraints are satisfied,
14165 * if not, a positive error code and -1 on internal
14166 * errors.
14167 */
14168static int
14169xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14170 xmlSchemaValidCtxtPtr vctxt,
14171 xmlSchemaTypePtr type,
14172 const xmlChar *value,
14173 xmlNodePtr node)
14174{
14175 int ret = 0;
14176
14177 /*
14178 * cos-valid-default:
14179 * Schema Component Constraint: Element Default Valid (Immediate)
14180 * For a string to be a valid default with respect to a type
14181 * definition the appropriate case among the following must be true:
14182 */
14183 /*
14184 * NOTE: This has to work without a given node (the holder of the
14185 * value), since it should work on the component, i.e. an underlying
14186 * DOM must not be mandatory.
14187 */
14188 if ((pctxt == NULL) || (vctxt == NULL)) {
14189 xmlSchemaPErr(pctxt, node,
14190 XML_SCHEMAP_INTERNAL,
14191 "Internal error: xmlSchemaCheckCOSValidDefault, "
14192 "bad arguments: the parser and/or validation context is "
14193 "missing.\n",
14194 NULL, NULL);
14195 return (-1);
14196 }
14197 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014198 /*
14199 * Complex type.
14200 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014201 * SPEC (2.1) "its {content type} must be a simple type definition
14202 * or mixed."
14203 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
14204 * type}'s particle must be ·emptiable· as defined by
14205 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014206 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014207 if ((! HAS_SIMPLE_CONTENT(type)) &&
14208 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14209 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014210 xmlSchemaPSimpleTypeErr(pctxt,
14211 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
14212 NULL, NULL, node,
14213 type, NULL, NULL,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014214 "For a string to be a valid default, the type definition "
14215 "must be a simple type or a complex type with mixed content "
14216 "and a particle emptiable",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014217 NULL, NULL);
14218 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14219 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014220 }
14221 /*
14222 * 1 If the type definition is a simple type definition, then the string
14223 * must be ·valid· with respect to that definition as defined by String
14224 * Valid (§3.14.4).
14225 *
14226 * AND
14227 *
14228 * 2.2.1 If the {content type} is a simple type definition, then the
14229 * string must be ·valid· with respect to that simple type definition
14230 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014231 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014232 vctxt->node = node;
14233 vctxt->cur = NULL;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014234 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014235 if (IS_SIMPLE_TYPE(type))
14236 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value,
14237 1, 1, 1, 0);
14238 else if (HAS_SIMPLE_CONTENT(type))
14239 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type->contentTypeDef,
14240 value, 1, 1, 1, 0);
14241 else
14242 return (ret);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014243 if (ret != 0) {
14244 pctxt->err = vctxt->err;
14245 pctxt->nberrors++;
14246 }
14247
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014248 if (ret < 0) {
14249 xmlSchemaPErr(pctxt, node,
14250 /* NOTNICE: error code: This function will be used during
14251 * schema construction and xsi:type validation.
14252 */
14253 XML_SCHEMAP_INTERNAL,
14254 "Internal error: xmlSchemaCheckCOSValidDefault, "
14255 "while validating a value constaint value.\n",
14256 NULL, NULL);
14257
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014258 }
14259
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014260 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014261}
14262
14263/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014264 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014265 * @ctxt: the schema parser context
14266 * @type: the complex type definition
14267 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014268 *.(4.6) Constraints on Complex Type Definition Schema Components
14269 * Schema Component Constraint:
14270 * Complex Type Definition Properties Correct (ct-props-correct)
14271 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014272 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014273 * Returns 0 if the constraints are satisfied, a positive
14274 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014275 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014276static int
14277xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14278 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014279{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014280 /*
14281 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14282 *
14283 * SPEC (1) "The values of the properties of a complex type definition must
14284 * be as described in the property tableau in The Complex Type Definition
14285 * Schema Component (§3.4.1), modulo the impact of Missing
14286 * Sub-components (§5.3)."
14287 */
14288 if ((type->baseType != NULL) &&
14289 (IS_SIMPLE_TYPE(type->baseType)) &&
14290 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14291 /*
14292 * SPEC (2) "If the {base type definition} is a simple type definition,
14293 * the {derivation method} must be extension."
14294 */
14295 xmlSchemaPCustomErr(pctxt,
14296 XML_SCHEMAP_SRC_CT_1,
14297 NULL, type, NULL,
14298 "If the base type is a simple type, the derivation method must be "
14299 "'extension'", NULL);
14300 return (XML_SCHEMAP_SRC_CT_1);
14301 }
14302 /*
14303 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14304 * definition·. That is, it must be possible to reach the ·ur-type
14305 * definition by repeatedly following the {base type definition}."
14306 *
14307 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14308 *
14309 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
14310 * must not have identical {name}s and {target namespace}s."
14311 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14312 * must not have {type definition}s which are or are derived from ID."
14313 *
14314 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14315 */
14316 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014317}
14318
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014319static int
14320xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14321 xmlSchemaTypePtr typeB)
14322{
14323 /*
14324 * TODO: This should implement component-identity
14325 * in the future.
14326 */
14327 if ((typeA == NULL) || (typeB == NULL))
14328 return (0);
14329 return (typeA == typeB);
14330}
14331
14332/**
14333 * xmlSchemaCheckCOSCTExtends:
14334 * @ctxt: the schema parser context
14335 * @derivedType: the to-be derived complex type definition
14336 * @baseType: the base complex type definition
14337 * @subset: the given subset
14338 *
14339 * Schema Component Constraint:
14340 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14341 *
14342 * STATUS: completed
14343 *
14344 * Returns 0 if the constraints are satisfied, or 1
14345 * if not.
14346 */
14347static int
14348xmlSchemaCheckCOSCTDerivedOK(xmlSchemaPtr schema,
14349 xmlSchemaTypePtr type,
14350 xmlSchemaTypePtr baseType,
14351 int set)
14352{
14353 int equal = xmlSchemaAreEqualTypes(type, baseType);
14354 /* TODO: Error codes. */
14355 /*
14356 * SPEC "For a complex type definition (call it D, for derived)
14357 * to be validly derived from a type definition (call this
14358 * B, for base) given a subset of {extension, restriction}
14359 * all of the following must be true:"
14360 */
14361 if (! equal) {
14362 /*
14363 * SPEC (1) "If B and D are not the same type definition, then the
14364 * {derivation method} of D must not be in the subset."
14365 */
14366 if (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
14367 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
14368 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
14369 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014370 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014371 } else {
14372 /*
14373 * SPEC (2.1) "B and D must be the same type definition."
14374 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014375 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014376 }
14377 /*
14378 * SPEC (2.2) "B must be D's {base type definition}."
14379 */
14380 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014381 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014382 /*
14383 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14384 * definition·."
14385 */
14386 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014387 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014388
14389 if (IS_COMPLEX_TYPE(type->baseType)) {
14390 /*
14391 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14392 * must be validly derived from B given the subset as defined by this
14393 * constraint."
14394 */
14395 return (xmlSchemaCheckCOSCTDerivedOK(schema, type->baseType,
14396 baseType, set));
14397 } else {
14398 /*
14399 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14400 * must be validly derived from B given the subset as defined in Type
14401 * Derivation OK (Simple) (§3.14.6).
14402 */
14403 return (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType,
14404 set));
14405 }
14406}
14407
14408/**
14409 * xmlSchemaCheckCOSDerivedOK:
14410 * @type: the derived simple type definition
14411 * @baseType: the base type definition
14412 *
14413 * Calls:
14414 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
14415 *
14416 * Checks wheter @type can be validly derived from @baseType.
14417 *
14418 * Returns 0 on success, an positive error code otherwise.
14419 */
14420static int
14421xmlSchemaCheckCOSDerivedOK(xmlSchemaPtr schema,
14422 xmlSchemaTypePtr type,
14423 xmlSchemaTypePtr baseType,
14424 int set)
14425{
14426 if (IS_SIMPLE_TYPE(type))
14427 return (xmlSchemaCheckCOSSTDerivedOK(schema, type, baseType, set));
14428 else
14429 return (xmlSchemaCheckCOSCTDerivedOK(schema, type, baseType, set));
14430}
14431
William M. Brack2f2a6632004-08-20 23:09:47 +000014432/**
14433 * xmlSchemaCheckCOSCTExtends:
14434 * @ctxt: the schema parser context
14435 * @type: the complex type definition
14436 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014437 * (3.4.6) Constraints on Complex Type Definition Schema Components
14438 * Schema Component Constraint:
14439 * Derivation Valid (Extension) (cos-ct-extends)
14440 *
14441 * STATUS:
14442 * missing:
14443 * (1.5)
14444 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014445 *
14446 * Returns 0 if the constraints are satisfied, a positive
14447 * error code if not and -1 if an internal error occured.
14448 */
14449static int
14450xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14451 xmlSchemaTypePtr type)
14452{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014453 xmlSchemaTypePtr base = type->baseType;
14454 /*
14455 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14456 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014457 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014458 /*
14459 * SPEC (1) "If the {base type definition} is a complex type definition,
14460 * then all of the following must be true:"
14461 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014462 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14463 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014464 * SPEC (1.1) "The {final} of the {base type definition} must not
14465 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014466 */
14467 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14468 xmlSchemaPCustomErr(ctxt,
14469 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14470 NULL, type, NULL,
14471 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014472 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014473 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14474 }
14475 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014476 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
14477 * uses}
William M. Brack2f2a6632004-08-20 23:09:47 +000014478 * of the complex type definition itself, that is, for every attribute
14479 * use in the {attribute uses} of the {base type definition}, there
14480 * must be an attribute use in the {attribute uses} of the complex
14481 * type definition itself whose {attribute declaration} has the same
14482 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014483 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014484 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014485 * NOTE (1.2): This will be already satisfied by the way the attribute
14486 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14487 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014488 */
14489
14490 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014491 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14492 * definition must also have one, and the base type definition's
14493 * {attribute wildcard}'s {namespace constraint} must be a subset
14494 * of the complex type definition's {attribute wildcard}'s {namespace
14495 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014496 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014497 * NOTE (1.3) This is already checked in
14498 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014499 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014500 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014501 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014502 if ((type->contentTypeDef != NULL) &&
14503 (type->contentTypeDef == base->contentTypeDef)) {
14504 /*
14505 * SPEC (1.4.1) "The {content type} of the {base type definition}
14506 * and the {content type} of the complex type definition itself
14507 * must be the same simple type definition"
14508 * PASS
14509 */
14510 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14511 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14512 /*
14513 * SPEC (1.4.2) "The {content type} of both the {base type
14514 * definition} and the complex type definition itself must
14515 * be empty."
14516 * PASS
14517 */
14518 } else {
14519 /*
14520 * SPEC (1.4.3) "All of the following must be true:"
14521 */
14522 if (type->subtypes == NULL) {
14523 /*
14524 * SPEC 1.4.3.1 The {content type} of the complex type
14525 * definition itself must specify a particle.
14526 */
14527 xmlSchemaPCustomErr(ctxt,
14528 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14529 NULL, type, NULL,
14530 "The content type must specify a particle", NULL);
14531 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14532 }
14533 /*
14534 * SPEC (1.4.3.2) "One of the following must be true:"
14535 */
14536 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14537 /*
14538 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14539 * definition} must be empty.
14540 * PASS
14541 */
14542 } else {
14543 /*
14544 * SPEC (1.4.3.2.2) "All of the following must be true:"
14545 */
14546 if ((type->contentType != base->contentType) ||
14547 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14548 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14549 /*
14550 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14551 * or both must be element-only."
14552 */
14553 xmlSchemaPCustomErr(ctxt,
14554 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14555 NULL, type, NULL,
14556 "The content type of both, the type and its base "
14557 "type, must either 'mixed' or 'element-only'", NULL);
14558 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14559 }
14560 /*
14561 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14562 * complex type definition must be a ·valid extension·
14563 * of the {base type definition}'s particle, as defined
14564 * in Particle Valid (Extension) (§3.9.6)."
14565 *
14566 * NOTE that we won't check "Particle Valid (Extension)",
14567 * since it is ensured by the derivation process in
14568 * xmlSchemaTypeFixup(). We need to implement this when heading
14569 * for a construction API
14570 */
14571 }
14572 /*
14573 * TODO (1.5)
14574 */
14575 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014576 } else {
14577 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014578 * SPEC (2) "If the {base type definition} is a simple type definition,
14579 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014580 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014581 if (type->contentTypeDef != base) {
14582 /*
14583 * SPEC (2.1) "The {content type} must be the same simple type
14584 * definition."
14585 */
14586 xmlSchemaPCustomErr(ctxt,
14587 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14588 NULL, type, NULL,
14589 "The content type must be the simple base type", NULL);
14590 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14591 }
14592 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14593 /*
14594 * SPEC (2.2) "The {final} of the {base type definition} must not
14595 * contain extension"
14596 * NOTE that this is the same as (1.1).
14597 */
14598 xmlSchemaPCustomErr(ctxt,
14599 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14600 NULL, type, NULL,
14601 "The 'final' of the base type definition "
14602 "contains 'extension'", NULL);
14603 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14604 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014605 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014606 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014607}
14608
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014609/**
14610 * xmlSchemaCheckDerivationOKRestriction:
14611 * @ctxt: the schema parser context
14612 * @type: the complex type definition
14613 *
14614 * (3.4.6) Constraints on Complex Type Definition Schema Components
14615 * Schema Component Constraint:
14616 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14617 *
14618 * STATUS:
14619 * missing:
14620 * (5.4.2), (5.2.2.1)
14621 *
14622 * Returns 0 if the constraints are satisfied, a positive
14623 * error code if not and -1 if an internal error occured.
14624 */
14625static int
14626xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14627 xmlSchemaTypePtr type)
14628{
14629 xmlSchemaTypePtr base;
14630
14631 /*
14632 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14633 * temporarily only.
14634 */
14635 base = type->baseType;
14636 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14637 /*
14638 * SPEC (1) "The {base type definition} must be a complex type
14639 * definition whose {final} does not contain restriction."
14640 */
14641 xmlSchemaPCustomErr(ctxt,
14642 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14643 NULL, type, NULL,
14644 "The 'final' of the base type definition "
14645 "contains 'restriction'", NULL);
14646 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14647 }
14648 /*
14649 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14650 *
14651 * SPEC (5) "One of the following must be true:"
14652 */
14653 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14654 /*
14655 * SPEC (5.1) "The {base type definition} must be the
14656 * ·ur-type definition·."
14657 * PASS
14658 */
14659 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14660 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14661 /*
14662 * SPEC (5.2.1) "The {content type} of the complex type definition
14663 * must be a simple type definition"
14664 *
14665 * SPEC (5.2.2) "One of the following must be true:"
14666 */
14667 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14668 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14669 /*
14670 * SPEC (5.2.2.1) "The {content type} of the {base type
14671 * definition} must be a simple type definition from which
14672 * the {content type} is validly derived given the empty
14673 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14674 * URGENT TODO
14675 */
14676 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14677 (xmlSchemaIsParticleEmptiable(
14678 (xmlSchemaParticlePtr) base->subtypes))) {
14679 /*
14680 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14681 * and have a particle which is ·emptiable· as defined in
14682 * Particle Emptiable (§3.9.6)."
14683 * PASS
14684 */
14685 } else {
14686 xmlSchemaPCustomErr(ctxt,
14687 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14688 NULL, type, NULL,
14689 "The content type of the base type must be either "
14690 "a simple type or 'mixed' and an emptiable particle", NULL);
14691 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14692 }
14693 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14694 /*
14695 * SPEC (5.3.1) "The {content type} of the complex type itself must
14696 * be empty"
14697 */
14698 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14699 /*
14700 * SPEC (5.3.2.1) "The {content type} of the {base type
14701 * definition} must also be empty."
14702 * PASS
14703 */
14704 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14705 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14706 xmlSchemaIsParticleEmptiable(
14707 (xmlSchemaParticlePtr) base->subtypes)) {
14708 /*
14709 * SPEC (5.3.2.2) "The {content type} of the {base type
14710 * definition} must be elementOnly or mixed and have a particle
14711 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14712 * PASS
14713 */
14714 } else {
14715 xmlSchemaPCustomErr(ctxt,
14716 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14717 NULL, type, NULL,
14718 "The content type of the base type must be either "
14719 "empty or 'mixed' (or 'elements-only') and an emptiable "
14720 "particle", NULL);
14721 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14722 }
14723 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14724 ((type->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14725 (base->contentType == XML_SCHEMA_CONTENT_MIXED))) {
14726 /*
14727 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14728 * itself must be element-only"
14729 * SPEC (5.4.1.2) "The {content type} of the complex type definition
14730 * itself and of the {base type definition} must be mixed"
14731 */
14732 /*
14733 * SPEC (5.4.2) "The particle of the complex type definition itself
14734 * must be a ·valid restriction· of the particle of the {content
14735 * type} of the {base type definition} as defined in Particle Valid
14736 * (Restriction) (§3.9.6).
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014737 * URGENT TODO: (5.4.2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014738 */
14739 } else {
14740 xmlSchemaPCustomErr(ctxt,
14741 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14742 NULL, type, NULL,
14743 "The type is not a valid restriction of its base type", NULL);
14744 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14745 }
14746 return (0);
14747}
14748
14749/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014750 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014751 * @ctxt: the schema parser context
14752 * @type: the complex type definition
14753 *
14754 * (3.4.6) Constraints on Complex Type Definition Schema Components
14755 *
14756 * Returns 0 if the constraints are satisfied, a positive
14757 * error code if not and -1 if an internal error occured.
14758 */
14759static int
14760xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14761 xmlSchemaTypePtr type)
14762{
14763 int ret;
14764 /*
14765 * Complex Type Definition Properties Correct
14766 */
14767 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14768 if (ret != 0)
14769 return (ret);
14770 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14771 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14772 else
14773 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14774 return (ret);
14775}
14776
14777/**
14778 * xmlSchemaCheckSRCCT:
14779 * @ctxt: the schema parser context
14780 * @type: the complex type definition
14781 *
14782 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
14783 * Schema Representation Constraint:
14784 * Complex Type Definition Representation OK (src-ct)
14785 *
14786 * Returns 0 if the constraints are satisfied, a positive
14787 * error code if not and -1 if an internal error occured.
14788 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014789static int
14790xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
14791 xmlSchemaTypePtr type)
14792{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014793 xmlSchemaTypePtr base;
14794 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014795
14796 /*
14797 * TODO: Adjust the error codes here, as I used
14798 * XML_SCHEMAP_SRC_CT_1 only yet.
14799 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014800 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014801 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014802 /*
14803 * 1 If the <complexContent> alternative is chosen, the type definition
14804 * ·resolved· to by the ·actual value· of the base [attribute]
14805 * must be a complex type definition;
14806 */
14807 if (! IS_COMPLEX_TYPE(base)) {
14808 xmlChar *str = NULL;
14809 xmlSchemaPCustomErr(ctxt,
14810 XML_SCHEMAP_SRC_CT_1,
14811 NULL, type, type->node,
14812 "If using <complexContent>, the base type is expected to be "
14813 "a complex type. The base type '%s' is a simple type",
14814 xmlSchemaFormatQName(&str, base->targetNamespace,
14815 base->name));
14816 FREE_AND_NULL(str)
14817 return (XML_SCHEMAP_SRC_CT_1);
14818 }
14819 } else {
14820 /*
14821 * SPEC
14822 * 2 If the <simpleContent> alternative is chosen, all of the
14823 * following must be true:
14824 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14825 * base [attribute] must be one of the following:
14826 */
14827 if (IS_SIMPLE_TYPE(base)) {
14828 if ((type->flags &
14829 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14830 xmlChar *str = NULL;
14831 /*
14832 * 2.1.3 only if the <extension> alternative is also
14833 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014834 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014835 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014836 xmlSchemaPCustomErr(ctxt,
14837 XML_SCHEMAP_SRC_CT_1,
14838 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014839 "If using <simpleContent> and <restriction>, the base "
14840 "type must be a complex type. The base type '%s' is "
14841 "a simple type",
14842 xmlSchemaFormatQName(&str, base->targetNamespace,
14843 base->name));
14844 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014845 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014846 }
14847 } else {
14848 /* Base type is a complex type. */
14849 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14850 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14851 /*
14852 * 2.1.1 a complex type definition whose {content type} is a
14853 * simple type definition;
14854 * PASS
14855 */
14856 if (base->contentTypeDef == NULL) {
14857 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014858 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014859 "Internal error: xmlSchemaCheckSRCCT, "
14860 "'%s', base type has no content type",
14861 type->name);
14862 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014863 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014864 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14865 (type->flags &
14866 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014867
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014868 /*
14869 * 2.1.2 only if the <restriction> alternative is also
14870 * chosen, a complex type definition whose {content type}
14871 * is mixed and a particle emptiable.
14872 */
14873 if (! xmlSchemaIsParticleEmptiable(
14874 (xmlSchemaParticlePtr) base->subtypes)) {
14875 ret = XML_SCHEMAP_SRC_CT_1;
14876 } else if ((type->contentTypeDef == NULL) ||
14877 (type->contentTypeDef->baseType == NULL)) {
14878 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014879 /*
14880 * 2.2 If clause 2.1.2 above is satisfied, then there
14881 * must be a <simpleType> among the [children] of
14882 * <restriction>.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014883 */
14884 /* TODO: Change error code to ..._SRC_CT_2_2. */
14885 xmlSchemaPCustomErr(ctxt,
14886 XML_SCHEMAP_SRC_CT_1,
14887 NULL, type, NULL,
14888 "A <simpleType> is expected among the children "
14889 "of <restriction>, if <simpleContent> is used and "
14890 "the base type '%s' is a complex type",
14891 xmlSchemaFormatQName(&str, base->targetNamespace,
14892 base->name));
14893 FREE_AND_NULL(str)
14894 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014895 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014896 } else {
14897 ret = XML_SCHEMAP_SRC_CT_1;
14898 }
14899 }
14900 if (ret > 0) {
14901 xmlChar *str = NULL;
14902 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
14903 xmlSchemaPCustomErr(ctxt,
14904 XML_SCHEMAP_SRC_CT_1,
14905 NULL, type, NULL,
14906 "If <simpleContent> and <restriction> is used, the "
14907 "base type must be a simple type or a complex type with "
14908 "mixed content and particle emptiable. The base type "
14909 "'%s' is none of those",
14910 xmlSchemaFormatQName(&str, base->targetNamespace,
14911 base->name));
14912 } else {
14913 xmlSchemaPCustomErr(ctxt,
14914 XML_SCHEMAP_SRC_CT_1,
14915 NULL, type, NULL,
14916 "If <simpleContent> and <extension> is used, the "
14917 "base type must be a simple type. The base type '%s' "
14918 "is a complex type",
14919 xmlSchemaFormatQName(&str, base->targetNamespace,
14920 base->name));
14921 }
14922 FREE_AND_NULL(str)
14923 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014924 }
14925 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014926 * SPEC (3) "The corresponding complex type definition component must
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014927 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014928 * Definition Schema Components (§3.4.6);"
14929 * NOTE (3) will be done in xmlSchemaTypeFixup().
14930 */
14931 /*
14932 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014933 * above for {attribute wildcard} is satisfied, the intensional
14934 * intersection must be expressible, as defined in Attribute Wildcard
14935 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014936 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014937 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014938 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014939}
William M. Brack2f2a6632004-08-20 23:09:47 +000014940
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014941#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
14942 xmlSchemaPCustomErrExt(pctxt, \
14943 XML_SCHEMAP_INVALID_FACET_VALUE, \
14944 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
14945 "It is an error for both '%s' and '%s' to be specified on the "\
14946 "same type definition", \
14947 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
14948 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
14949
14950#define FACET_RESTR_ERR(fac1, msg) \
14951 xmlSchemaPCustomErr(pctxt, \
14952 XML_SCHEMAP_INVALID_FACET_VALUE, \
14953 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
14954 msg, NULL);
14955
14956#define FACET_RESTR_FIXED_ERR(fac) \
14957 xmlSchemaPCustomErr(pctxt, \
14958 XML_SCHEMAP_INVALID_FACET_VALUE, \
14959 NULL, (xmlSchemaTypePtr) fac, fac->node, \
14960 "The base type's facet is 'fixed', thus the value must not " \
14961 "differ", NULL);
14962
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014963static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014964xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
14965 xmlSchemaFacetPtr facet1,
14966 xmlSchemaFacetPtr facet2,
14967 int lessGreater,
14968 int orEqual,
14969 int ofBase)
14970{
14971 xmlChar *msg = NULL;
14972
14973 msg = xmlStrdup(BAD_CAST "'");
14974 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
14975 msg = xmlStrcat(msg, BAD_CAST "' has to be");
14976 if (lessGreater == 0)
14977 msg = xmlStrcat(msg, BAD_CAST " equal to");
14978 if (lessGreater == 1)
14979 msg = xmlStrcat(msg, BAD_CAST " greater than");
14980 else
14981 msg = xmlStrcat(msg, BAD_CAST " less than");
14982
14983 if (orEqual)
14984 msg = xmlStrcat(msg, BAD_CAST " or equal to");
14985 msg = xmlStrcat(msg, BAD_CAST " '");
14986 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
14987 if (ofBase)
14988 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
14989 else
14990 msg = xmlStrcat(msg, BAD_CAST "'");
14991
14992 xmlSchemaPCustomErr(pctxt,
14993 XML_SCHEMAP_INVALID_FACET_VALUE,
14994 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
14995 (const char *) msg, NULL);
14996
14997 if (msg != NULL)
14998 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014999}
15000
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015001static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015002xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15003 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015004{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015005 xmlSchemaTypePtr base = type->baseType;
15006 xmlSchemaFacetLinkPtr link, cur, last = NULL;
15007 xmlSchemaFacetPtr facet, bfacet,
15008 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15009 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15010 fmininc = NULL, fmaxinc = NULL,
15011 fminexc = NULL, fmaxexc = NULL,
15012 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15013 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15014 bfmininc = NULL, bfmaxinc = NULL,
15015 bfminexc = NULL, bfmaxexc = NULL;
15016 int res, err = 0, fixedErr;
15017 /*
15018 * 3 The {facets} of R are the union of S and the {facets}
15019 * of B, eliminating duplicates. To eliminate duplicates,
15020 * when a facet of the same kind occurs in both S and the
15021 * {facets} of B, the one in the {facets} of B is not
15022 * included, with the exception of enumeration and pattern
15023 * facets, for which multiple occurrences with distinct values
15024 * are allowed.
15025 */
15026 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15027 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015028
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015029 last = type->facetSet;
15030 if (last != NULL)
15031 while (last->next != NULL)
15032 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015033
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015034 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15035 facet = cur->facet;
15036 switch (facet->type) {
15037 case XML_SCHEMA_FACET_LENGTH:
15038 flength = facet; break;
15039 case XML_SCHEMA_FACET_MINLENGTH:
15040 fminlen = facet; break;
15041 case XML_SCHEMA_FACET_MININCLUSIVE:
15042 fmininc = facet; break;
15043 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15044 fminexc = facet; break;
15045 case XML_SCHEMA_FACET_MAXLENGTH:
15046 fmaxlen = facet; break;
15047 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15048 fmaxinc = facet; break;
15049 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15050 fmaxexc = facet; break;
15051 case XML_SCHEMA_FACET_TOTALDIGITS:
15052 ftotdig = facet; break;
15053 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15054 ffracdig = facet; break;
15055 default:
15056 break;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015057 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015058 }
15059 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15060 facet = cur->facet;
15061 switch (facet->type) {
15062 case XML_SCHEMA_FACET_LENGTH:
15063 bflength = facet; break;
15064 case XML_SCHEMA_FACET_MINLENGTH:
15065 bfminlen = facet; break;
15066 case XML_SCHEMA_FACET_MININCLUSIVE:
15067 bfmininc = facet; break;
15068 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15069 bfminexc = facet; break;
15070 case XML_SCHEMA_FACET_MAXLENGTH:
15071 bfmaxlen = facet; break;
15072 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15073 bfmaxinc = facet; break;
15074 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15075 bfmaxexc = facet; break;
15076 case XML_SCHEMA_FACET_TOTALDIGITS:
15077 bftotdig = facet; break;
15078 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15079 bffracdig = facet; break;
15080 default:
15081 break;
15082 }
15083 }
15084 err = 0;
15085 /*
15086 * length and minLength or maxLength (2.2) + (3.2)
15087 */
15088 if (flength && (fminlen || fmaxlen)) {
15089 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15090 "either of 'minLength' or 'maxLength' to be specified on "
15091 "the same type definition")
15092 }
15093 /*
15094 * Mutual exclusions in the same derivation step.
15095 */
15096 if ((fmaxinc) && (fmaxexc)) {
15097 /*
15098 * SCC "maxInclusive and maxExclusive"
15099 */
15100 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15101 }
15102 if ((fmininc) && (fminexc)) {
15103 /*
15104 * SCC "minInclusive and minExclusive"
15105 */
15106 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015107 }
15108
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015109 if (flength && bflength) {
15110 /*
15111 * SCC "length valid restriction"
15112 * The values have to be equal.
15113 */
15114 res = xmlSchemaCompareValues(flength->val, bflength->val);
15115 if (res == -2)
15116 goto internal_error;
15117 /*
15118 * TODO: Maby a bug in the spec.
15119 */
15120 if (res != 0)
15121 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15122 if ((res != 0) && (bflength->fixed)) {
15123 FACET_RESTR_FIXED_ERR(flength)
15124 }
15125
15126 }
15127 if (fminlen && bfminlen) {
15128 /*
15129 * SCC "minLength valid restriction"
15130 * minLength >= BASE minLength
15131 */
15132 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15133 if (res == -2)
15134 goto internal_error;
15135 if (res == -1)
15136 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15137 if ((res != 0) && (bfminlen->fixed)) {
15138 FACET_RESTR_FIXED_ERR(fminlen)
15139 }
15140 }
15141 if (fmaxlen && bfmaxlen) {
15142 /*
15143 * SCC "maxLength valid restriction"
15144 * maxLength <= BASE minLength
15145 */
15146 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15147 if (res == -2)
15148 goto internal_error;
15149 if (res == 1)
15150 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15151 if ((res != 0) && (bfmaxlen->fixed)) {
15152 FACET_RESTR_FIXED_ERR(fmaxlen)
15153 }
15154 }
15155 /*
15156 * SCC "length and minLength or maxLength"
15157 */
15158 if (! flength)
15159 flength = bflength;
15160 if (flength) {
15161 if (! fminlen)
15162 flength = bflength;
15163 if (fminlen) {
15164 /* (1.1) length >= minLength */
15165 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15166 if (res == -2)
15167 goto internal_error;
15168 if (res == -1)
15169 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15170 }
15171 if (! fmaxlen)
15172 fmaxlen = bfmaxlen;
15173 if (fmaxlen) {
15174 /* (2.1) length <= maxLength */
15175 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15176 if (res == -2)
15177 goto internal_error;
15178 if (res == 1)
15179 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15180 }
15181 }
15182 if (fmaxinc) {
15183 /*
15184 * "maxInclusive"
15185 */
15186 if (fmininc) {
15187 /* SCC "maxInclusive >= minInclusive" */
15188 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15189 if (res == -2)
15190 goto internal_error;
15191 if (res == -1) {
15192 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15193 }
15194 }
15195 /*
15196 * SCC "maxInclusive valid restriction"
15197 */
15198 if (bfmaxinc) {
15199 /* maxInclusive <= BASE maxInclusive */
15200 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15201 if (res == -2)
15202 goto internal_error;
15203 if (res == 1)
15204 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15205 if ((res != 0) && (bfmaxinc->fixed)) {
15206 FACET_RESTR_FIXED_ERR(fmaxinc)
15207 }
15208 }
15209 if (bfmaxexc) {
15210 /* maxInclusive < BASE maxExclusive */
15211 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15212 if (res == -2)
15213 goto internal_error;
15214 if (res != -1) {
15215 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15216 }
15217 }
15218 if (bfmininc) {
15219 /* maxInclusive >= BASE minInclusive */
15220 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15221 if (res == -2)
15222 goto internal_error;
15223 if (res == -1) {
15224 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15225 }
15226 }
15227 if (bfminexc) {
15228 /* maxInclusive > BASE minExclusive */
15229 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15230 if (res == -2)
15231 goto internal_error;
15232 if (res != 1) {
15233 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15234 }
15235 }
15236 }
15237 if (fmaxexc) {
15238 /*
15239 * "maxExclusive >= minExclusive"
15240 */
15241 if (fminexc) {
15242 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15243 if (res == -2)
15244 goto internal_error;
15245 if (res == -1) {
15246 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15247 }
15248 }
15249 /*
15250 * "maxExclusive valid restriction"
15251 */
15252 if (bfmaxexc) {
15253 /* maxExclusive <= BASE maxExclusive */
15254 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15255 if (res == -2)
15256 goto internal_error;
15257 if (res == 1) {
15258 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15259 }
15260 if ((res != 0) && (bfmaxexc->fixed)) {
15261 FACET_RESTR_FIXED_ERR(fmaxexc)
15262 }
15263 }
15264 if (bfmaxinc) {
15265 /* maxExclusive <= BASE maxInclusive */
15266 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15267 if (res == -2)
15268 goto internal_error;
15269 if (res == 1) {
15270 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15271 }
15272 }
15273 if (bfmininc) {
15274 /* maxExclusive > BASE minInclusive */
15275 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15276 if (res == -2)
15277 goto internal_error;
15278 if (res != 1) {
15279 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15280 }
15281 }
15282 if (bfminexc) {
15283 /* maxExclusive > BASE minExclusive */
15284 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15285 if (res == -2)
15286 goto internal_error;
15287 if (res != 1) {
15288 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15289 }
15290 }
15291 }
15292 if (fminexc) {
15293 /*
15294 * "minExclusive < maxInclusive"
15295 */
15296 if (fmaxinc) {
15297 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15298 if (res == -2)
15299 goto internal_error;
15300 if (res != -1) {
15301 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15302 }
15303 }
15304 /*
15305 * "minExclusive valid restriction"
15306 */
15307 if (bfminexc) {
15308 /* minExclusive >= BASE minExclusive */
15309 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15310 if (res == -2)
15311 goto internal_error;
15312 if (res == -1) {
15313 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15314 }
15315 if ((res != 0) && (bfminexc->fixed)) {
15316 FACET_RESTR_FIXED_ERR(fminexc)
15317 }
15318 }
15319 if (bfmaxinc) {
15320 /* minExclusive <= BASE maxInclusive */
15321 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15322 if (res == -2)
15323 goto internal_error;
15324 if (res == 1) {
15325 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15326 }
15327 }
15328 if (bfmininc) {
15329 /* minExclusive >= BASE minInclusive */
15330 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15331 if (res == -2)
15332 goto internal_error;
15333 if (res == -1) {
15334 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15335 }
15336 }
15337 if (bfmaxexc) {
15338 /* minExclusive < BASE maxExclusive */
15339 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15340 if (res == -2)
15341 goto internal_error;
15342 if (res != -1) {
15343 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15344 }
15345 }
15346 }
15347 if (fmininc) {
15348 /*
15349 * "minInclusive < maxExclusive"
15350 */
15351 if (fmaxexc) {
15352 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15353 if (res == -2)
15354 goto internal_error;
15355 if (res != -1) {
15356 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15357 }
15358 }
15359 /*
15360 * "minExclusive valid restriction"
15361 */
15362 if (bfmininc) {
15363 /* minInclusive >= BASE minInclusive */
15364 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15365 if (res == -2)
15366 goto internal_error;
15367 if (res == -1) {
15368 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15369 }
15370 if ((res != 0) && (bfmininc->fixed)) {
15371 FACET_RESTR_FIXED_ERR(fmininc)
15372 }
15373 }
15374 if (bfmaxinc) {
15375 /* minInclusive <= BASE maxInclusive */
15376 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15377 if (res == -2)
15378 goto internal_error;
15379 if (res == -1) {
15380 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15381 }
15382 }
15383 if (bfminexc) {
15384 /* minInclusive > BASE minExclusive */
15385 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15386 if (res == -2)
15387 goto internal_error;
15388 if (res != 1)
15389 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15390 }
15391 if (bfmaxexc) {
15392 /* minInclusive < BASE maxExclusive */
15393 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15394 if (res == -2)
15395 goto internal_error;
15396 if (res != -1)
15397 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15398 }
15399 }
15400 if (ftotdig && bftotdig) {
15401 /*
15402 * SCC " totalDigits valid restriction"
15403 * totalDigits <= BASE totalDigits
15404 */
15405 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15406 if (res == -2)
15407 goto internal_error;
15408 if (res == 1)
15409 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15410 -1, 1, 1);
15411 if ((res != 0) && (bftotdig->fixed)) {
15412 FACET_RESTR_FIXED_ERR(ftotdig)
15413 }
15414 }
15415 if (ffracdig && bffracdig) {
15416 /*
15417 * SCC "fractionDigits valid restriction"
15418 * fractionDigits <= BASE fractionDigits
15419 */
15420 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15421 if (res == -2)
15422 goto internal_error;
15423 if (res == 1)
15424 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15425 -1, 1, 1);
15426 if ((res != 0) && (bffracdig->fixed)) {
15427 FACET_RESTR_FIXED_ERR(ffracdig)
15428 }
15429 }
15430 /*
15431 * SCC "fractionDigits less than or equal to totalDigits"
15432 */
15433 if (! ftotdig)
15434 ftotdig = bftotdig;
15435 if (! ffracdig)
15436 ffracdig = bffracdig;
15437 if (ftotdig && ffracdig) {
15438 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15439 if (res == -2)
15440 goto internal_error;
15441 if (res == 1)
15442 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15443 -1, 1, 0);
15444 }
15445 /*
15446 * *Enumerations* won' be added here, since only the first set
15447 * of enumerations in the ancestor-or-self axis is used
15448 * for validation, plus we need to use the base type of those
15449 * enumerations for whitespace.
15450 *
15451 * *Patterns*: won't be add here, since they are ORed at
15452 * type level and ANDed at ancestor level. This will
15453 * happed during validation by walking the base axis
15454 * of the type.
15455 */
15456 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15457 bfacet = cur->facet;
15458 /*
15459 * Special handling of enumerations and patterns.
15460 * TODO: hmm, they should not appear in the set, so remove this.
15461 */
15462 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
15463 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
15464 continue;
15465 /*
15466 * Search for a duplicate facet in the current type.
15467 */
15468 link = type->facetSet;
15469 err = 0;
15470 fixedErr = 0;
15471 while (link != NULL) {
15472 facet = link->facet;
15473 if (facet->type == bfacet->type) {
15474 switch (facet->type) {
15475 case XML_SCHEMA_FACET_WHITESPACE:
15476 /*
15477 * The whitespace must be stronger.
15478 */
15479 if (facet->whitespace < bfacet->whitespace) {
15480 FACET_RESTR_ERR(flength,
15481 "The 'whitespace' value has to be equal to "
15482 "or stronger than the 'whitespace' value of "
15483 "the base type")
15484 }
15485 if ((bfacet->fixed) &&
15486 (facet->whitespace != bfacet->whitespace)) {
15487 FACET_RESTR_FIXED_ERR(facet)
15488 }
15489 break;
15490 default:
15491 break;
15492 }
15493 /* Duplicate found. */
15494 break;
15495 }
15496 link = link->next;
15497 }
15498 /*
15499 * If no duplicate was found: add the base types's facet
15500 * to the set.
15501 */
15502 if (link == NULL) {
15503 link = (xmlSchemaFacetLinkPtr)
15504 xmlMalloc(sizeof(xmlSchemaFacetLink));
15505 if (link == NULL) {
15506 xmlSchemaPErrMemory(pctxt,
15507 "deriving facets, creating a facet link", NULL);
15508 return (-1);
15509 }
15510 link->facet = cur->facet;
15511 link->next = NULL;
15512 if (last == NULL)
15513 type->facetSet = link;
15514 else
15515 last->next = link;
15516 last = link;
15517 }
15518
15519 }
15520
15521 return (0);
15522internal_error:
15523 xmlSchemaPCustomErr(pctxt,
15524 XML_SCHEMAP_INVALID_FACET_VALUE,
15525 NULL, type, NULL,
15526 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15527 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015528}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015529
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015530static int
15531xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15532 xmlSchemaTypePtr type)
15533{
15534 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
15535 /*
15536 * The actual value is then formed by replacing any union type
15537 * definition in the ·explicit members· with the members of their
15538 * {member type definitions}, in order.
15539 */
15540 link = type->memberTypes;
15541 while (link != NULL) {
15542
15543 if (IS_NOT_TYPEFIXED(link->type))
15544 xmlSchemaTypeFixup(link->type, pctxt, NULL);
15545
15546 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
15547 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
15548 if (subLink != NULL) {
15549 link->type = subLink->type;
15550 if (subLink->next != NULL) {
15551 lastLink = link->next;
15552 subLink = subLink->next;
15553 prevLink = link;
15554 while (subLink != NULL) {
15555 newLink = (xmlSchemaTypeLinkPtr)
15556 xmlMalloc(sizeof(xmlSchemaTypeLink));
15557 if (newLink == NULL) {
15558 xmlSchemaPErrMemory(pctxt, "allocating a type link",
15559 NULL);
15560 return (-1);
15561 }
15562 newLink->type = subLink->type;
15563 prevLink->next = newLink;
15564 prevLink = newLink;
15565 newLink->next = lastLink;
15566
15567 subLink = subLink->next;
15568 }
15569 }
15570 }
15571 }
15572 link = link->next;
15573 }
15574 return (0);
15575}
15576
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015577/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015578 * xmlSchemaTypeFixup:
15579 * @typeDecl: the schema type definition
15580 * @ctxt: the schema parser context
15581 *
15582 * Fixes the content model of the type.
15583 */
15584static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015585xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015586 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000015587{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015588 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000015589 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015590 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
15591 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015592 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015593 if (! IS_NOT_TYPEFIXED(type))
15594 return;
15595 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000015596 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015597 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015598
15599 if (type->baseType == NULL) {
15600 xmlSchemaPCustomErr(ctxt,
15601 XML_SCHEMAP_INTERNAL,
15602 NULL, type, NULL,
15603 "Internal error: xmlSchemaTypeFixup, "
15604 "baseType is missing on '%s'", type->name);
15605 return;
15606 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015607
15608 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015609 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015610
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015611 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015612 * Type-fix the base type.
15613 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015614 if (IS_NOT_TYPEFIXED(baseType))
15615 xmlSchemaTypeFixup(baseType, ctxt, NULL);
15616 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
15617 /*
15618 * Skip fixup if the base type is invalid.
15619 * TODO: Generate a warning!
15620 */
15621 return;
15622 }
15623 /*
15624 * This basically checks if the base type can be derived.
15625 */
15626 if (xmlSchemaCheckSRCCT(ctxt, type) != 0) {
15627 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
15628 return;
15629 }
15630 /*
15631 * Fixup the content type.
15632 */
15633 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
15634 /*
15635 * Corresponds to <complexType><simpleContent>...
15636 */
15637 if ((IS_COMPLEX_TYPE(baseType)) &&
15638 (baseType->contentTypeDef != NULL) &&
15639 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
15640 /*
15641 * SPEC (1) If <restriction> + base type is <complexType>,
15642 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000015643 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015644 * NOTE (1.1) is handled during parsing of <restriction>.
15645 *
15646 * (1.2) "...otherwise (<restriction> has no <simpleType> among
15647 * its [children]), the simple type definition which is the
15648 * {content type} of the ... base type."
Daniel Veillard01fa6152004-06-29 17:04:39 +000015649 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015650 if (type->contentTypeDef->baseType == NULL) {
15651 /*
15652 * <simpleContent><restriction> has *no* <simpleType>
15653 * child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015654 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015655 type->contentTypeDef->baseType =
15656 baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015657 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015658 } else if ((IS_COMPLEX_TYPE(baseType)) &&
15659 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
15660 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
15661 /*
15662 * SPEC (2) If <restriction> + base is a mixed <complexType> with
15663 * an emptiable particle, then a simple type definition which
15664 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015665 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015666 if ((type->contentTypeDef == NULL) ||
15667 (type->contentTypeDef->baseType == NULL)) {
15668 /*
15669 * TODO: Check if this ever happens.
15670 */
15671 xmlSchemaPCustomErr(ctxt,
15672 XML_SCHEMAP_INTERNAL,
15673 NULL, type, NULL,
15674 "Internal error: xmlSchemaTypeFixup, "
15675 "complex type '%s': the <simpleContent><restriction> "
15676 "is missing a <simpleType> child, but was not catched "
15677 "by xmlSchemaCheckSRCCT()", type->name);
15678 }
15679 } else if ((IS_COMPLEX_TYPE(baseType)) &&
15680 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
15681 /*
15682 * SPEC (3) If <extension> + base is <complexType> with
15683 * <simpleType> content, "...then the {content type} of that
15684 * complex type definition"
15685 */
15686 if (baseType->contentTypeDef == NULL) {
15687 /*
15688 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
15689 * should have catched this already.
15690 */
15691 xmlSchemaPCustomErr(ctxt,
15692 XML_SCHEMAP_INTERNAL,
15693 NULL, type, NULL,
15694 "Internal error: xmlSchemaTypeFixup, "
15695 "complex type '%s': the <extension>ed base type is "
15696 "a complex type with no simple content type",
15697 type->name);
15698 }
15699 type->contentTypeDef = baseType->contentTypeDef;
15700 } else if ((IS_SIMPLE_TYPE(baseType)) &&
15701 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
15702 /*
15703 * SPEC (4) <extension> + base is <simpleType>
15704 * "... then that simple type definition"
15705 */
15706 type->contentTypeDef = baseType;
15707 } else {
15708 /*
15709 * TODO: Check if this ever happens.
15710 */
15711 xmlSchemaPCustomErr(ctxt,
15712 XML_SCHEMAP_INTERNAL,
15713 NULL, type, NULL,
15714 "Internal error: xmlSchemaTypeFixup, "
15715 "complex type '%s' with <simpleContent>: unhandled "
15716 "derivation case", type->name);
15717 }
15718 } else {
15719 int dummySequence = 0;
15720 xmlSchemaParticlePtr particle =
15721 (xmlSchemaParticlePtr) type->subtypes;
15722 /*
15723 * Corresponds to <complexType><complexContent>...
15724 *
15725 * NOTE that the effective mixed was already set during parsing of
15726 * <complexType> and <complexContent>; its flag value is
15727 * XML_SCHEMAS_TYPE_MIXED.
15728 *
15729 * Compute the "effective content":
15730 * (2.1.1) + (2.1.2) + (2.1.3)
15731 */
15732 if ((particle == NULL) ||
15733 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
15734 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
15735 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
15736 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
15737 (particle->minOccurs == 0))) &&
15738 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
15739 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
15740 /*
15741 * SPEC (2.1.4) "If the ·effective mixed· is true, then
15742 * a particle whose properties are as follows:..."
15743 *
15744 * Empty sequence model group with
15745 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
15746 * NOTE that we sill assign it the <complexType> node to
15747 * somehow anchor it in the doc.
15748 */
15749 if ((particle == NULL) ||
15750 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015751 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015752 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015753 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015754 particle = xmlSchemaAddParticle(ctxt, ctxt->schema,
15755 type->node, 1, 1);
15756 if (particle == NULL)
15757 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015758 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015759 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015760 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015761 particle->children = (xmlSchemaTreeItemPtr)
15762 xmlSchemaAddModelGroup(ctxt, ctxt->schema,
15763 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
15764 if (particle->children == NULL)
15765 return;
15766
15767 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015768 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015769 dummySequence = 1;
15770 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
15771 } else {
15772 /*
15773 * SPEC (2.1.5) "otherwise empty"
15774 */
15775 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
15776 }
15777 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015778 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015779 * SPEC (2.2) "otherwise the particle corresponding to the
15780 * <all>, <choice>, <group> or <sequence> among the
15781 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000015782 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015783 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
15784 }
15785 /*
15786 * Compute the "content type".
15787 */
15788 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015789 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015790 * SPEC (3.1) "If <restriction>..."
15791 * (3.1.1) + (3.1.2) */
15792 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
15793 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
15794 type->contentType = XML_SCHEMA_CONTENT_MIXED;
15795 }
15796 } else {
15797 /*
15798 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015799 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015800 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
15801 /*
15802 * SPEC (3.2.1)
15803 */
15804 type->contentType = baseType->contentType;
15805 type->subtypes = baseType->subtypes;
15806 /*
15807 * NOTE that the effective mixed is ignored here.
15808 */
15809 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
15810 /*
15811 * SPEC (3.2.2)
15812 */
15813 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
15814 type->contentType = XML_SCHEMA_CONTENT_MIXED;
15815 } else {
15816 /*
15817 * SPEC (3.2.3)
15818 */
15819 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
15820 type->contentType = XML_SCHEMA_CONTENT_MIXED;
15821 /*
15822 * "A model group whose {compositor} is sequence and whose
15823 * {particles} are..."
15824 */
15825 if (! dummySequence) {
15826 xmlSchemaTreeItemPtr effectiveContent =
15827 (xmlSchemaTreeItemPtr) type->subtypes;
15828 /*
15829 * Create the particle.
15830 */
15831 particle = xmlSchemaAddParticle(ctxt, ctxt->schema,
15832 type->node, 1, 1);
15833 if (particle == NULL)
15834 return;
15835 /*
15836 * Create the "sequence" model group.
15837 */
15838 particle->children = (xmlSchemaTreeItemPtr)
15839 xmlSchemaAddModelGroup(ctxt, ctxt->schema,
15840 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
15841 if (particle->children == NULL)
15842 return;
15843 type->subtypes = (xmlSchemaTypePtr) particle;
15844 /*
15845 * SPEC "the particle of the {content type} of
15846 * the ... base ..."
15847 * Create a duplicate of the base type's particle
15848 * and assign its "term" to it.
15849 */
15850 particle->children->children =
15851 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(ctxt,
15852 ctxt->schema, type->node,
15853 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
15854 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
15855 if (particle->children->children == NULL)
15856 return;
15857 particle = (xmlSchemaParticlePtr)
15858 particle->children->children;
15859 particle->children =
15860 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
15861 /*
15862 * SPEC "followed by the ·effective content·."
15863 */
15864 particle->next = effectiveContent;
15865 } else {
15866 /*
15867 * This is the case when there is already an empty
15868 * <sequence> with minOccurs==maxOccurs==1.
15869 * Just add the base types's content type.
15870 * NOTE that, although we miss to add an intermediate
15871 * <sequence>, this should produce no difference to
15872 * neither the regex compilation of the content model,
15873 * nor to the complex type contraints.
15874 */
15875 particle->children->children =
15876 (xmlSchemaTreeItemPtr) baseType->subtypes;
15877 }
15878 }
15879 }
15880 }
15881 /*
15882 * Apply the complex type component constraints; this will not
15883 * check attributes, since this is done in
15884 * xmlSchemaBuildAttributeValidation().
15885 */
15886 if (xmlSchemaCheckCTComponent(ctxt, type) != 0)
15887 return;
15888 /*
15889 * Inherit & check constraints for attributes.
15890 */
15891 xmlSchemaBuildAttributeValidation(ctxt, type);
15892 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
15893 /*
15894 * Simple Type Definition Schema Component
15895 */
15896 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
15897 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15898 /*
15899 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015900 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015901 if (type->subtypes == NULL) {
15902 /*
15903 * This one is really needed, so get out.
15904 */
15905 return;
15906 }
15907 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015908 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015909 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
15910 /*
15911 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015912 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015913 if (type->memberTypes == NULL) {
15914 /*
15915 * This one is really needed, so get out.
15916 */
15917 return;
15918 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015919 if (xmlSchemaFinishMemberTypeDefinitionsProperty(ctxt, type) == -1)
15920 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015921 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015922 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015923 /*
15924 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015925 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015926 if (IS_NOT_TYPEFIXED(baseType))
15927 xmlSchemaTypeFixup(baseType, ctxt, NULL);
15928 /*
15929 * Variety
15930 * If the <restriction> alternative is chosen, then the
15931 * {variety} of the {base type definition}.
15932 */
15933 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
15934 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
15935 else if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15936 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
15937 /*
15938 * Inherit the itemType.
15939 */
15940 type->subtypes = baseType->subtypes;
15941 } else if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
15942 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
15943 /*
15944 * NOTE that we won't assign the memberTypes of the base,
15945 * since this will make trouble when freeing them; we will
15946 * use a lookup function to access them instead.
15947 */
15948 }
15949
15950 /*
15951 * Some optimization for validation:
15952 * If there are no facets beside the "whitespace" facet,
15953 * then a value needs not to checked against against a
15954 * facet, thus no computed value is needed.
15955 */
15956#if 0
15957 if (baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
15958 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15959 else {
15960 for (cur = type->facetSet; cur != NULL;
15961 cur = cur->next) {
15962 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15963 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15964 break;
15965 }
15966 }
15967 }
15968#endif
15969 }
15970 /*
15971 * Check constraints.
15972 *
15973 * TODO: Split this somehow, we need to know first if we can derive
15974 * from the base type at all!
15975 */
15976 if (type->baseType != NULL) {
15977 /*
15978 * Schema Component Constraint: Simple Type Restriction
15979 * (Facets)
15980 * NOTE: Satisfaction of 1 and 2 arise from the fixup
15981 * applied beforehand.
15982 */
15983 xmlSchemaCheckSRCSimpleType(ctxt, type);
15984 xmlSchemaCheckFacetValues(type, ctxt);
15985 xmlSchemaDeriveAndValidateFacets(ctxt, type);
15986 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015987 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015988
Daniel Veillard8651f532002-04-17 09:06:27 +000015989#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015990 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015991 xmlGenericError(xmlGenericErrorContext,
15992 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015993 type->node->doc->URL,
15994 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000015995 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015996 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000015997 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015998 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
15999 switch (type->contentType) {
16000 case XML_SCHEMA_CONTENT_SIMPLE:
16001 xmlGenericError(xmlGenericErrorContext, "simple\n");
16002 break;
16003 case XML_SCHEMA_CONTENT_ELEMENTS:
16004 xmlGenericError(xmlGenericErrorContext, "elements\n");
16005 break;
16006 case XML_SCHEMA_CONTENT_UNKNOWN:
16007 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16008 break;
16009 case XML_SCHEMA_CONTENT_EMPTY:
16010 xmlGenericError(xmlGenericErrorContext, "empty\n");
16011 break;
16012 case XML_SCHEMA_CONTENT_MIXED:
16013 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
16014 type->subtypes))
16015 xmlGenericError(xmlGenericErrorContext,
16016 "mixed as emptiable particle\n");
16017 else
16018 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16019 break;
16020 /* Removed, since not used. */
16021 /*
16022 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16023 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16024 break;
16025 */
16026 case XML_SCHEMA_CONTENT_BASIC:
16027 xmlGenericError(xmlGenericErrorContext, "basic\n");
16028 break;
16029 default:
16030 xmlGenericError(xmlGenericErrorContext,
16031 "not registered !!!\n");
16032 break;
16033 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016034 }
16035#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016036}
16037
16038/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016039 * xmlSchemaCheckFacet:
16040 * @facet: the facet
16041 * @typeDecl: the schema type definition
16042 * @ctxt: the schema parser context or NULL
16043 * @name: name of the type
16044 *
16045 * Checks the default values types, especially for facets
16046 *
16047 * Returns 0 if okay or -1 in cae of error
16048 */
16049int
16050xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016051 xmlSchemaTypePtr typeDecl,
16052 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016053{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000016054 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016055 int ret = 0, reuseValCtxt = 0;
16056
Daniel Veillardce682bc2004-11-05 17:22:25 +000016057 if ((facet == NULL) || (typeDecl == NULL))
16058 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016059 /*
16060 * TODO: will the parser context be given if used from
16061 * the relaxNG module?
16062 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016063
16064 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016065 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000016066 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016067 }
16068 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016069 case XML_SCHEMA_FACET_MININCLUSIVE:
16070 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16071 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016072 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16073 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016074 /*
16075 * Okay we need to validate the value
16076 * at that point.
16077 */
16078 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016079 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016080
16081 /* 4.3.5.5 Constraints on enumeration Schema Components
16082 * Schema Component Constraint: enumeration valid restriction
16083 * It is an ·error· if any member of {value} is not in the
16084 * ·value space· of {base type definition}.
16085 *
16086 * minInclusive, maxInclusive, minExclusive, maxExclusive:
16087 * The value ·must· be in the
16088 * ·value space· of the ·base type·.
16089 */
16090 /*
16091 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016092 * on the facet. In this implementation of XML Schemata the
16093 * type holding a facet, won't be a built-in type.
16094 * Thus to ensure that other API
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016095 * calls (relaxng) do work, if the given type is a built-in
16096 * type, we will assume that the given built-in type *is
16097 * already* the base type.
16098 */
16099 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16100 base = typeDecl->baseType;
16101 if (base == NULL) {
16102 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016103 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016104 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016105 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016106 typeDecl->name, NULL);
16107 return (-1);
16108 }
16109 } else
16110 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016111 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016112 * This avoids perseverative creation of the
16113 * validation context if a parser context is
16114 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016115 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016116 if (ctxt != NULL) {
16117 reuseValCtxt = 1;
16118 if (ctxt->vctxt == NULL) {
16119 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16120 return (-1);
16121 }
16122 vctxt = ctxt->vctxt;
16123 } else {
16124 vctxt = xmlSchemaNewValidCtxt(NULL);
16125 if (vctxt == NULL) {
16126 xmlSchemaPErr(ctxt, typeDecl->node,
16127 XML_SCHEMAP_INTERNAL,
16128 "Internal error: xmlSchemaCheckFacet, "
16129 "creating a new validation context.\n",
16130 NULL, NULL);
16131 return (-1);
16132 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016133 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016134
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016135 vctxt->node = facet->node;
16136 vctxt->cur = NULL;
16137 /*
16138 * NOTE: This call does not check the content nodes,
16139 * since they are not available:
16140 * facet->node is just the node holding the facet
16141 * definition, *not* the attribute holding the *value*
16142 * of the facet.
16143 */
16144 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016145 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016146 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016147 /* error code */
16148 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016149 xmlChar *str = NULL;
16150
16151 xmlSchemaPCustomErrExt(ctxt,
16152 XML_SCHEMAP_INVALID_FACET_VALUE,
16153 NULL, (xmlSchemaTypePtr) facet, facet->node,
16154 "The value '%s' of the facet does not validate "
16155 "against the base type '%s'",
16156 facet->value,
16157 xmlSchemaFormatQName(&str,
16158 base->targetNamespace, base->name), NULL);
16159 FREE_AND_NULL(str)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016160 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016161 /* xmlSchemaFacetTypeToString(facet->type), */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016162 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016163 } else if (ret < 0) {
16164 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016165 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016166 NULL, NULL, NULL,
16167 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016168 "failed to validate the value '%s' name of the "
16169 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016170 facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016171 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016172 base->name, NULL, NULL);
16173 ret = -1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016174 } else {
16175 if (vctxt->value != NULL) {
16176 facet->val = vctxt->value;
16177 vctxt->value = NULL;
16178 } else {
16179 xmlChar *str;
16180 /*
16181 * Ensure computed values even for type string.
16182 * TODO OPTIMIZE MEMORY: The value will be hold twice,
16183 * by the facet->value and by the computed value.
16184 */
16185 str = xmlStrdup(facet->value);
16186 if (xmlSchemaPostCreateVal(vctxt, typeDecl,
16187 BAD_CAST str, &(facet->val)) == -1) {
16188 FREE_AND_NULL(str)
16189 xmlSchemaPErr(ctxt, typeDecl->node,
16190 XML_SCHEMAP_INTERNAL,
16191 "Internal error: xmlSchemaCheckFacet, "
16192 "post-creating a computed value.\n",
16193 NULL, NULL);
16194 /* Note that we don't return a failure yet.*/
16195 }
16196 }
16197 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016198 if (reuseValCtxt == 0)
16199 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016200 break;
16201 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016202 case XML_SCHEMA_FACET_PATTERN:
16203 facet->regexp = xmlRegexpCompile(facet->value);
16204 if (facet->regexp == NULL) {
16205 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016206 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016207 "Type definition '%s': The value '%s' of the "
16208 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016209 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016210 ret = -1;
16211 }
16212 break;
16213 case XML_SCHEMA_FACET_TOTALDIGITS:
16214 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16215 case XML_SCHEMA_FACET_LENGTH:
16216 case XML_SCHEMA_FACET_MAXLENGTH:
16217 case XML_SCHEMA_FACET_MINLENGTH:{
16218 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016219
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016220 tmp =
16221 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
16222 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000016223 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016224 if (tmp != 0) {
16225 /* error code */
16226 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016227 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016228 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016229 NULL, (xmlSchemaTypePtr) facet, facet->node,
16230 "The value '%s' of the facet is not a valid "
16231 "nonNegativeInteger", facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016232 }
16233 ret = -1;
16234 }
16235 break;
16236 }
16237 case XML_SCHEMA_FACET_WHITESPACE:{
16238 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16239 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16240 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16241 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16242 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16243 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16244 } else {
16245 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016246 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
16247 xmlSchemaPCustomErr(ctxt,
16248 XML_SCHEMAP_INVALID_FACET_VALUE,
16249 NULL, (xmlSchemaTypePtr) facet, facet->node,
16250 "The value '%s' of the facet is not a valid",
16251 facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016252 }
16253 ret = -1;
16254 }
16255 }
16256 default:
16257 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016258 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016259 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016260}
16261
16262/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016263 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016264 * @typeDecl: the schema type definition
16265 * @ctxt: the schema parser context
16266 *
16267 * Checks the default values types, especially for facets
16268 */
16269static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016270xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16271 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016272{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016273 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016274 /*
16275 * NOTE: It is intended to use the facets list, instead
16276 * of facetSet.
16277 */
16278 if (typeDecl->facets != NULL) {
16279 xmlSchemaFacetPtr facet = typeDecl->facets;
16280
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016281 /*
16282 * Temporarily assign the "schema" to the validation context
16283 * of the parser context. This is needed for NOTATION validation.
16284 */
16285 if (ctxt->vctxt == NULL) {
16286 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16287 return;
16288 }
16289 ctxt->vctxt->schema = ctxt->schema;
16290
Daniel Veillard01fa6152004-06-29 17:04:39 +000016291 while (facet != NULL) {
16292 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16293 facet = facet->next;
16294 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016295
16296 ctxt->vctxt->schema = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016297 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016298}
16299
16300/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016301 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016302 * @ctxtMGroup: the searched model group
16303 * @selfMGroup: the second searched model group
16304 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016305 *
16306 * This one is intended to be used by
16307 * xmlSchemaCheckGroupDefCircular only.
16308 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016309 * Returns the particle with the circular model group definition reference,
16310 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016311 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016312static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016313xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016314 xmlSchemaTreeItemPtr particle)
16315{
16316 xmlSchemaTreeItemPtr circ = NULL;
16317 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016318 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016319
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016320 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016321 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016322 if (term == NULL)
16323 continue;
16324 switch (term->type) {
16325 case XML_SCHEMA_TYPE_GROUP:
16326 gdef = (xmlSchemaModelGroupDefPtr) term;
16327 if (gdef == groupDef)
16328 return (particle);
16329 /*
16330 * Mark this model group definition to avoid infinite
16331 * recursion on circular references not yet examined.
16332 */
16333 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16334 continue;
16335 if (gdef->children != NULL) {
16336 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16337 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16338 gdef->children->children);
16339 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16340 if (circ != NULL)
16341 return (circ);
16342 }
16343 break;
16344 case XML_SCHEMA_TYPE_SEQUENCE:
16345 case XML_SCHEMA_TYPE_CHOICE:
16346 case XML_SCHEMA_TYPE_ALL:
16347 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16348 if (circ != NULL)
16349 return (circ);
16350 break;
16351 default:
16352 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016353 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016354 }
16355 return (NULL);
16356}
16357
16358/**
16359 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016360 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016361 * @ctxt: the parser context
16362 * @name: the name
16363 *
16364 * Checks for circular references to model group definitions.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016365 * Additionally it
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016366 */
16367static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016368xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016369 xmlSchemaParserCtxtPtr ctxt,
16370 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016371{
16372 /*
16373 * Schema Component Constraint: Model Group Correct
16374 * 2 Circular groups are disallowed. That is, within the {particles}
16375 * of a group there must not be at any depth a particle whose {term}
16376 * is the group itself.
16377 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016378 if ((item == NULL) ||
16379 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16380 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016381 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016382 {
16383 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016384
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016385 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016386 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016387 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016388 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016389 * TODO: The error report is not adequate: this constraint
16390 * is defined for model groups but not definitions, but since
16391 * there cannot be any circular model groups without a model group
16392 * definition (if not using a construction API), we check those
16393 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016394 */
16395 xmlSchemaPCustomErr(ctxt,
16396 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016397 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016398 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016399 "defined", xmlSchemaFormatQName(&str,
16400 item->targetNamespace, item->name));
16401 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016402 /*
16403 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016404 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016405 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016406 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016407 }
16408 }
16409}
16410
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016411/**
16412 * xmlSchemaGroupDefTermFixup:
16413 * @item: the particle with a model group definition as term
16414 * @ctxt: the parser context
16415 * @name: the name
16416 *
16417 * Checks for circular references to model group definitions.
16418 * Additionally it
16419 */
16420static void
16421xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
16422 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
16423 const xmlChar * name ATTRIBUTE_UNUSED)
16424{
16425 if ((item == NULL) ||
16426 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16427 (item->children == NULL) ||
16428 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16429 (item->children->children == NULL))
16430 return;
16431 item->children = item->children->children;
16432}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016433
16434/**
16435 * xmlSchemaGetCircAttrGrRef:
16436 * @ctxtGr: the searched attribute group
16437 * @attr: the current attribute list to be processed
16438 *
16439 * This one is intended to be used by
16440 * xmlSchemaCheckSRCAttributeGroupCircular only.
16441 *
16442 * Returns the circular attribute grou reference, otherwise NULL.
16443 */
16444static xmlSchemaAttributeGroupPtr
16445xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16446 xmlSchemaAttributePtr attr)
16447{
16448 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16449 int marked;
16450 /*
16451 * We will search for an attribute group reference which
16452 * references the context attribute group.
16453 */
16454 while (attr != NULL) {
16455 marked = 0;
16456 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16457 gr = (xmlSchemaAttributeGroupPtr) attr;
16458 if (gr->refItem != NULL) {
16459 if (gr->refItem == ctxtGr)
16460 return (gr);
16461 else if (gr->refItem->flags &
16462 XML_SCHEMAS_ATTRGROUP_MARKED) {
16463 attr = attr->next;
16464 continue;
16465 } else {
16466 /*
16467 * Mark as visited to avoid infinite recursion on
16468 * circular references not yet examined.
16469 */
16470 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16471 marked = 1;
16472 }
16473 }
16474 if (gr->attributes != NULL)
16475 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16476 /*
16477 * Unmark the visited group's attributes.
16478 */
16479 if (marked)
16480 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16481 if (circ != NULL)
16482 return (circ);
16483 }
16484 attr = attr->next;
16485 }
16486 return (NULL);
16487}
16488
16489/**
16490 * xmlSchemaCheckSRCAttributeGroupCircular:
16491 * attrGr: the attribute group definition
16492 * @ctxt: the parser context
16493 * @name: the name
16494 *
16495 * Checks for circular references of attribute groups.
16496 */
16497static void
16498xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
16499 xmlSchemaParserCtxtPtr ctxt,
16500 const xmlChar * name ATTRIBUTE_UNUSED)
16501{
16502 /*
16503 * Schema Representation Constraint:
16504 * Attribute Group Definition Representation OK
16505 * 3 Circular group reference is disallowed outside <redefine>.
16506 * That is, unless this element information item's parent is
16507 * <redefine>, then among the [children], if any, there must
16508 * not be an <attributeGroup> with ref [attribute] which resolves
16509 * to the component corresponding to this <attributeGroup>. Indirect
16510 * circularity is also ruled out. That is, when QName resolution
16511 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16512 * any <attributeGroup>s with a ref [attribute] among the [children],
16513 * it must not be the case that a ·QName· is encountered at any depth
16514 * which resolves to the component corresponding to this <attributeGroup>.
16515 */
16516 /*
16517 * Only global components can be referenced.
16518 */
16519 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
16520 (attrGr->attributes == NULL))
16521 return;
16522 else {
16523 xmlSchemaAttributeGroupPtr circ;
16524
16525 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16526 if (circ != NULL) {
16527 /*
16528 * TODO: Report the referenced attr group as QName.
16529 */
16530 xmlSchemaPCustomErr(ctxt,
16531 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16532 NULL, NULL, circ->node,
16533 "Circular reference to the attribute group '%s' "
16534 "defined", attrGr->name);
16535 /*
16536 * NOTE: We will cut the reference to avoid further
16537 * confusion of the processor.
16538 * BADSPEC: The spec should define how to process in this case.
16539 */
16540 circ->attributes = NULL;
16541 circ->refItem = NULL;
16542 }
16543 }
16544}
16545
16546/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000016547 * xmlSchemaAttrGrpFixup:
16548 * @attrgrpDecl: the schema attribute definition
16549 * @ctxt: the schema parser context
16550 * @name: the attribute name
16551 *
16552 * Fixes finish doing the computations on the attributes definitions
16553 */
16554static void
Daniel Veillard3646d642004-06-02 19:19:14 +000016555xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016556 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000016557{
16558 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016559 name = attrgrp->name;
16560 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016561 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000016562 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016563 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000016564
Daniel Veillardc0826a72004-08-10 14:17:33 +000016565 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
16566 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016567 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016568 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016569 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016570 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
16571 "ref", attrgrp->ref, attrgrp->refNs,
16572 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016573 return;
16574 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016575 attrgrp->refItem = ref;
16576 /*
16577 * Check for self reference!
16578 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016579 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000016580 attrgrp->attributes = ref->attributes;
16581 attrgrp->attributeWildcard = ref->attributeWildcard;
16582 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000016583}
16584
16585/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016586 * xmlSchemaAttrCheckValConstr:
16587 * @item: an schema attribute declaration/use
16588 * @ctxt: a schema parser context
16589 * @name: the name of the attribute
16590 *
16591 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000016592 *
16593 * Fixes finish doing the computations on the attributes definitions
16594 */
16595static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016596xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
16597 xmlSchemaParserCtxtPtr ctxt,
16598 const xmlChar * name ATTRIBUTE_UNUSED)
16599{
16600
16601 /*
16602 * a-props-correct
16603 * Schema Component Constraint: Attribute Declaration Properties Correct
16604 *
16605 * 2 if there is a {value constraint}, the canonical lexical
16606 * representation of its value must be ·valid· with respect
16607 * to the {type definition} as defined in String Valid (§3.14.4).
16608 */
16609
16610 if (item->defValue != NULL) {
16611 int ret;
16612 xmlNodePtr node;
16613 xmlSchemaTypePtr type;
16614
16615 if (item->subtypes == NULL) {
16616 xmlSchemaPErr(ctxt, item->node,
16617 XML_SCHEMAP_INTERNAL,
16618 "Internal error: xmlSchemaCheckAttrValConstr, "
16619 "type is missing... skipping validation of "
16620 "value constraint", NULL, NULL);
16621 return;
16622 }
16623
16624 /*
16625 * TODO: Try to avoid creating a new context.
16626 * TODO: This all is not very performant.
16627 */
16628 type = item->subtypes;
16629 /*
16630 * Ensure there's validation context.
16631 */
16632 if (ctxt->vctxt == NULL) {
16633 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
16634 xmlSchemaPErr(ctxt, item->node,
16635 XML_SCHEMAP_INTERNAL,
16636 "Internal error: xmlSchemaCheckAttrValConstr, "
16637 "creating a new validation context.\n",
16638 NULL, NULL);
16639 return;
16640 }
16641 }
16642
16643 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
16644 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
16645 else
16646 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
16647 ctxt->vctxt->node = node;
16648 ctxt->vctxt->cur = NULL;
16649 /*
16650 * NOTE: This call does not check the content nodes,
16651 * since they are not available:
16652 * facet->node is just the node holding the facet
16653 * definition, *not* the attribute holding the *value*
16654 * of the facet.
16655 */
16656 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
16657 item->defValue, 0, 1, 1, 0);
16658 if (ret == 0) {
16659 /*
16660 * Store the computed value.
16661 */
16662 item->defVal = ctxt->vctxt->value;
16663 ctxt->vctxt->value = NULL;
16664 } else if (ret > 0) {
16665 if (ctxt != NULL) {
16666 xmlSchemaPSimpleTypeErr(ctxt,
16667 XML_SCHEMAP_A_PROPS_CORRECT_2,
16668 NULL, NULL, node,
16669 type, NULL, item->defValue,
16670 NULL, NULL, NULL);
16671 }
16672 } else if (ret < 0) {
16673 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16674 NULL, NULL, node,
16675 "Internal error: xmlSchemaAttrCheckValConstr, "
16676 "failed to validate the value constraint of the "
16677 "attribute decl/use against the type '%s'",
16678 type->name);
16679 }
16680 }
16681}
16682
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016683/**
16684 * xmlSchemaCheckElemPropsCorrect:
16685 * @ctxt: a schema parser context
16686 * @decl: the element declaration
16687 * @name: the name of the attribute
16688 *
16689 * Schema Component Constraint:
16690 * Element Declaration Properties Correct (e-props-correct)
16691 *
16692 * STATUS:
16693 * missing: (6)
16694 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016695static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016696xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
16697 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016698{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016699 int ret = 0;
16700 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016701 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016702 * SPEC (1) "The values of the properties of an element declaration
16703 * must be as described in the property tableau in The Element
16704 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
16705 * Sub-components (§5.3)."
16706 */
16707 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
16708 xmlSchemaElementPtr substGrAff = SUBST_GROUP_AFF(elemDecl);
16709 /*
16710 * SPEC (3) "If there is a non-·absent· {substitution group
16711 * affiliation}, then {scope} must be global."
16712 */
16713 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
16714 xmlSchemaPCustomErr(pctxt,
16715 XML_SCHEMAP_E_PROPS_CORRECT_3,
16716 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
16717 "Only global element declarations can have a "
16718 "substitution group affiliation", NULL);
16719 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
16720 }
16721 /*
16722 * SPEC (4) "If there is a {substitution group affiliation},
16723 * the {type definition}
16724 * of the element declaration must be validly derived from the {type
16725 * definition} of the {substitution group affiliation}, given the value
16726 * of the {substitution group exclusions} of the {substitution group
16727 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
16728 * (if the {type definition} is complex) or as defined in
16729 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
16730 * simple)."
16731 *
16732 * NOTE: {substitution group exclusions} means the values of the
16733 * attribute "final".
16734 */
16735 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
16736 int set = 0;
16737
16738 if (substGrAff->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
16739 set |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
16740 if (substGrAff->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
16741 set |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
16742
16743 if (xmlSchemaCheckCOSDerivedOK(pctxt->schema, typeDef,
16744 ELEM_TYPE(substGrAff), set) != 0) {
16745 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
16746
16747 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
16748 xmlSchemaPCustomErrExt(pctxt,
16749 XML_SCHEMAP_E_PROPS_CORRECT_4,
16750 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
16751 "The type definition '%s' is not validly derived from "
16752 "the type definition '%s' of the element declaration "
16753 "'%s' (the substitution group affiliation)",
16754 xmlSchemaGetComponentQName(&strA, typeDef),
16755 xmlSchemaGetComponentQName(&strB, ELEM_TYPE(substGrAff)),
16756 xmlSchemaGetComponentQName(&strC, substGrAff));
16757 FREE_AND_NULL(strA)
16758 FREE_AND_NULL(strB)
16759 FREE_AND_NULL(strC)
16760 }
16761 }
16762 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016763 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016764 * SPEC (5) "If the {type definition} or {type definition}'s
16765 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016766 * is or is derived from ID then there must not be a {value constraint}.
16767 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016768 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016769 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016770 if ((elemDecl->value != NULL) &&
16771 ((IS_SIMPLE_TYPE(typeDef) &&
16772 xmlSchemaIsDerivedFromBuiltInType(pctxt,
16773 ELEM_TYPE(elemDecl), XML_SCHEMAS_ID)) ||
16774 (IS_COMPLEX_TYPE(typeDef) &&
16775 HAS_SIMPLE_CONTENT(typeDef) &&
16776 xmlSchemaIsDerivedFromBuiltInType(pctxt,
16777 typeDef->contentTypeDef, XML_SCHEMAS_ID)))) {
16778
16779 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
16780 xmlSchemaPCustomErr(pctxt,
16781 XML_SCHEMAP_E_PROPS_CORRECT_5,
16782 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
16783 "The type definition (or type definition's content type) is or "
16784 "is derived from ID; value constraints are not allowed in "
16785 "conjunction with such a type definition", NULL);
16786 } else if (elemDecl->value != NULL) {
16787 int vcret;
16788 xmlNodePtr node = NULL;
16789
16790 /*
16791 * SPEC (2) "If there is a {value constraint}, the canonical lexical
16792 * representation of its value must be ·valid· with respect to the
16793 * {type definition} as defined in Element Default Valid (Immediate)
16794 * (§3.3.6)."
16795 */
16796 if (typeDef == NULL) {
16797 xmlSchemaPErr(pctxt, elemDecl->node,
16798 XML_SCHEMAP_INTERNAL,
16799 "Internal error: xmlSchemaCheckElemPropsCorrect, "
16800 "type is missing... skipping validation of "
16801 "the value constraint", NULL, NULL);
16802 return (-1);
16803 }
16804 /*
16805 * Ensure there's a validation context.
16806 */
16807 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
16808 return (-1);
16809 if (elemDecl->node != NULL) {
16810 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
16811 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
16812 BAD_CAST "fixed");
16813 else
16814 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
16815 BAD_CAST "default");
16816 }
16817 pctxt->vctxt->node = node;
16818 pctxt->vctxt->cur = NULL;
16819 vcret = xmlSchemaCheckCOSValidDefault(pctxt, pctxt->vctxt, typeDef,
16820 elemDecl->value, node);
16821 if (vcret == 0) {
16822 /*
16823 * Consume the computed value.
16824 */
16825 elemDecl->defVal = pctxt->vctxt->value;
16826 pctxt->vctxt->value = NULL;
16827 } else if (vcret < 0) {
16828 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_INTERNAL,
16829 NULL, NULL, node,
16830 "Internal error: xmlSchemaElemCheckValConstr, "
16831 "failed to validate the value constraint of the "
16832 "element declaration '%s'",
16833 elemDecl->name);
16834 ret = vcret;
16835 } else
16836 ret = vcret;
16837 }
16838
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016839 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016840 * TODO: SPEC (6) "Circular substitution groups are disallowed.
16841 * That is, it must not be possible to return to an element declaration
16842 * by repeatedly following the {substitution group affiliation} property."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016843 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016844 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016845}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016846
16847/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016848 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016849 * @item: an schema element declaration/particle
16850 * @ctxt: a schema parser context
16851 * @name: the name of the attribute
16852 *
16853 * Validates the value constraints of an element declaration.
16854 *
16855 * Fixes finish doing the computations on the element declarations.
16856 */
16857static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016858xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
16859 xmlSchemaParserCtxtPtr ctxt,
16860 const xmlChar * name ATTRIBUTE_UNUSED)
16861{
16862 if (elemDecl == NULL)
16863 return;
16864 xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016865}
16866
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016867/**
16868 * xmlSchemaMiscRefFixup:
16869 * @item: an schema component
16870 * @ctxt: a schema parser context
16871 * @name: the internal name of the component
16872 *
16873 * Resolves references of misc. schema components.
16874 */
16875static void
16876xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
16877 xmlSchemaParserCtxtPtr ctxt,
16878 const xmlChar * name ATTRIBUTE_UNUSED)
16879{
16880 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
16881 if ((item->children != NULL) &&
16882 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
16883 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
16884 xmlSchemaTreeItemPtr refItem;
16885 /*
16886 * Resolve the reference.
16887 */
16888 item->children = NULL;
16889 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
16890 ref->itemType, ref->name, ref->targetNamespace);
16891 if (refItem == NULL) {
16892 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
16893 NULL, NULL, GET_NODE(item), "ref", ref->name,
16894 ref->targetNamespace, ref->itemType, NULL);
16895 } else {
16896 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
16897 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016898 * NOTE that we will assign the model group definition
16899 * itself to the "term" of the particle. This will ease
16900 * the check for circular model group definitions. After
16901 * that the "term" will be assigned the model group of the
16902 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016903 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016904 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016905 } else
16906 item->children = refItem;
16907 }
16908 }
16909 }
16910}
16911
16912
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016913/**
16914 * xmlSchemaAttrFixup:
16915 * @item: an schema attribute declaration/use.
16916 * @ctxt: a schema parser context
16917 * @name: the name of the attribute
16918 *
16919 * Fixes finish doing the computations on attribute declarations/uses.
16920 */
16921static void
16922xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
16923 xmlSchemaParserCtxtPtr ctxt,
16924 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000016925{
Daniel Veillardc0826a72004-08-10 14:17:33 +000016926 /*
16927 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016928 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000016929 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016930 /*
16931 * The simple type definition corresponding to the <simpleType> element
16932 * information item in the [children], if present, otherwise the simple
16933 * type definition ·resolved· to by the ·actual value· of the type
16934 * [attribute], if present, otherwise the ·simple ur-type definition·.
16935 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016936 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000016937 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016938 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
16939 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016940 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016941 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016942 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000016943
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016944 type = xmlSchemaGetType(ctxt->schema, item->typeName,
16945 item->typeNs);
16946 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016947 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016948 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016949 NULL, (xmlSchemaTypePtr) item, item->node,
16950 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016951 XML_SCHEMA_TYPE_SIMPLE, NULL);
16952 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016953 item->subtypes = type;
16954
16955 } else if (item->ref != NULL) {
16956 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000016957
Daniel Veillardc0826a72004-08-10 14:17:33 +000016958 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016959 * We have an attribute use here; assign the referenced
16960 * attribute declaration.
16961 */
16962 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016963 * TODO: Evaluate, what errors could occur if the declaration is not
16964 * found. It might be possible that the "typefixup" might crash if
16965 * no ref declaration was found.
16966 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016967 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
16968 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016969 xmlSchemaPResCompAttrErr(ctxt,
16970 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016971 NULL, (xmlSchemaTypePtr) item, item->node,
16972 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016973 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016974 return;
16975 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016976 item->refDecl = decl;
16977 xmlSchemaAttrFixup(decl, ctxt, NULL);
16978
16979 item->subtypes = decl->subtypes;
16980 /*
16981 * Attribute Use Correct
16982 * au-props-correct.2: If the {attribute declaration} has a fixed
16983 * {value constraint}, then if the attribute use itself has a
16984 * {value constraint}, it must also be fixed and its value must match
16985 * that of the {attribute declaration}'s {value constraint}.
16986 */
16987 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
16988 (item->defValue != NULL)) {
16989 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
16990 (!xmlStrEqual(item->defValue, decl->defValue))) {
16991 xmlSchemaPCustomErr(ctxt,
16992 XML_SCHEMAP_AU_PROPS_CORRECT_2,
16993 NULL, NULL, item->node,
16994 "The value constraint must be fixed "
16995 "and match the referenced attribute "
16996 "declarations's value constraint '%s'",
16997 decl->defValue);
16998 }
16999 /*
17000 * FUTURE: One should change the values of the attr. use
17001 * if ever validation should be attempted even if the
17002 * schema itself was not fully valid.
17003 */
17004 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017005 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017006 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17007 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017008}
17009
17010/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017011 * xmlSchemaResolveIDCKeyRef:
17012 * @idc: the identity-constraint definition
17013 * @ctxt: the schema parser context
17014 * @name: the attribute name
17015 *
17016 * Resolve keyRef references to key/unique IDCs.
17017 */
17018static void
17019xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
17020 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017021 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017022{
17023 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17024 return;
17025 if (idc->ref->name != NULL) {
17026 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
17027 ctxt->schema->idcDef,
17028 idc->ref->name,
17029 idc->ref->targetNamespace);
17030 if (idc->ref->item == NULL) {
17031 /*
17032 * TODO: It is actually not an error to fail to resolve.
17033 */
17034 xmlSchemaPResCompAttrErr(ctxt,
17035 XML_SCHEMAP_SRC_RESOLVE,
17036 NULL, (xmlSchemaTypePtr) idc, idc->node,
17037 "refer", idc->ref->name,
17038 idc->ref->targetNamespace,
17039 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17040 return;
17041 }
17042 }
17043}
17044
17045/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017046 * xmlSchemaParse:
17047 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017048 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017049 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017050 * XML Shema struture which can be used to validate instances.
17051 * *WARNING* this interface is highly subject to change
17052 *
17053 * Returns the internal XML Schema structure built from the resource or
17054 * NULL in case of error
17055 */
17056xmlSchemaPtr
17057xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17058{
17059 xmlSchemaPtr ret = NULL;
17060 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017061 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017062 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017063
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017064 /*
17065 * This one is used if the schema to be parsed was specified via
17066 * the API; i.e. not automatically by the validated instance document.
17067 */
17068
Daniel Veillard4255d502002-04-16 15:50:10 +000017069 xmlSchemaInitTypes();
17070
Daniel Veillard6045c902002-10-09 21:13:59 +000017071 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017072 return (NULL);
17073
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017074 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017075 ctxt->counter = 0;
17076 ctxt->container = NULL;
17077
17078 /*
17079 * First step is to parse the input document into an DOM/Infoset
17080 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017081 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017082 doc = xmlReadFile((const char *) ctxt->URL, NULL,
17083 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017084 if (doc == NULL) {
17085 xmlSchemaPErr(ctxt, NULL,
17086 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017087 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017088 ctxt->URL, NULL);
17089 return (NULL);
17090 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017091 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017092 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17093 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017094 if (doc == NULL) {
17095 xmlSchemaPErr(ctxt, NULL,
17096 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017097 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017098 NULL, NULL);
17099 return (NULL);
17100 }
17101 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017102 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017103 } else if (ctxt->doc != NULL) {
17104 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017105 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017106 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017107 xmlSchemaPErr(ctxt, NULL,
17108 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017109 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017110 NULL, NULL);
17111 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017112 }
17113
17114 /*
17115 * Then extract the root and Schema parse it
17116 */
17117 root = xmlDocGetRootElement(doc);
17118 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017119 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17120 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017121 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017122 if (!preserve) {
17123 xmlFreeDoc(doc);
17124 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017125 return (NULL);
17126 }
17127
17128 /*
17129 * Remove all the blank text nodes
17130 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017131 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017132
17133 /*
17134 * Then do the parsing for good
17135 */
17136 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017137 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017138 if (!preserve) {
17139 xmlFreeDoc(doc);
17140 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017141 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017142 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017143 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017144 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017145 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017146 ctxt->ctxtType = NULL;
17147 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017148
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017149 /*
17150 * Resolve base types of simple/complex types.
17151 */
17152 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
17153
17154 if (ctxt->nberrors != 0)
17155 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017156
17157 if (ret->volatiles != NULL) {
17158 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17159 int i;
17160 xmlSchemaTreeItemPtr item;
17161
17162 for (i = 0; i < list->nbItems; i++) {
17163 item = (xmlSchemaTreeItemPtr) list->items[i];
17164 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17165 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017166 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017167 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017168 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017169 * Then fixup all attributes declarations
17170 */
17171 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017172 /*
17173 * Then fixup all attributes group declarations
17174 */
17175 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17176 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017177 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017178 * Resolve identity-constraint keyRefs.
17179 */
17180 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017181 /*
17182 * Check type defnitions for circular references.
17183 */
17184 xmlHashScan(ret->typeDecl, (xmlHashScanner)
17185 xmlSchemaCheckTypeDefCircular, ctxt);
17186 /*
17187 * Check model groups defnitions for circular references.
17188 */
17189 xmlHashScan(ret->groupDecl, (xmlHashScanner)
17190 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017191 /*
17192 * Set the "term" of particles pointing to model group definitions
17193 * to the contained model group.
17194 */
17195 if (ret->volatiles != NULL) {
17196 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17197 int i;
17198 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017199
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017200 for (i = 0; i < list->nbItems; i++) {
17201 item = (xmlSchemaParticlePtr) list->items[i];
17202 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17203 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17204 }
17205 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017206 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017207 * Check attribute groups for circular references.
17208 */
17209 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017210 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017211 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017212 * Then fix references of element declaration; apply constraints.
17213 */
17214 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017215 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017216 /*
17217 * We will stop here if the schema was not valid to avoid internal errors
17218 * on missing sub-components. This is not conforming to the spec, since it
17219 * allows missing components, but it might make further processing crash.
17220 * So see it as a very strict handling, which might be made more lax in the
17221 * future.
17222 */
17223 if (ctxt->nberrors != 0)
17224 goto exit;
17225 /*
17226 * Then fixup all types properties
17227 */
17228 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000017229 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017230 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000017231 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017232 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017233 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017234 /*
17235 * Validate the value constraint of attribute declarations/uses.
17236 */
17237 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017238 /*
17239 * Validate the value constraint of element declarations.
17240 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017241 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017242
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017243exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017244 if (ctxt->nberrors != 0) {
17245 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017246 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017247 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017248 return (ret);
17249}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017250
Daniel Veillard4255d502002-04-16 15:50:10 +000017251/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017252 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017253 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017254 * @err: the error callback
17255 * @warn: the warning callback
17256 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017257 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017258 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017259 */
17260void
17261xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017262 xmlSchemaValidityErrorFunc err,
17263 xmlSchemaValidityWarningFunc warn, void *ctx)
17264{
Daniel Veillard4255d502002-04-16 15:50:10 +000017265 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017266 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017267 ctxt->error = err;
17268 ctxt->warning = warn;
17269 ctxt->userData = ctx;
17270}
17271
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017272/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017273 * xmlSchemaGetParserErrors:
17274 * @ctxt: a XMl-Schema parser context
17275 * @err: the error callback result
17276 * @warn: the warning callback result
17277 * @ctx: contextual data for the callbacks result
17278 *
17279 * Get the callback information used to handle errors for a parser context
17280 *
17281 * Returns -1 in case of failure, 0 otherwise
17282 */
17283int
17284xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17285 xmlSchemaValidityErrorFunc * err,
17286 xmlSchemaValidityWarningFunc * warn, void **ctx)
17287{
17288 if (ctxt == NULL)
17289 return(-1);
17290 if (err != NULL)
17291 *err = ctxt->error;
17292 if (warn != NULL)
17293 *warn = ctxt->warning;
17294 if (ctx != NULL)
17295 *ctx = ctxt->userData;
17296 return(0);
17297}
17298
17299/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017300 * xmlSchemaFacetTypeToString:
17301 * @type: the facet type
17302 *
17303 * Convert the xmlSchemaTypeType to a char string.
17304 *
17305 * Returns the char string representation of the facet type if the
17306 * type is a facet and an "Internal Error" string otherwise.
17307 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017308static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017309xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17310{
17311 switch (type) {
17312 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017313 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017314 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017315 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017316 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017317 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017318 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017319 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017320 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017321 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017322 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017323 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017324 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017325 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017326 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017327 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017328 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017329 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017330 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017331 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017332 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017333 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017334 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017335 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017336 default:
17337 break;
17338 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017339 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017340}
17341
Daniel Veillardc0826a72004-08-10 14:17:33 +000017342static int
17343xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
17344{
17345 xmlSchemaTypePtr anc;
17346
17347 /*
17348 * The normalization type can be changed only for types which are derived
17349 * from xsd:string.
17350 */
17351 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017352 if (type->builtInType == XML_SCHEMAS_STRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017353 return(XML_SCHEMAS_FACET_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017354 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017355 return(XML_SCHEMAS_FACET_REPLACE);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017356 else if (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
17357 /*
17358 * Note that we assume a whitespace of preserve for anySimpleType.
17359 */
17360 return(XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017361 else {
17362 /*
17363 * For all ·atomic· datatypes other than string (and types ·derived·
17364 * by ·restriction· from it) the value of whiteSpace is fixed to
17365 * collapse
17366 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017367 return(XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017368 }
17369 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
17370 /*
17371 * For list types the facet "whiteSpace" is fixed to "collapse".
17372 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017373 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017374 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017375 return (XML_SCHEMAS_FACET_UNKNOWN);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017376 } else if (type->facetSet != NULL) {
17377 xmlSchemaTypePtr anyST;
17378 xmlSchemaFacetLinkPtr lin;
17379
17380 /*
17381 * Atomic types.
17382 */
17383 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17384 anc = type->baseType;
17385 do {
17386 /*
17387 * For all ·atomic· datatypes other than string (and types ·derived·
17388 * by ·restriction· from it) the value of whiteSpace is fixed to
17389 * collapse
17390 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017391 if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17392 (anc->builtInType == XML_SCHEMAS_NORMSTRING)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017393
17394 lin = type->facetSet;
17395 do {
17396 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017397 return(lin->facet->whitespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017398 }
17399 lin = lin->next;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017400 } while (lin != NULL);
17401 if (anc->builtInType == XML_SCHEMAS_NORMSTRING)
17402 return (XML_SCHEMAS_FACET_REPLACE);
17403 else
17404 return (XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017405 }
17406 anc = anc->baseType;
17407 } while (anc != anyST);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017408 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017409 }
17410 return (-1);
17411}
17412
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017413/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000017414 * xmlSchemaValidateFacetsInternal:
17415 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000017416 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000017417 * @facets: the list of facets to check
17418 * @value: the lexical repr of the value to validate
17419 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000017420 * @fireErrors: if 0, only internal errors will be fired;
17421 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000017422 *
17423 * Check a value against all facet conditions
17424 *
17425 * Returns 0 if the element is schemas valid, a positive error code
17426 * number otherwise and -1 in case of internal or API error.
17427 */
17428static int
17429xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017430 xmlSchemaTypePtr type,
17431 const xmlChar * value,
17432 unsigned long length,
17433 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000017434{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017435 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017436 xmlNodePtr node;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017437 xmlSchemaTypePtr biType; /* The build-in type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017438 xmlSchemaTypePtr tmpType;
17439 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000017440 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017441 xmlSchemaFacetPtr facet;
17442 unsigned long len = 0;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017443 xmlSchemaWhitespaceValueType ws;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017444
17445 ws = (xmlSchemaWhitespaceValueType) xmlSchemaGetWhiteSpaceFacetValue(type);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017446
Daniel Veillardc0826a72004-08-10 14:17:33 +000017447#ifdef DEBUG_UNION_VALIDATION
17448 printf("Facets of type: '%s'\n", (const char *) type->name);
17449 printf(" fireErrors: %d\n", fireErrors);
17450#endif
17451
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017452 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017453 /*
17454 * NOTE: Do not jump away, if the facetSet of the given type is
17455 * empty: until now, "pattern" facets of the *base types* need to
17456 * be checked as well.
17457 */
17458 biType = type->baseType;
17459 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
17460 biType = biType->baseType;
17461 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017462 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017463 "Internal error: xmlSchemaValidateFacetsInternal, "
17464 "the base type axis of the given type '%s' does not resolve to "
17465 "a built-in type.\n",
17466 type->name, NULL);
17467 return (-1);
17468 }
17469
17470 if (type->facetSet != NULL) {
17471 facetLink = type->facetSet;
17472 while (facetLink != NULL) {
17473 facet = facetLink->facet;
17474 /*
17475 * Skip the pattern "whiteSpace": it is used to
17476 * format the character content beforehand.
17477 */
17478 switch (facet->type) {
17479 case XML_SCHEMA_FACET_WHITESPACE:
17480 case XML_SCHEMA_FACET_PATTERN:
17481 case XML_SCHEMA_FACET_ENUMERATION:
17482 break;
17483 case XML_SCHEMA_FACET_LENGTH:
17484 case XML_SCHEMA_FACET_MINLENGTH:
17485 case XML_SCHEMA_FACET_MAXLENGTH:
17486 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
17487 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017488 value, length, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017489 len = length;
17490 } else
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017491 ret = xmlSchemaValidateLengthFacetWhtsp(facet,
17492 (xmlSchemaValType) biType->builtInType,
17493 value, ctxt->value, &len, ws);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017494 break;
17495 default:
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017496 ret = xmlSchemaValidateFacetWhtsp(facet, ws,
17497 biType->builtInType, value, ctxt->value, ws);
17498 /*
17499 * ret = xmlSchemaValidateFacet(biType, facet, value,
17500 * ctxt->value);
17501 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017502 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000017503 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017504 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017505 "Internal error: xmlSchemaValidateFacetsInternal, "
17506 "validating facet of type '%s'.\n",
17507 type->name, NULL);
17508 break;
17509 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017510 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017511 type, facet, NULL, NULL, NULL, NULL);
17512 }
17513
17514 facetLink = facetLink->next;
17515 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017516
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017517 }
17518
Daniel Veillardc0826a72004-08-10 14:17:33 +000017519 if (ret >= 0) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017520 xmlSchemaWhitespaceValueType fws;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017521 int found = 0;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017522 /*
17523 * Process enumerations. Facet values are in the value space
17524 * of the defining type's base type. This seems to be a bug in the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017525 * XML Schema 1.0 spec. Use the whitespace type of the base type.
17526 * Only the first set of enumerations in the ancestor-or-self axis
17527 * is used for validation.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017528 */
17529 tmpType = type;
17530 do {
17531 /*
17532 * Use the whitespace type of the base type.
17533 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017534 fws = (xmlSchemaWhitespaceValueType)
17535 xmlSchemaGetWhiteSpaceFacetValue(tmpType->baseType);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017536 retFacet = 0;
17537 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
17538 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017539 continue;
17540 found = 1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017541 retFacet = xmlSchemaValidateFacetWhtsp(facet, fws,
17542 biType->builtInType, value, ctxt->value, ws);
17543 if (retFacet == 0)
17544 break;
17545 else if (retFacet < 0) {
17546 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
17547 "Internal error: xmlSchemaValidateFacetsInternal, "
17548 "validating enumeration facet '%s' of type '%s'.\n",
17549 facet->value, tmpType->name);
17550 ret = -1;
17551 break;
17552 }
17553 }
17554 if (retFacet <= 0)
17555 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017556 tmpType = tmpType->baseType;
17557 } while ((! found) && (tmpType != NULL) &&
17558 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017559 if (retFacet > 0) {
Kasimier T. Buchcik53b5e052005-03-24 11:05:13 +000017560 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017561 if (fireErrors) {
17562 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, NULL,
17563 NULL, NULL, NULL, NULL);
17564 }
17565 }
17566 }
17567
17568 if (ret >= 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017569 /*
17570 * Process patters. Pattern facets are ORed at type level
17571 * and ANDed if derived. Walk the base type axis.
17572 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017573 tmpType = type;
17574 facet = NULL;
17575 do {
17576 retFacet = 0;
17577 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017578 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017579 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
17580 continue;
17581 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
17582 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017583 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017584 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017585 else if (retFacet < 0) {
17586 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
17587 "Internal error: xmlSchemaValidateFacetsInternal, "
17588 "validating 'pattern' facet '%s' of type '%s'.\n",
17589 facetLink->facet->value, tmpType->name);
17590 ret = -1;
17591 break;
17592 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000017593 /* Save the last non-validating facet. */
17594 facet = facetLink->facet;
17595 }
17596 if (retFacet != 0)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017597 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017598 tmpType = tmpType->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017599 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017600 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017601 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
17602 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017603 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017604 NULL, NULL, NULL, NULL);
17605 }
17606 }
17607 }
17608
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017609 return (ret);
17610}
17611
Daniel Veillard4255d502002-04-16 15:50:10 +000017612/************************************************************************
17613 * *
17614 * Simple type validation *
17615 * *
17616 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000017617
Daniel Veillard4255d502002-04-16 15:50:10 +000017618
17619/************************************************************************
17620 * *
17621 * DOM Validation code *
17622 * *
17623 ************************************************************************/
17624
Daniel Veillard4255d502002-04-16 15:50:10 +000017625static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017626 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000017627 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017628static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017629 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017630 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017631 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000017632
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017633static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017634static int xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017635
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017636/**
17637 * xmlSchemaGetFreshElemInfo:
17638 * @vctxt: the schema validation context
17639 *
17640 * Creates/reuses and initializes the element info item for
17641 * the currect tree depth.
17642 *
17643 * Returns the element info item or NULL on API or internal errors.
17644 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017645static xmlSchemaNodeInfoPtr
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017646xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt,
17647 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017648{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017649 xmlSchemaNodeInfoPtr info = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017650
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017651 if (depth > vctxt->sizeElemInfos) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017652 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017653 "Internal error: xmlSchemaGetFreshElemInfo, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017654 "an inconsistent depth encountered.\n",
17655 NULL, NULL);
17656 return (NULL);
17657 }
17658 if (vctxt->elemInfos == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017659 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
17660 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017661 if (vctxt->elemInfos == NULL) {
17662 xmlSchemaVErrMemory(vctxt,
17663 "allocating the element info array", NULL);
17664 return (NULL);
17665 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017666 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017667 vctxt->sizeElemInfos = 10;
17668 } else if (vctxt->sizeElemInfos == vctxt->depth) {
17669 int i = vctxt->sizeElemInfos;
17670
17671 vctxt->sizeElemInfos *= 2;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017672 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017673 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017674 sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017675 if (vctxt->elemInfos == NULL) {
17676 xmlSchemaVErrMemory(vctxt,
17677 "re-allocating the element info array", NULL);
17678 return (NULL);
17679 }
17680 /*
17681 * We need the new memory to be NULLed.
17682 * TODO: Use memset instead?
17683 */
17684 for (; i < vctxt->sizeElemInfos; i++)
17685 vctxt->elemInfos[i] = NULL;
17686 } else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017687 info = vctxt->elemInfos[depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017688
17689 if (info == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017690 info = (xmlSchemaNodeInfoPtr)
17691 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017692 if (info == NULL) {
17693 xmlSchemaVErrMemory(vctxt,
17694 "allocating an element info", NULL);
17695 return (NULL);
17696 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017697 vctxt->elemInfos[depth] = info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017698 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017699 memset(info, 0, sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017700 info->depth = depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017701
17702 return (info);
17703}
Daniel Veillard3646d642004-06-02 19:19:14 +000017704
17705/**
17706 * xmlSchemaFreeAttrStates:
17707 * @state: a list of attribute states
17708 *
17709 * Free the given list of attribute states
17710 *
17711 */
17712static void
17713xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
17714{
17715 xmlSchemaAttrStatePtr tmp;
17716 while (state != NULL) {
17717 tmp = state;
17718 state = state->next;
17719 xmlFree(tmp);
17720 }
17721}
17722
Daniel Veillard4255d502002-04-16 15:50:10 +000017723/**
17724 * xmlSchemaRegisterAttributes:
17725 * @ctxt: a schema validation context
17726 * @attrs: a list of attributes
17727 *
17728 * Register the list of attributes as the set to be validated on that element
17729 *
17730 * Returns -1 in case of error, 0 otherwise
17731 */
17732static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017733xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
17734{
Daniel Veillard3646d642004-06-02 19:19:14 +000017735 xmlSchemaAttrStatePtr tmp;
17736
17737 ctxt->attr = NULL;
17738 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000017739 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017740 if ((attrs->ns != NULL) &&
17741 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
17742 attrs = attrs->next;
17743 continue;
17744 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000017745 tmp = (xmlSchemaAttrStatePtr)
17746 xmlMalloc(sizeof(xmlSchemaAttrState));
17747 if (tmp == NULL) {
17748 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
17749 return (-1);
17750 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017751 tmp->attr = attrs;
17752 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
17753 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017754 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000017755 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017756 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000017757 else
17758 ctxt->attrTop->next = tmp;
17759 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017760 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000017761 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017762 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000017763}
17764
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000017765#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000017766/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017767 * xmlSchemaValidateCheckNodeList
17768 * @nodelist: the list of nodes
17769 *
17770 * Check the node list is only made of text nodes and entities pointing
17771 * to text nodes
17772 *
17773 * Returns 1 if true, 0 if false and -1 in case of error
17774 */
17775static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017776xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
17777{
Daniel Veillard4255d502002-04-16 15:50:10 +000017778 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017779 if (nodelist->type == XML_ENTITY_REF_NODE) {
17780 TODO /* implement recursion in the entity content */
17781 }
17782 if ((nodelist->type != XML_TEXT_NODE) &&
17783 (nodelist->type != XML_COMMENT_NODE) &&
17784 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000017785 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017786 return (0);
17787 }
17788 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000017789 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017790 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000017791}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000017792#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000017793
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017794static void
17795xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
17796{
17797 int i, nbItems;
17798 xmlSchemaTypePtr item, *items;
17799
17800
17801 /*
17802 * During the Assemble of the schema ctxt->curItems has
17803 * been filled with the relevant new items. Fix those up.
17804 */
17805 nbItems = ctxt->assemble->nbItems;
17806 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
17807
17808 for (i = 0; i < nbItems; i++) {
17809 item = items[i];
17810 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017811 case XML_SCHEMA_TYPE_COMPLEX:
17812 case XML_SCHEMA_TYPE_SIMPLE:
17813 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
17814 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017815 case XML_SCHEMA_TYPE_ATTRIBUTE:
17816 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
17817 break;
17818 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017819 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017820 NULL, NULL, NULL);
17821 break;
17822 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
17823 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
17824 ctxt, NULL);
17825 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017826 case XML_SCHEMA_TYPE_PARTICLE:
17827 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017828 default:
17829 break;
17830 }
17831 }
17832 /*
17833 * Circularity checks.
17834 */
17835 for (i = 0; i < nbItems; i++) {
17836 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017837 switch (item->type) {
17838 case XML_SCHEMA_TYPE_COMPLEX:
17839 case XML_SCHEMA_TYPE_SIMPLE:
17840 xmlSchemaCheckTypeDefCircular(
17841 (xmlSchemaTypePtr) item, ctxt, NULL);
17842 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017843 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017844 xmlSchemaCheckGroupDefCircular(
17845 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017846 break;
17847 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
17848 xmlSchemaCheckAttributeGroupCircular(
17849 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
17850 break;
17851 default:
17852 break;
17853 }
17854 }
17855 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017856 * Set the "term" of particles pointing to model group definitions
17857 * to the contained model group.
17858 */
17859 for (i = 0; i < nbItems; i++) {
17860 item = items[i];
17861 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
17862 (((xmlSchemaParticlePtr) item)->children != NULL) &&
17863 (((xmlSchemaParticlePtr) item)->children->type ==
17864 XML_SCHEMA_TYPE_GROUP)) {
17865 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
17866 ctxt, NULL);
17867 }
17868 }
17869 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017870 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017871 */
17872 for (i = 0; i < nbItems; i++) {
17873 item = items[i];
17874 switch (item->type) {
17875 case XML_SCHEMA_TYPE_SIMPLE:
17876 case XML_SCHEMA_TYPE_COMPLEX:
17877 xmlSchemaTypeFixup(item, ctxt, NULL);
17878 break;
17879 default:
17880 break;
17881 }
17882 }
17883 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017884 * Build the content model for complex types.
17885 */
17886 for (i = 0; i < nbItems; i++) {
17887 item = items[i];
17888 switch (item->type) {
17889 case XML_SCHEMA_TYPE_COMPLEX:
17890 xmlSchemaBuildContentModel(item, ctxt, NULL);
17891 break;
17892 default:
17893 break;
17894 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017895 }
17896 /*
17897 * Validate value contraint values.
17898 */
17899 for (i = 0; i < nbItems; i++) {
17900 item = items[i];
17901 switch (item->type) {
17902 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017903 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
17904 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017905 break;
17906 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017907 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017908 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017909 break;
17910 default:
17911 break;
17912 }
17913 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017914}
17915
17916/**
17917 * xmlSchemaAssembleByLocation:
17918 * @pctxt: a schema parser context
17919 * @vctxt: a schema validation context
17920 * @schema: the existing schema
17921 * @node: the node that fired the assembling
17922 * @nsName: the namespace name of the new schema
17923 * @location: the location of the schema
17924 *
17925 * Expands an existing schema by an additional schema.
17926 *
17927 * Returns 0 if the new schema is correct, a positive error code
17928 * number otherwise and -1 in case of an internal or API error.
17929 */
17930static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017931xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
17932 xmlSchemaPtr schema,
17933 xmlNodePtr node,
17934 const xmlChar *nsName,
17935 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017936{
17937 const xmlChar *targetNs, *oldtns;
17938 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017939 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017940 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017941 xmlSchemaParserCtxtPtr pctxt;
17942
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017943 /*
17944 * This should be used:
17945 * 1. on <import>(s)
17946 * 2. if requested by the validated instance
17947 * 3. if requested via the API
17948 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017949 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017950 return (-1);
17951 /*
17952 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017953 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017954 if ((vctxt->pctxt == NULL) &&
17955 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
17956 xmlSchemaVErr(vctxt, node,
17957 XML_SCHEMAV_INTERNAL,
17958 "Internal error: xmlSchemaAssembleByLocation, "
17959 "failed to create a temp. parser context.\n",
17960 NULL, NULL);
17961 return (-1);
17962 }
17963 pctxt = vctxt->pctxt;
17964 /*
17965 * Set the counter to produce unique names for anonymous items.
17966 */
17967 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017968 /*
17969 * Acquire the schema document.
17970 */
17971 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
17972 nsName, location, &doc, &targetNs, 0);
17973 if (ret != 0) {
17974 if (doc != NULL)
17975 xmlFreeDoc(doc);
17976 } else if (doc != NULL) {
17977 docElem = xmlDocGetRootElement(doc);
17978 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017979 * Create new assemble info.
17980 */
17981 if (pctxt->assemble == NULL) {
17982 pctxt->assemble = xmlSchemaNewAssemble();
17983 if (pctxt->assemble == NULL) {
17984 xmlSchemaVErrMemory(vctxt,
17985 "Memory error: xmlSchemaAssembleByLocation, "
17986 "allocating assemble info", NULL);
17987 xmlFreeDoc(doc);
17988 return (-1);
17989 }
17990 }
17991 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017992 * Save and reset the context & schema.
17993 */
17994 oldflags = schema->flags;
17995 oldtns = schema->targetNamespace;
17996 olddoc = schema->doc;
17997
17998 xmlSchemaClearSchemaDefaults(schema);
17999 schema->targetNamespace = targetNs;
18000 /* schema->nbCurItems = 0; */
18001 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018002 pctxt->ctxtType = NULL;
18003 pctxt->parentItem = NULL;
18004
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018005 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18006 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018007 xmlSchemaPostSchemaAssembleFixup(pctxt);
18008 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018009 * Set the counter of items.
18010 */
18011 schema->counter = pctxt->counter;
18012 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018013 * Free the list of assembled components.
18014 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018015 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018016 /*
18017 * Restore the context & schema.
18018 */
18019 schema->flags = oldflags;
18020 schema->targetNamespace = oldtns;
18021 schema->doc = olddoc;
18022 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018023 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018024 return (ret);
18025}
18026
18027/**
18028 * xmlSchemaAssembleByXSIAttr:
18029 * @vctxt: a schema validation context
18030 * @xsiAttr: an xsi attribute
18031 * @noNamespace: whether a schema with no target namespace is exptected
18032 *
18033 * Expands an existing schema by an additional schema using
18034 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18035 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18036 * must be set to 1.
18037 *
18038 * Returns 0 if the new schema is correct, a positive error code
18039 * number otherwise and -1 in case of an internal or API error.
18040 */
18041static int
18042xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
18043 xmlAttrPtr xsiAttr,
18044 int noNamespace)
18045{
18046 xmlChar *value;
18047 const xmlChar *cur, *end;
18048 const xmlChar *nsname = NULL, *location;
18049 int count = 0;
18050 int ret = 0;
18051
18052 if (xsiAttr == NULL) {
18053 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
18054 NULL, NULL,
18055 "Internal error: xmlSchemaAssembleByXSIAttr, "
18056 "bad arguments", NULL);
18057 return (-1);
18058 }
18059 /*
18060 * Parse the value; we will assume an even number of values
18061 * to be given (this is how Xerces and XSV work).
18062 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018063 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018064 cur = value;
18065 do {
18066 if (noNamespace != 1) {
18067 /*
18068 * Get the namespace name.
18069 */
18070 while (IS_BLANK_CH(*cur))
18071 cur++;
18072 end = cur;
18073 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18074 end++;
18075 if (end == cur)
18076 break;
18077 count++;
18078 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
18079 cur = end;
18080 }
18081 /*
18082 * Get the URI.
18083 */
18084 while (IS_BLANK_CH(*cur))
18085 cur++;
18086 end = cur;
18087 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18088 end++;
18089 if (end == cur)
18090 break;
18091 count++;
18092 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018093 cur = end;
18094 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018095 xsiAttr->parent, nsname, location);
18096 if (ret == -1) {
18097 xmlSchemaVCustomErr(vctxt,
18098 XML_SCHEMAV_INTERNAL,
18099 (xmlNodePtr) xsiAttr, NULL,
18100 "Internal error: xmlSchemaAssembleByXSIAttr, "
18101 "assembling schemata", NULL);
18102 if (value != NULL)
18103 xmlFree(value);
18104 return (-1);
18105 }
18106 } while (*cur != 0);
18107 if (value != NULL)
18108 xmlFree(value);
18109 return (ret);
18110}
18111
18112/**
18113 * xmlSchemaAssembleByXSIElem:
18114 * @vctxt: a schema validation context
18115 * @elem: an element node possibly holding xsi attributes
18116 * @noNamespace: whether a schema with no target namespace is exptected
18117 *
18118 * Assembles an existing schema by an additional schema using
18119 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
18120 * of the given @elem.
18121 *
18122 * Returns 0 if the new schema is correct, a positive error code
18123 * number otherwise and -1 in case of an internal or API error.
18124 */
18125static int
18126xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
18127 xmlNodePtr elem)
18128{
18129 int ret = 0, retNs = 0;
18130 xmlAttrPtr attr;
18131
18132 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
18133 if (attr != NULL) {
18134 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
18135 if (retNs == -1)
18136 return (-1);
18137 }
18138 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
18139 if (attr != NULL) {
18140 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
18141 if (ret == -1)
18142 return (-1);
18143 }
18144 if (retNs != 0)
18145 return (retNs);
18146 else
18147 return (ret);
18148}
18149
Daniel Veillard4255d502002-04-16 15:50:10 +000018150/**
Daniel Veillard4255d502002-04-16 15:50:10 +000018151 * xmlSchemaValidateCallback:
18152 * @ctxt: a schema validation context
18153 * @name: the name of the element detected (might be NULL)
18154 * @type: the type
18155 *
18156 * A transition has been made in the automata associated to an element
18157 * content model
18158 */
18159static void
18160xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018161 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018162 xmlSchemaBasicItemPtr item, xmlNodePtr node)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018163{
Daniel Veillard4255d502002-04-16 15:50:10 +000018164 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018165
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018166 /*
18167 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
18168 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018169 ctxt->node = node;
18170 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018171
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018172 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018173
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018174 /*
18175 * Assemble new schemata using xsi.
18176 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018177 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018178 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018179
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018180 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
18181 if (ret == -1) {
18182 xmlSchemaVCustomErr(ctxt,
18183 XML_SCHEMAV_INTERNAL,
18184 ctxt->node, NULL,
18185 "Internal error: xmlSchemaValidateElement, "
18186 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018187 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018188 }
18189 /*
18190 * NOTE: We won't react on schema parser errors here.
18191 * TODO: But a warning would be nice.
18192 */
18193 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018194 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018195 case XML_SCHEMA_TYPE_ELEMENT: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018196#ifdef DEBUG_CONTENT
18197 xmlGenericError(xmlGenericErrorContext,
18198 "xmlSchemaValidateCallback: %s, %s, %s\n",
18199 name, ((xmlSchemaElementPtr) item)->name, node->name);
18200#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018201 xmlSchemaValidateElementByDeclaration(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018202 (xmlSchemaElementPtr) item);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018203 break;
18204 }
18205 case XML_SCHEMA_TYPE_ANY:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018206#ifdef DEBUG_CONTENT
18207 xmlGenericError(xmlGenericErrorContext,
18208 "xmlSchemaValidateCallback: %s, <any>, %s\n",
18209 name, node->name);
18210#endif
18211 xmlSchemaValidateElementByWildcard(ctxt,
18212 (xmlSchemaWildcardPtr) item);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018213 break;
18214 default:
18215 break;
18216 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018217leave:
18218
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018219 xmlSchemaEndElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000018220 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018221}
Daniel Veillard4255d502002-04-16 15:50:10 +000018222
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018223static int
18224xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18225 const xmlChar *value,
18226 xmlSchemaValPtr *val,
18227 xmlNodePtr node)
18228{
18229 int ret;
18230
18231 ret = xmlValidateQName(value, 1);
18232 if (ret != 0)
18233 return (ret);
18234
18235 {
18236 xmlChar *uri = NULL;
18237 xmlChar *local = NULL;
18238 xmlChar *prefix;
18239
18240 local = xmlSplitQName2(value, &prefix);
18241 if (prefix != NULL) {
18242 xmlNsPtr ns;
18243
18244 /*
18245 * TODO: Make this streamable.
18246 */
18247 if ((node == NULL) || (node->doc == NULL)) {
18248 xmlFree(prefix);
18249 xmlFree(local);
18250 return (3);
18251 }
18252
18253 ns = xmlSearchNs(node->doc, node, prefix);
18254 if (ns == NULL) {
18255 xmlFree(prefix);
18256 xmlFree(local);
18257 return (1);
18258 }
18259 }
18260 if (prefix != NULL) {
18261 if (xmlHashLookup2(vctxt->schema->notaDecl, local, uri) == NULL)
18262 ret = 1;
18263 } else if (xmlHashLookup2(vctxt->schema->notaDecl, value,
18264 NULL) == NULL)
18265 ret = 1;
18266
18267 if ((ret == 0) && (val != NULL)) {
18268 if (prefix != NULL) {
18269 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST local,
18270 BAD_CAST xmlStrdup(uri));
18271 local = NULL;
18272 } else
18273 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST xmlStrdup(value),
18274 NULL);
18275 if (*val == NULL)
18276 ret = -1;
18277 }
18278 if (local != NULL)
18279 xmlFree(local);
18280 }
18281
18282 return (ret);
18283}
18284
Daniel Veillard01fa6152004-06-29 17:04:39 +000018285/**
18286 * xmlSchemaValidateSimpleTypeValue:
18287 * @ctxt: a schema validation context
18288 * @value: the value to be validated
18289 * @fireErrors: shall errors be reported?
18290 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000018291 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018292 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000018293 *
18294 * Validates a value by the given type (user derived or built-in).
18295 *
18296 * Returns 0 if the value is valid, a positive error code
18297 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000018298 */
18299static int
18300xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018301 xmlSchemaTypePtr type,
18302 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018303 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018304 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018305 int normalize,
18306 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000018307{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018308 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018309 int ret = 0;
18310 xmlChar *normValue = NULL;
18311 int wtsp;
18312
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018313 node = ctxt->node;
18314 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018315 wtsp = ctxt->valueWS;
18316 /*
18317 * Normalize the value.
18318 */
18319 if (normalize &&
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018320 (ctxt->valueWS != XML_SCHEMAS_FACET_COLLAPSE)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018321 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
18322
18323 if ((norm != -1) && (norm > ctxt->valueWS)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018324 if (norm == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018325 normValue = xmlSchemaCollapseString(value);
18326 else
18327 normValue = xmlSchemaWhiteSpaceReplace(value);
18328 ctxt->valueWS = norm;
18329 if (normValue != NULL)
18330 value = (const xmlChar *) normValue;
18331 }
18332 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018333 /*
18334 * The nodes of a content must be checked only once,
18335 * this is not working since list types will fire this
18336 * multiple times.
18337 */
18338 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
18339 xmlNodePtr cur = ctxt->cur;
18340
18341 do {
18342 switch (cur->type) {
18343 case XML_TEXT_NODE:
18344 case XML_CDATA_SECTION_NODE:
18345 case XML_PI_NODE:
18346 case XML_COMMENT_NODE:
18347 case XML_XINCLUDE_START:
18348 case XML_XINCLUDE_END:
18349 break;
18350 case XML_ENTITY_REF_NODE:
18351 case XML_ENTITY_NODE:
18352 /* TODO: Scour the entities for illegal nodes. */
18353 TODO break;
18354 case XML_ELEMENT_NODE: {
18355 /* NOTE: Changed to an internal error, since the
18356 * existence of an element node will be already checked in
18357 * xmlSchemaValidateElementBySimpleType and in
18358 * xmlSchemaValidateElementByComplexType.
18359 */
18360 xmlSchemaVCustomErr(ctxt,
18361 XML_SCHEMAV_INTERNAL,
18362 /* XML_SCHEMAS_ERR_INVALIDELEM, */
18363 node, type,
18364 "Element '%s' found in simple type content",
18365 cur->name);
18366 return (XML_SCHEMAV_INTERNAL);
18367 }
18368 case XML_ATTRIBUTE_NODE:
18369 case XML_DOCUMENT_NODE:
18370 case XML_DOCUMENT_TYPE_NODE:
18371 case XML_DOCUMENT_FRAG_NODE:
18372 case XML_NOTATION_NODE:
18373 case XML_HTML_DOCUMENT_NODE:
18374 case XML_DTD_NODE:
18375 case XML_ELEMENT_DECL:
18376 case XML_ATTRIBUTE_DECL:
18377 case XML_ENTITY_DECL:
18378 case XML_NAMESPACE_DECL:
18379#ifdef LIBXML_DOCB_ENABLED
18380 case XML_DOCB_DOCUMENT_NODE:
18381#endif
18382 xmlSchemaVCustomErr(ctxt,
18383 XML_SCHEMAV_INTERNAL,
18384 /* XML_SCHEMAS_ERR_INVALIDELEM, */
18385 node, NULL,
18386 "Node of unexpected type found in simple type content",
18387 NULL);
18388 return (XML_SCHEMAV_INTERNAL);
18389 }
18390 cur = cur->next;
18391 } while (cur != NULL);
18392 }
18393
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018394 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018395
18396 if (ctxt->value != NULL) {
18397 xmlSchemaFreeValue(ctxt->value);
18398 ctxt->value = NULL;
18399 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018400 /*
18401 * STREAM-READ-CHILDREN.
18402 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018403 if ((type->builtInType == XML_SCHEMAS_NOTATION) &&
18404 (ctxt->schema != NULL)) {
18405 /*
18406 * NOTATIONs need to be processed here, since they need
18407 * to lookup in the hashtable of NOTATION declarations.
18408 */
18409 ret = xmlSchemaValidateNotation(ctxt, value, &(ctxt->value), node);
18410 } else
18411 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018412 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018413 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
18414 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
18415 else
18416 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018417 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018418 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018419 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018420 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018421 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018422 "validating built-in type '%s'\n", type->name, NULL);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018423 } else if ((ctxt->value == NULL) &&
18424 (type->builtInType == XML_SCHEMAS_STRING) &&
18425 (ctxt->nodeInfo != NULL) &&
18426 (ctxt->nodeInfo->flags & XML_SCHEMA_ELEM_INFO_VALUE_NEEDED)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018427 xmlChar *valdup;
18428 /*
18429 * Create a precomputed string value for "string" as well if
18430 * requested.
18431 */
18432 valdup = xmlStrdup(value);
18433 ctxt->value = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
18434 BAD_CAST valdup);
18435 if ((valdup != NULL) && (ctxt->value == NULL))
18436 xmlFree(valdup);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018437 }
18438 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
18439 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
18440 * a literal in the ·lexical space· of {base type definition}
18441 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018442 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018443 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018444 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018445 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018446 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018447 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018448 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018449 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018450 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018451 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018452 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018453 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000018454 * Check facets.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018455 */
18456 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018457 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018458 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018459 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018460 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018461 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018462 type->name, NULL);
18463 } else if (ret > 0) {
18464 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018465 /*
18466 Disabled, since the facet validation already reports errors.
18467 if (fireErrors)
18468 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
18469 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018470 }
18471 }
18472 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
18473
18474 xmlSchemaTypePtr tmpType;
18475 const xmlChar *cur, *end;
18476 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018477 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018478
18479 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
18480 * of white space separated tokens, each of which ·match·es a literal
18481 * in the ·lexical space· of {item type definition}
18482 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000018483
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000018484 if (value == NULL)
18485 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000018486 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018487 cur = value;
18488 do {
18489 while (IS_BLANK_CH(*cur))
18490 cur++;
18491 end = cur;
18492 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18493 end++;
18494 if (end == cur)
18495 break;
18496 tmp = xmlStrndup(cur, end - cur);
18497 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018498 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018499 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018500 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018501 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018502 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18503 "validating an item of list simple type '%s'\n",
18504 type->name, NULL);
18505 break;
18506 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018507 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018508 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018509 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018510 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018511 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018512 cur = end;
18513 } while (*cur != 0);
18514 /*
18515 * Check facets.
18516 */
18517 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018518 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018519 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018520 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018521 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018522 } else if ((ret == 0) && (applyFacets)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018523 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018524 value, len, fireErrors);
18525 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018526 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018527 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18528 "validating facets of list simple type '%s'\n",
18529 type->name, NULL);
18530 } else if (ret > 0) {
18531 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018532 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000018533 Disabled, since the facet validation already reports errors.
18534 if (fireErrors)
18535 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018536 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018537 }
18538
Daniel Veillard01fa6152004-06-29 17:04:39 +000018539 }
18540 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
18541 xmlSchemaTypeLinkPtr memberLink;
18542
18543 /*
18544 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
18545 * not apply directly; however, the normalization behavior of ·union·
18546 * types is controlled by the value of whiteSpace on that one of the
18547 * ·memberTypes· against which the ·union· is successfully validated.
18548 *
18549 * This means that the value is normalized by the first validating
18550 * member type, then the facets of the union type are applied. This
18551 * needs changing of the value!
18552 */
18553
18554 /*
18555 * 1.2.3 if {variety} is ·union· then the string must ·match· a
18556 * literal in the ·lexical space· of at least one member of
18557 * {member type definitions}
18558 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018559#ifdef DEBUG_UNION_VALIDATION
18560 printf("Union ST : '%s'\n", (const char *) type->name);
18561 printf(" fireErrors : %d\n", fireErrors);
18562 printf(" applyFacets: %d\n", applyFacets);
18563#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000018564 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
18565 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018566 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018567 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018568 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018569 type->name, NULL);
18570 ret = -1;
18571 }
18572 if (ret == 0) {
18573 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018574 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
18575 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018576 if ((ret <= 0) || (ret == 0))
18577 break;
18578 memberLink = memberLink->next;
18579 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018580 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018581 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018582 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018583 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018584 type->name, NULL);
18585 } else if (ret > 0) {
18586 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018587 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018588 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018589 }
18590 }
18591 /*
18592 * Apply facets (pattern, enumeration).
18593 */
18594 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
18595 int mws;
18596 /*
18597 * The normalization behavior of ·union· types is controlled by
18598 * the value of whiteSpace on that one of the ·memberTypes·
18599 * against which the ·union· is successfully validated.
18600 */
18601 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018602 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018603 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18604 "the value was already normalized for the union simple "
18605 "type '%s'.\n", type->name, NULL);
18606 }
18607 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
18608 if (mws > ctxt->valueWS) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018609 if (mws == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018610 normValue = xmlSchemaCollapseString(value);
18611 else
18612 normValue = xmlSchemaWhiteSpaceReplace(value);
18613 if (normValue != NULL)
18614 value = (const xmlChar *) normValue;
18615 }
18616
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018617 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018618 value, 0, fireErrors);
18619 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018620 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018621 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18622 "validating facets of union simple type '%s'\n",
18623 type->name, NULL);
18624 } else if (ret > 0) {
18625 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
18626 /*
18627 if (fireErrors)
18628 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
18629 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018630 }
18631 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018632 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018633 ctxt->valueWS = wtsp;
18634 if (normValue != NULL)
18635 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018636 return (ret);
18637}
18638
18639/**
18640 * xmlSchemaValidateSimpleTypeElement:
18641 * @ctxt: a schema validation context
18642 * @node: the element node to be validated.
18643 *
18644 * Validate the element against a simple type.
18645 *
18646 * Returns 0 if the element is valid, a positive error code
18647 * number otherwise and -1 in case of an internal or API error.
18648 */
18649static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018650xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018651 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018652 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018653 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000018654{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018655 xmlSchemaTypePtr oldtype;
18656 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018657 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018658 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018659 int ret = 0, retval = 0;
18660
Daniel Veillard01fa6152004-06-29 17:04:39 +000018661 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018662 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
18663 "Internal error: xmlSchemaValidateElementBySimpleType, "
18664 "bad arguments", NULL);
18665 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018666 }
18667
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018668 oldtype = ctxt->type;
18669 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018670 /*
18671 * cvc-type: 3.1.2 The element information item must have no element
18672 * information item [children].
18673 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018674 /*
18675 * STREAM: Child nodes are processed.
18676 */
18677 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018678 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018679 /*
18680 * TODO: Entities, will they produce elements as well?
18681 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018682 if (cur->type == XML_ELEMENT_NODE) {
18683 xmlSchemaVCustomErr(ctxt,
18684 XML_SCHEMAV_CVC_TYPE_3_1_2,
18685 node, type,
18686 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018687 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018688 }
18689 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018690 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018691
Daniel Veillard01fa6152004-06-29 17:04:39 +000018692 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018693 * cvc-type 3.1.1:
18694 *
18695 * The attributes of must be empty, excepting those whose namespace name
18696 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
18697 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018698 */
18699 /*
18700 * STREAM: Attribute nodes are processed.
18701 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018702 attr = node->properties;
18703 while (attr != NULL) {
18704 if ((attr->ns == NULL) ||
18705 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
18706 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
18707 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
18708 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
18709 (!xmlStrEqual
18710 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018711 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018712 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
18713 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018714 }
18715 attr = attr->next;
18716 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018717 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018718 * This will skip validation if the type is 'anySimpleType' and
18719 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018720 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018721 if ((! isNil) &&
18722 (valSimpleContent == 1) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018723 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
18724 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018725 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018726
18727 value = xmlNodeGetContent(node);
18728 /*
18729 * NOTE: This call will not check the content nodes, since
18730 * this should be checked here already.
18731 */
18732 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
18733 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000018734 if (value != NULL)
18735 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018736 if (retval != 0)
18737 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000018738 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018739 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018740 return (ret);
18741}
Daniel Veillard4255d502002-04-16 15:50:10 +000018742
18743/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018744 * xmlSchemaValQNameAcquire:
18745 * @value: the lexical represantation of the QName value
18746 * @node: the node to search for the corresponding namespace declaration
18747 * @nsName: the resulting namespace name if found
18748 *
18749 * Checks that a value conforms to the lexical space of the type QName;
18750 * if valid, the corresponding namespace name is searched and retured
18751 * as a copy in @nsName. The local name is returned in @localName as
18752 * a copy.
18753 *
18754 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
18755 * namespace declaration was found in scope; -1 in case of an internal or
18756 * API error.
18757 */
18758static int
18759xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
18760 xmlChar **nsName, xmlChar **localName)
18761{
18762 int ret;
18763 xmlChar *local = NULL;
18764
18765 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
18766 return (-1);
18767 *nsName = NULL;
18768 *localName = NULL;
18769 ret = xmlValidateQName(value, 1);
18770 if (ret == 0) {
18771 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018772 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018773
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018774 /*
18775 * NOTE: xmlSplitQName2 will return a duplicated
18776 * string.
18777 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018778 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018779 if (local == NULL)
18780 local = xmlStrdup(value);
18781 ns = xmlSearchNs(node->doc, node, prefix);
18782 /*
18783 * A namespace need not to be found if the prefix is NULL.
18784 */
18785 if (ns != NULL) {
18786 /*
18787 * TODO: Is it necessary to duplicate the URI here?
18788 */
18789 *nsName = xmlStrdup(ns->href);
18790 } else if (prefix != NULL) {
18791 xmlFree(prefix);
18792 if (local != NULL)
18793 xmlFree(local);
18794 return (2);
18795 }
18796 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018797 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018798 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018799 } else
18800 return (1);
18801 return (ret);
18802}
18803
18804/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018805 * xmlSchemaHasElemContent:
18806 * @node: the node
18807 *
18808 * Scours the content of the given node for element
18809 * nodes.
18810 *
18811 * Returns 1 if an element node is found,
18812 * 0 otherwise.
18813 */
18814static int
18815xmlSchemaHasElemContent(xmlNodePtr node)
18816{
18817 if (node == NULL)
18818 return (0);
18819 node = node->children;
18820 while (node != NULL) {
18821 if (node->type == XML_ELEMENT_NODE)
18822 return (1);
18823 node = node->next;
18824 }
18825 return (0);
18826}
18827/**
18828 * xmlSchemaHasElemOrCharContent:
18829 * @node: the node
18830 *
18831 * Scours the content of the given node for element
18832 * and character nodes.
18833 *
18834 * Returns 1 if an element or character node is found,
18835 * 0 otherwise.
18836 */
18837static int
18838xmlSchemaHasElemOrCharContent(xmlNodePtr node)
18839{
18840 if (node == NULL)
18841 return (0);
18842 node = node->children;
18843 while (node != NULL) {
18844 switch (node->type) {
18845 case XML_ELEMENT_NODE:
18846 /*
18847 * TODO: Ask Daniel if these are all character nodes.
18848 */
18849 case XML_TEXT_NODE:
18850 case XML_CDATA_SECTION_NODE:
18851 /*
18852 * TODO: How XML_ENTITY_NODEs evaluated?
18853 */
18854 case XML_ENTITY_REF_NODE:
18855 case XML_ENTITY_NODE:
18856 return (1);
18857 break;
18858 default:
18859 break;
18860 }
18861 node = node->next;
18862 }
18863 return (0);
18864}
18865
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018866/************************************************************************
18867 * *
18868 * Identity-constraints (IDC) *
18869 * *
18870 ************************************************************************/
18871
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018872/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018873 * xmlSchemaAugmentIDC:
18874 * @idcDef: the IDC definition
18875 *
18876 * Creates an augmented IDC definition item.
18877 *
18878 * Returns the item, or NULL on internal errors.
18879 */
18880static void
18881xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18882 xmlSchemaValidCtxtPtr vctxt)
18883{
18884 xmlSchemaIDCAugPtr aidc;
18885
18886 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18887 if (aidc == NULL) {
18888 xmlSchemaVErrMemory(vctxt,
18889 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18890 NULL);
18891 return;
18892 }
18893 aidc->bubbleDepth = -1;
18894 aidc->def = idcDef;
18895 aidc->next = NULL;
18896 if (vctxt->aidcs == NULL)
18897 vctxt->aidcs = aidc;
18898 else {
18899 aidc->next = vctxt->aidcs;
18900 vctxt->aidcs = aidc;
18901 }
18902}
18903
18904/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018905 * xmlSchemaIDCNewBinding:
18906 * @idcDef: the IDC definition of this binding
18907 *
18908 * Creates a new IDC binding.
18909 *
18910 * Returns the new binding in case of succeeded, NULL on internal errors.
18911 */
18912static xmlSchemaPSVIIDCBindingPtr
18913xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18914{
18915 xmlSchemaPSVIIDCBindingPtr ret;
18916
18917 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18918 sizeof(xmlSchemaPSVIIDCBinding));
18919 if (ret == NULL) {
18920 xmlSchemaVErrMemory(NULL,
18921 "allocating a PSVI IDC binding item", NULL);
18922 return (NULL);
18923 }
18924 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18925 ret->definition = idcDef;
18926 return (ret);
18927}
18928
18929/**
18930 * xmlSchemaIDCStoreNodeTableItem:
18931 * @vctxt: the WXS validation context
18932 * @item: the IDC node table item
18933 *
18934 * The validation context is used to store an IDC node table items.
18935 * They are stored to avoid copying them if IDC node-tables are merged
18936 * with corresponding parent IDC node-tables (bubbling).
18937 *
18938 * Returns 0 if succeeded, -1 on internal errors.
18939 */
18940static int
18941xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
18942 xmlSchemaPSVIIDCNodePtr item)
18943{
18944 /*
18945 * Add to gobal list.
18946 */
18947 if (vctxt->idcNodes == NULL) {
18948 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18949 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18950 if (vctxt->idcNodes == NULL) {
18951 xmlSchemaVErrMemory(vctxt,
18952 "allocating the IDC node table item list", NULL);
18953 return (-1);
18954 }
18955 vctxt->sizeIdcNodes = 20;
18956 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18957 vctxt->sizeIdcNodes *= 2;
18958 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18959 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
18960 sizeof(xmlSchemaPSVIIDCNodePtr));
18961 if (vctxt->idcNodes == NULL) {
18962 xmlSchemaVErrMemory(vctxt,
18963 "re-allocating the IDC node table item list", NULL);
18964 return (-1);
18965 }
18966 }
18967 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
18968
18969 return (0);
18970}
18971
18972/**
18973 * xmlSchemaIDCStoreKey:
18974 * @vctxt: the WXS validation context
18975 * @item: the IDC key
18976 *
18977 * The validation context is used to store an IDC key.
18978 *
18979 * Returns 0 if succeeded, -1 on internal errors.
18980 */
18981static int
18982xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
18983 xmlSchemaPSVIIDCKeyPtr key)
18984{
18985 /*
18986 * Add to gobal list.
18987 */
18988 if (vctxt->idcKeys == NULL) {
18989 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18990 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18991 if (vctxt->idcKeys == NULL) {
18992 xmlSchemaVErrMemory(vctxt,
18993 "allocating the IDC key storage list", NULL);
18994 return (-1);
18995 }
18996 vctxt->sizeIdcKeys = 40;
18997 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18998 vctxt->sizeIdcKeys *= 2;
18999 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
19000 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
19001 sizeof(xmlSchemaPSVIIDCKeyPtr));
19002 if (vctxt->idcKeys == NULL) {
19003 xmlSchemaVErrMemory(vctxt,
19004 "re-allocating the IDC key storage list", NULL);
19005 return (-1);
19006 }
19007 }
19008 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
19009
19010 return (0);
19011}
19012
19013/**
19014 * xmlSchemaIDCAppendNodeTableItem:
19015 * @bind: the IDC binding
19016 * @ntItem: the node-table item
19017 *
19018 * Appends the IDC node-table item to the binding.
19019 *
19020 * Returns 0 on success and -1 on internal errors.
19021 */
19022static int
19023xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
19024 xmlSchemaPSVIIDCNodePtr ntItem)
19025{
19026 if (bind->nodeTable == NULL) {
19027 bind->sizeNodes = 10;
19028 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19029 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
19030 if (bind->nodeTable == NULL) {
19031 xmlSchemaVErrMemory(NULL,
19032 "allocating an array of IDC node-table items", NULL);
19033 return(-1);
19034 }
19035 } else if (bind->sizeNodes <= bind->nbNodes) {
19036 bind->sizeNodes *= 2;
19037 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19038 xmlRealloc(bind->nodeTable, bind->sizeNodes *
19039 sizeof(xmlSchemaPSVIIDCNodePtr));
19040 if (bind->nodeTable == NULL) {
19041 xmlSchemaVErrMemory(NULL,
19042 "re-allocating an array of IDC node-table items", NULL);
19043 return(-1);
19044 }
19045 }
19046 bind->nodeTable[bind->nbNodes++] = ntItem;
19047 return(0);
19048}
19049
19050/**
19051 * xmlSchemaIDCAquireBinding:
19052 * @vctxt: the WXS validation context
19053 * @matcher: the IDC matcher
19054 *
19055 * Looks up an PSVI IDC binding, for the IDC definition and
19056 * of the given matcher. If none found, a new one is created
19057 * and added to the IDC table.
19058 *
19059 * Returns an IDC binding or NULL on internal errors.
19060 */
19061static xmlSchemaPSVIIDCBindingPtr
19062xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
19063 xmlSchemaIDCMatcherPtr matcher)
19064{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019065 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019066
19067 info = vctxt->elemInfos[matcher->depth];
19068
19069 if (info->idcTable == NULL) {
19070 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
19071 if (info->idcTable == NULL)
19072 return (NULL);
19073 return(info->idcTable);
19074 } else {
19075 xmlSchemaPSVIIDCBindingPtr bind = NULL;
19076
19077 bind = info->idcTable;
19078 do {
19079 if (bind->definition == matcher->aidc->def)
19080 return(bind);
19081 if (bind->next == NULL) {
19082 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
19083 if (bind->next == NULL)
19084 return (NULL);
19085 return(bind->next);
19086 }
19087 bind = bind->next;
19088 } while (bind != NULL);
19089 }
19090 return (NULL);
19091}
19092
19093/**
19094 * xmlSchemaIDCFreeKey:
19095 * @key: the IDC key
19096 *
19097 * Frees an IDC key together with its compiled value.
19098 */
19099static void
19100xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
19101{
19102 if (key->compValue != NULL)
19103 xmlSchemaFreeValue(key->compValue);
19104 xmlFree(key);
19105}
19106
19107/**
19108 * xmlSchemaIDCFreeBinding:
19109 *
19110 * Frees an IDC binding. Note that the node table-items
19111 * are not freed.
19112 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019113static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019114xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
19115{
19116 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019117 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19118 int i;
19119 /*
19120 * Node-table items for keyrefs are not stored globally
19121 * to the validation context, since they are not bubbled.
19122 * We need to free them here.
19123 */
19124 for (i = 0; i < bind->nbNodes; i++) {
19125 xmlFree(bind->nodeTable[i]->keys);
19126 xmlFree(bind->nodeTable[i]);
19127 }
19128 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019129 xmlFree(bind->nodeTable);
19130 }
19131 xmlFree(bind);
19132}
19133
19134/**
19135 * xmlSchemaIDCFreeIDCTable:
19136 * @bind: the first IDC binding in the list
19137 *
19138 * Frees an IDC table, i.e. all the IDC bindings in the list.
19139 */
19140static void
19141xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
19142{
19143 xmlSchemaPSVIIDCBindingPtr prev;
19144
19145 while (bind != NULL) {
19146 prev = bind;
19147 bind = bind->next;
19148 xmlSchemaIDCFreeBinding(prev);
19149 }
19150}
19151
19152/**
19153 * xmlSchemaIDCFreeMatcherList:
19154 * @matcher: the first IDC matcher in the list
19155 *
19156 * Frees a list of IDC matchers.
19157 */
19158static void
19159xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
19160{
19161 xmlSchemaIDCMatcherPtr next;
19162
19163 while (matcher != NULL) {
19164 next = matcher->next;
19165 if (matcher->keySeqs != NULL) {
19166 int i;
19167 for (i = 0; i < matcher->sizeKeySeqs; i++)
19168 if (matcher->keySeqs[i] != NULL)
19169 xmlFree(matcher->keySeqs[i]);
19170 xmlFree(matcher->keySeqs);
19171 }
19172 xmlFree(matcher);
19173 matcher = next;
19174 }
19175}
19176
19177/**
19178 * xmlSchemaAreValuesEqual:
19179 * @ta: the first type
19180 * @a: the first value
19181 * @tb: the second type
19182 * @b: the second value
19183 *
19184 * Compares two values.
19185 *
19186 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
19187 */
19188static int
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019189xmlSchemaAreValuesEqual(xmlSchemaValidCtxtPtr vctxt,
19190 xmlSchemaTypePtr ta,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019191 xmlSchemaValPtr a,
19192 xmlSchemaTypePtr tb,
19193 xmlSchemaValPtr b)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019194{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019195 /* Same user derived/built-in derived/built-in primitive types. */
19196 if (ta == tb)
19197 goto compareValue;
19198
19199 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019200 * Note that comparison with anySimpleTypes with be supported for
19201 * string based types as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019202 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019203#if 0
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019204 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
19205 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
19206 return(0);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019207#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019208
19209 /*
19210 * 4.2.1 equal (data-types)
19211 *
19212 * the ·value space·s of all ·primitive· datatypes are disjoint
19213 * (they do not share any values)
19214 */
19215 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
19216 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
19217 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
19218 return(0);
19219
19220 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
19221 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
19222 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
19223 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
19224 TODO
19225 return(0);
19226 }
19227 /*
19228 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
19229 * T then the ·value space· of T' is a subset of the ·value space· of T.
19230 */
19231 /*
19232 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
19233 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
19234 */
19235
19236 {
19237 xmlSchemaTypePtr pta = ta, ptb = tb;
19238
19239 /* Note that we will compare the primitives here. */
19240 while ((pta->builtInType == 0) ||
19241 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
19242 pta = pta->baseType;
19243 while ((ptb->builtInType == 0) ||
19244 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
19245 ptb = ptb->baseType;
19246 if (pta == ptb)
19247 goto compareValue;
19248 return(0);
19249 }
19250compareValue:
19251 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019252 int ret;
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019253 int aws, bws;
19254
19255 aws = xmlSchemaGetWhiteSpaceFacetValue(ta);
19256 bws = xmlSchemaGetWhiteSpaceFacetValue(tb);
19257
19258 ret = xmlSchemaCompareValuesWhtsp(
19259 a, (xmlSchemaWhitespaceValueType) aws,
19260 b, (xmlSchemaWhitespaceValueType) bws);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019261 if (ret == 0)
19262 return(1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019263 else if (ret == -2) {
19264 xmlSchemaVErr(vctxt, vctxt->node,
19265 XML_SCHEMAV_INTERNAL,
19266 "Internal error: xmlSchemaAreValuesEqual, "
19267 "failed to compare the values.\n",
19268 NULL, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019269 return(-1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019270 } else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019271 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019272 }
19273}
19274
19275/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019276 * xmlSchemaIDCAddStateObject:
19277 * @vctxt: the WXS validation context
19278 * @matcher: the IDC matcher
19279 * @sel: the XPath information
19280 * @parent: the parent "selector" state object if any
19281 * @type: "selector" or "field"
19282 *
19283 * Creates/reuses and activates state objects for the given
19284 * XPath information; if the XPath expression consists of unions,
19285 * multiple state objects are created for every unioned expression.
19286 *
19287 * Returns 0 on success and -1 on internal errors.
19288 */
19289static int
19290xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
19291 xmlSchemaIDCMatcherPtr matcher,
19292 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019293 int type)
19294{
19295 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019296
19297 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019298 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019299 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019300 if (vctxt->xpathStatePool != NULL) {
19301 sto = vctxt->xpathStatePool;
19302 vctxt->xpathStatePool = sto->next;
19303 sto->next = NULL;
19304 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019305 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019306 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019307 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019308 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
19309 if (sto == NULL) {
19310 xmlSchemaVErrMemory(NULL,
19311 "allocating an IDC state object", NULL);
19312 return (-1);
19313 }
19314 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
19315 }
19316 /*
19317 * Add to global list.
19318 */
19319 if (vctxt->xpathStates != NULL)
19320 sto->next = vctxt->xpathStates;
19321 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019322
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019323 /*
19324 * Free the old xpath validation context.
19325 */
19326 if (sto->xpathCtxt != NULL)
19327 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
19328
19329 /*
19330 * Create a new XPath (pattern) validation context.
19331 */
19332 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
19333 (xmlPatternPtr) sel->xpathComp);
19334 if (sto->xpathCtxt == NULL) {
19335 xmlSchemaVErr(vctxt, vctxt->node,
19336 XML_SCHEMAV_INTERNAL,
19337 "Internal error: xmlSchemaIDCAddStateObject, "
19338 "failed to create the XPath validation context.\n",
19339 NULL, NULL);
19340 return (-1);
19341 }
19342 sto->type = type;
19343 sto->depth = vctxt->depth;
19344 sto->matcher = matcher;
19345 sto->sel = sel;
19346 sto->nbHistory = 0;
19347
19348#if DEBUG_IDC
19349 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
19350 sto->sel->xpath);
19351#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019352 return (0);
19353}
19354
19355/**
19356 * xmlSchemaXPathEvaluate:
19357 * @vctxt: the WXS validation context
19358 * @nodeType: the nodeType of the current node
19359 *
19360 * Evaluates all active XPath state objects.
19361 *
19362 * Returns the number of IC "field" state objects which resolved to
19363 * this node, 0 if none resolved and -1 on internal errors.
19364 */
19365static int
19366xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019367 xmlElementType nodeType)
19368{
19369 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019370 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019371
19372 if (vctxt->xpathStates == NULL)
19373 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019374
19375 if (nodeType == XML_ATTRIBUTE_NODE)
19376 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019377#if DEBUG_IDC
19378 {
19379 xmlChar *str = NULL;
19380 xmlGenericError(xmlGenericErrorContext,
19381 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019382 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
19383 vctxt->nodeInfo->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019384 FREE_AND_NULL(str)
19385 }
19386#endif
19387 /*
19388 * Process all active XPath state objects.
19389 */
19390 first = vctxt->xpathStates;
19391 sto = first;
19392 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019393#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019394 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019395 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
19396 sto->matcher->aidc->def->name, sto->sel->xpath);
19397 else
19398 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
19399 sto->matcher->aidc->def->name, sto->sel->xpath);
19400#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019401 if (nodeType == XML_ELEMENT_NODE)
19402 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
19403 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
19404 else
19405 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
19406 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
19407
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019408 if (res == -1) {
19409 xmlSchemaVErr(vctxt, vctxt->node,
19410 XML_SCHEMAV_INTERNAL,
19411 "Internal error: xmlSchemaXPathEvaluate, "
19412 "failed to evaluate a node.\n",
19413 NULL, NULL);
19414 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019415 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019416 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019417 goto next_sto;
19418 /*
19419 * Full match.
19420 */
19421#if DEBUG_IDC
19422 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019423 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019424#endif
19425 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019426 * Register a match in the state object history.
19427 */
19428 if (sto->history == NULL) {
19429 sto->history = (int *) xmlMalloc(5 * sizeof(int));
19430 if (sto->history == NULL) {
19431 xmlSchemaVErrMemory(NULL,
19432 "allocating the state object history", NULL);
19433 return(-1);
19434 }
19435 sto->sizeHistory = 10;
19436 } else if (sto->sizeHistory <= sto->nbHistory) {
19437 sto->sizeHistory *= 2;
19438 sto->history = (int *) xmlRealloc(sto->history,
19439 sto->sizeHistory * sizeof(int));
19440 if (sto->history == NULL) {
19441 xmlSchemaVErrMemory(NULL,
19442 "re-allocating the state object history", NULL);
19443 return(-1);
19444 }
19445 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019446 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019447
19448#ifdef DEBUG_IDC
19449 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
19450 vctxt->depth);
19451#endif
19452
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019453 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
19454 xmlSchemaIDCSelectPtr sel;
19455 /*
19456 * Activate state objects for the IDC fields of
19457 * the IDC selector.
19458 */
19459#if DEBUG_IDC
19460 xmlGenericError(xmlGenericErrorContext, "IDC: "
19461 "activating field states\n");
19462#endif
19463 sel = sto->matcher->aidc->def->fields;
19464 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019465 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
19466 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
19467 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019468 sel = sel->next;
19469 }
19470 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19471 /*
19472 * An IDC key node was found.
19473 */
19474#if DEBUG_IDC
19475 xmlGenericError(xmlGenericErrorContext,
19476 "IDC: key found\n");
19477#endif
19478 /*
19479 * Notify that the character value of this node is
19480 * needed.
19481 */
19482 if (resolved == 0)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019483 vctxt->nodeInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019484 resolved++;
19485 }
19486next_sto:
19487 if (sto->next == NULL) {
19488 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019489 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019490 */
19491 head = first;
19492 sto = vctxt->xpathStates;
19493 } else
19494 sto = sto->next;
19495 }
19496 return (resolved);
19497}
19498
19499/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019500 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019501 * @vctxt: the WXS validation context
19502 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019503 * @compValue: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019504 *
19505 * Processes and pops the history items of the IDC state objects.
19506 * IDC key-sequences are validated/created on IDC bindings.
19507 *
19508 * Returns 0 on success and -1 on internal errors.
19509 */
19510static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019511xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019512 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019513{
19514 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019515 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019516 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019517 xmlSchemaTypePtr type = vctxt->nodeInfo->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019518
19519 if (vctxt->xpathStates == NULL)
19520 return (0);
19521 sto = vctxt->xpathStates;
19522
19523#if DEBUG_IDC
19524 {
19525 xmlChar *str = NULL;
19526 xmlGenericError(xmlGenericErrorContext,
19527 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019528 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
19529 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019530 FREE_AND_NULL(str)
19531 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019532#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019533 /*
19534 * Evaluate the state objects.
19535 */
19536 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019537 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019538#if DEBUG_IDC
19539 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19540 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019541#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019542 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019543 goto deregister_check;
19544
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019545 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019546
19547 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019548 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019549 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019550 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019551 sto = sto->next;
19552 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019553 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019554 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19555 if (! IS_SIMPLE_TYPE(type)) {
19556 /*
19557 * Not qualified if the field resolves to a node of non
19558 * simple type.
19559 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019560 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019561 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019562 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019563 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19564 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019565 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019566
19567 sto->nbHistory--;
19568 goto deregister_check;
19569 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019570 if ((key == NULL) && (vctxt->nodeInfo->value == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019571 /*
19572 * Failed to provide the normalized value; maby
19573 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019574 */
19575 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019576 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019577 vctxt->nodeInfo,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019578 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19579 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019580 "was either invalid or something strange happend",
19581 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019582 /*
19583 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019584 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019585 "Internal error: xmlSchemaXPathProcessHistory, "
19586 "computed value not available.\n",
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019587 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019588 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019589 sto->nbHistory--;
19590 goto deregister_check;
19591 } else {
19592 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19593 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019594 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019595
19596 /*
19597 * The key will be anchored on the matcher's list of
19598 * key-sequences. The position in this list is determined
19599 * by the target node's depth relative to the matcher's
19600 * depth of creation (i.e. the depth of the scope element).
19601 */
19602 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019603 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019604
19605 /*
19606 * Create/grow the array of key-sequences.
19607 */
19608 if (matcher->keySeqs == NULL) {
19609 if (pos > 9)
19610 matcher->sizeKeySeqs = pos * 2;
19611 else
19612 matcher->sizeKeySeqs = 10;
19613 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19614 xmlMalloc(matcher->sizeKeySeqs *
19615 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19616 if (matcher->keySeqs == NULL) {
19617 xmlSchemaVErrMemory(NULL,
19618 "allocating an array of key-sequences",
19619 NULL);
19620 return(-1);
19621 }
19622 memset(matcher->keySeqs, 0,
19623 matcher->sizeKeySeqs *
19624 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19625 } else if (pos >= matcher->sizeKeySeqs) {
19626 int i = matcher->sizeKeySeqs;
19627
19628 matcher->sizeKeySeqs *= 2;
19629 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19630 xmlRealloc(matcher->keySeqs,
19631 matcher->sizeKeySeqs *
19632 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019633 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019634 xmlSchemaVErrMemory(NULL,
19635 "reallocating an array of key-sequences",
19636 NULL);
19637 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019638 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019639 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019640 * The array needs to be NULLed.
19641 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019642 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019643 for (; i < matcher->sizeKeySeqs; i++)
19644 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019645 }
19646
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019647 /*
19648 * Get/create the key-sequence.
19649 */
19650 keySeq = matcher->keySeqs[pos];
19651 if (keySeq == NULL) {
19652 goto create_sequence;
19653 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019654 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019655 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019656 * cvc-identity-constraint:
19657 * 3 For each node in the ·target node set· all
19658 * of the {fields}, with that node as the context
19659 * node, evaluate to either an empty node-set or
19660 * a node-set with exactly one member, which must
19661 * have a simple type.
19662 *
19663 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019664 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019665 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019666 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019667 vctxt->nodeInfo,
19668 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019669 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019670 "with more than one member",
19671 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019672 sto->nbHistory--;
19673 goto deregister_check;
19674 } else {
19675 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019676 }
19677 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019678
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019679create_sequence:
19680 /*
19681 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019682 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019683 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19684 matcher->aidc->def->nbFields *
19685 sizeof(xmlSchemaPSVIIDCKeyPtr));
19686 if (keySeq == NULL) {
19687 xmlSchemaVErrMemory(NULL,
19688 "allocating an IDC key-sequence", NULL);
19689 return(-1);
19690 }
19691 memset(keySeq, 0, matcher->aidc->def->nbFields *
19692 sizeof(xmlSchemaPSVIIDCKeyPtr));
19693 matcher->keySeqs[pos] = keySeq;
19694create_key:
19695 /*
19696 * Created a key once per node only.
19697 */
19698 if (key == NULL) {
19699 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19700 sizeof(xmlSchemaPSVIIDCKey));
19701 if (key == NULL) {
19702 xmlSchemaVErrMemory(NULL,
19703 "allocating a IDC key", NULL);
19704 xmlFree(keySeq);
19705 matcher->keySeqs[pos] = NULL;
19706 return(-1);
19707 }
19708 /*
19709 * Consume the compiled value.
19710 */
19711 key->type = type;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019712 key->compValue = vctxt->nodeInfo->value;
19713 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019714 /*
19715 * Store the key in a global list.
19716 */
19717 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19718 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019719 return (-1);
19720 }
19721 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019722 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019723 }
19724 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019725
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019726 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19727 xmlSchemaPSVIIDCBindingPtr bind;
19728 xmlSchemaPSVIIDCNodePtr ntItem;
19729 xmlSchemaIDCMatcherPtr matcher;
19730 xmlSchemaIDCPtr idc;
19731 int pos, i, j, nbKeys;
19732 /*
19733 * Here we have the following scenario:
19734 * An IDC 'selector' state object resolved to a target node,
19735 * during the time this target node was in the
19736 * ancestor-or-self axis, the 'field' state object(s) looked
19737 * out for matching nodes to create a key-sequence for this
19738 * target node. Now we are back to this target node and need
19739 * to put the key-sequence, together with the target node
19740 * itself, into the node-table of the corresponding IDC
19741 * binding.
19742 */
19743 matcher = sto->matcher;
19744 idc = matcher->aidc->def;
19745 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019746 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019747 /*
19748 * Check if the matcher has any key-sequences at all, plus
19749 * if it has a key-sequence for the current target node.
19750 */
19751 if ((matcher->keySeqs == NULL) ||
19752 (matcher->sizeKeySeqs <= pos)) {
19753 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19754 goto selector_key_error;
19755 else
19756 goto selector_leave;
19757 }
19758
19759 keySeq = &(matcher->keySeqs[pos]);
19760 if (*keySeq == NULL) {
19761 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19762 goto selector_key_error;
19763 else
19764 goto selector_leave;
19765 }
19766
19767 for (i = 0; i < nbKeys; i++) {
19768 if ((*keySeq)[i] == NULL) {
19769 /*
19770 * Not qualified, if not all fields did resolve.
19771 */
19772 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19773 /*
19774 * All fields of a "key" IDC must resolve.
19775 */
19776 goto selector_key_error;
19777 }
19778 goto selector_leave;
19779 }
19780 }
19781 /*
19782 * All fields did resolve.
19783 */
19784
19785 /*
19786 * 4.1 If the {identity-constraint category} is unique(/key),
19787 * then no two members of the ·qualified node set· have
19788 * ·key-sequences· whose members are pairwise equal, as
19789 * defined by Equal in [XML Schemas: Datatypes].
19790 *
19791 * Get the IDC binding from the matcher and check for
19792 * duplicate key-sequences.
19793 */
19794 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19795 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19796 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019797 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019798
19799 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019800 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019801 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019802 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019803 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019804 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019805 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019806 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019807 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019808 bkey = bkeySeq[j];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019809 res = xmlSchemaAreValuesEqual(vctxt, ckey->type,
19810 ckey->compValue, bkey->type, bkey->compValue);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019811 if (res == -1) {
19812 return (-1);
19813 } else if (res == 0)
19814 break;
19815 }
19816 if (res == 1) {
19817 /*
19818 * Duplicate found.
19819 */
19820 break;
19821 }
19822 i++;
19823 } while (i < bind->nbNodes);
19824 if (i != bind->nbNodes) {
19825 /*
19826 * TODO: Try to report the key-sequence.
19827 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019828 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019829 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019830 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019831 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019832 "Duplicate key-sequence found", NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019833
19834 goto selector_leave;
19835 }
19836 }
19837 /*
19838 * Add a node-table item to the IDC binding.
19839 */
19840 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19841 sizeof(xmlSchemaPSVIIDCNode));
19842 if (ntItem == NULL) {
19843 xmlSchemaVErrMemory(NULL,
19844 "allocating an IDC node-table item", NULL);
19845 xmlFree(*keySeq);
19846 *keySeq = NULL;
19847 return(-1);
19848 }
19849 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19850
19851 /*
19852 * Store the node-table item on global list.
19853 */
19854 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19855 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19856 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019857 xmlFree(*keySeq);
19858 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019859 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019860 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019861 }
19862 /*
19863 * Init the node-table item. Consume the key-sequence.
19864 */
19865 ntItem->node = vctxt->node;
19866 ntItem->keys = *keySeq;
19867 *keySeq = NULL;
19868 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19869 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19870 /*
19871 * Free the item, since keyref items won't be
19872 * put on a global list.
19873 */
19874 xmlFree(ntItem->keys);
19875 xmlFree(ntItem);
19876 }
19877 return (-1);
19878 }
19879
19880 goto selector_leave;
19881selector_key_error:
19882 /*
19883 * 4.2.1 (KEY) The ·target node set· and the
19884 * ·qualified node set· are equal, that is, every
19885 * member of the ·target node set· is also a member
19886 * of the ·qualified node set· and vice versa.
19887 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019888 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019889 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019890 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019891 (xmlSchemaTypePtr) idc,
19892 "All 'key' fields must evaluate to a node",
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019893 NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019894selector_leave:
19895 /*
19896 * Free the key-sequence if not added to the IDC table.
19897 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019898 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019899 xmlFree(*keySeq);
19900 *keySeq = NULL;
19901 }
19902 } /* if selector */
19903
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019904 sto->nbHistory--;
19905
19906deregister_check:
19907 /*
19908 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019909 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019910 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019911#if DEBUG_IDC
19912 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19913 sto->sel->xpath);
19914#endif
19915 if (vctxt->xpathStates != sto) {
19916 xmlSchemaVErr(vctxt, vctxt->node,
19917 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019918 "Internal error: xmlSchemaXPathProcessHistory, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019919 "The state object to be removed is not the first "
19920 "in the list.\n",
19921 NULL, NULL);
19922 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019923 nextsto = sto->next;
19924 /*
19925 * Unlink from the list of active XPath state objects.
19926 */
19927 vctxt->xpathStates = sto->next;
19928 sto->next = vctxt->xpathStatePool;
19929 /*
19930 * Link it to the pool of reusable state objects.
19931 */
19932 vctxt->xpathStatePool = sto;
19933 sto = nextsto;
19934 } else
19935 sto = sto->next;
19936 } /* while (sto != NULL) */
19937 return (0);
19938}
19939
19940/**
19941 * xmlSchemaIDCRegisterMatchers:
19942 * @vctxt: the WXS validation context
19943 * @elemDecl: the element declaration
19944 *
19945 * Creates helper objects to evaluate IDC selectors/fields
19946 * successively.
19947 *
19948 * Returns 0 if OK and -1 on internal errors.
19949 */
19950static int
19951xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19952 xmlSchemaElementPtr elemDecl)
19953{
19954 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19955 xmlSchemaIDCPtr idc, refIdc;
19956 xmlSchemaIDCAugPtr aidc;
19957
19958 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19959 if (idc == NULL)
19960 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019961
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019962#if DEBUG_IDC
19963 {
19964 xmlChar *str = NULL;
19965 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019966 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019967 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
19968 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019969 FREE_AND_NULL(str)
19970 }
19971#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019972 if (vctxt->nodeInfo->idcMatchers != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019973 xmlSchemaVErr(vctxt, vctxt->node,
19974 XML_SCHEMAV_INTERNAL,
19975 "Internal error: xmlSchemaIDCRegisterMatchers: "
19976 "The chain of IDC matchers is expected to be empty.\n",
19977 NULL, NULL);
19978 return (-1);
19979 }
19980 do {
19981 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19982 /*
19983 * Since IDCs bubbles are expensive we need to know the
19984 * depth at which the bubbles should stop; this will be
19985 * the depth of the top-most keyref IDC. If no keyref
19986 * references a key/unique IDC, the bubbleDepth will
19987 * be -1, indicating that no bubbles are needed.
19988 */
19989 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19990 if (refIdc != NULL) {
19991 /*
19992 * Lookup the augmented IDC.
19993 */
19994 aidc = vctxt->aidcs;
19995 while (aidc != NULL) {
19996 if (aidc->def == refIdc)
19997 break;
19998 aidc = aidc->next;
19999 }
20000 if (aidc == NULL) {
20001 xmlSchemaVErr(vctxt, vctxt->node,
20002 XML_SCHEMAV_INTERNAL,
20003 "Internal error: xmlSchemaIDCRegisterMatchers: "
20004 "Could not find an augmented IDC item for an IDC "
20005 "definition.\n",
20006 NULL, NULL);
20007 return (-1);
20008 }
20009 if ((aidc->bubbleDepth == -1) ||
20010 (vctxt->depth < aidc->bubbleDepth))
20011 aidc->bubbleDepth = vctxt->depth;
20012 }
20013 }
20014 /*
20015 * Lookup the augmented IDC item for the IDC definition.
20016 */
20017 aidc = vctxt->aidcs;
20018 while (aidc != NULL) {
20019 if (aidc->def == idc)
20020 break;
20021 aidc = aidc->next;
20022 }
20023 if (aidc == NULL) {
20024 xmlSchemaVErr(vctxt, vctxt->node,
20025 XML_SCHEMAV_INTERNAL,
20026 "Internal error: xmlSchemaIDCRegisterMatchers: "
20027 "Could not find an augmented IDC item for an IDC definition.\n",
20028 NULL, NULL);
20029 return (-1);
20030 }
20031 /*
20032 * Create an IDC matcher for every IDC definition.
20033 */
20034 matcher = (xmlSchemaIDCMatcherPtr)
20035 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
20036 if (matcher == NULL) {
20037 xmlSchemaVErrMemory(vctxt,
20038 "allocating an IDC matcher", NULL);
20039 return (-1);
20040 }
20041 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
20042 if (last == NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020043 vctxt->nodeInfo->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020044 else
20045 last->next = matcher;
20046 last = matcher;
20047
20048 matcher->type = IDC_MATCHER;
20049 matcher->depth = vctxt->depth;
20050 matcher->aidc = aidc;
20051#if DEBUG_IDC
20052 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
20053#endif
20054 /*
20055 * Init the automaton state object.
20056 */
20057 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020058 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020059 return (-1);
20060
20061 idc = idc->next;
20062 } while (idc != NULL);
20063 return (0);
20064}
20065
20066/**
20067 * xmlSchemaBubbleIDCNodeTables:
20068 * @depth: the current tree depth
20069 *
20070 * Merges IDC bindings of an element at @depth into the corresponding IDC
20071 * bindings of its parent element. If a duplicate note-table entry is found,
20072 * both, the parent node-table entry and child entry are discarded from the
20073 * node-table of the parent.
20074 *
20075 * Returns 0 if OK and -1 on internal errors.
20076 */
20077static int
20078xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
20079{
20080 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020081 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
20082 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020083 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
20084 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020085 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020086 int duplTop;
20087
20088 /*
20089 * The node table has the following sections:
20090 *
20091 * O --> old node-table entries (first)
20092 * O
20093 * + --> new node-table entries
20094 * +
20095 * % --> new duplicate node-table entries
20096 * %
20097 * # --> old duplicate node-table entries
20098 * # (last)
20099 *
20100 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020101 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020102 if (bind == NULL) {
20103 /* Fine, no table, no bubbles. */
20104 return (0);
20105 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020106
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020107 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
20108 /*
20109 * Walk all bindings; create new or add to existing bindings.
20110 * Remove duplicate key-sequences.
20111 */
20112start_binding:
20113 while (bind != NULL) {
20114 /*
20115 * Skip keyref IDCs.
20116 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020117 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20118 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020119 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020120 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020121 /*
20122 * Check if the key/unique IDC table needs to be bubbled.
20123 */
20124 aidc = vctxt->aidcs;
20125 do {
20126 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020127 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020128 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020129 bind = bind->next;
20130 goto start_binding;
20131 }
20132 break;
20133 }
20134 aidc = aidc->next;
20135 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020136
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020137 if (parTable != NULL)
20138 parBind = *parTable;
20139 while (parBind != NULL) {
20140 /*
20141 * Search a matching parent binding for the
20142 * IDC definition.
20143 */
20144 if (parBind->definition == bind->definition) {
20145
20146 /*
20147 * Compare every node-table entry of the child node,
20148 * i.e. the key-sequence within, ...
20149 */
20150 oldNum = parBind->nbNodes; /* Skip newly added items. */
20151 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020152 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020153
20154 for (i = 0; i < bind->nbNodes; i++) {
20155 node = bind->nodeTable[i];
20156 if (node == NULL)
20157 continue;
20158 /*
20159 * ...with every key-sequence of the parent node, already
20160 * evaluated to be a duplicate key-sequence.
20161 */
20162 if (parBind->nbDupls != 0) {
20163 j = bind->nbNodes + newDupls;
20164 while (j < duplTop) {
20165 parNode = parBind->nodeTable[j];
20166 for (k = 0; k < bind->definition->nbFields; k++) {
20167 key = node->keys[k];
20168 parKey = parNode->keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020169 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020170 key->compValue,
20171 parKey->type, parKey->compValue);
20172 if (ret == -1) {
20173 /* TODO: Internal error */
20174 return(-1);
20175 } else if (ret == 0)
20176 break;
20177
20178 }
20179 if (ret == 1)
20180 /* Duplicate found. */
20181 break;
20182 j++;
20183 }
20184 if (j != duplTop) {
20185 /* Duplicate found. */
20186 continue;
20187 }
20188 }
20189 /*
20190 * ... and with every key-sequence of the parent node.
20191 */
20192 j = 0;
20193 while (j < oldNum) {
20194 parNode = parBind->nodeTable[j];
20195 /*
20196 * Compare key by key.
20197 */
20198 for (k = 0; k < parBind->definition->nbFields; k++) {
20199 key = node->keys[k];
20200 parKey = parNode->keys[k];
20201
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020202 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020203 key->compValue,
20204 parKey->type, parKey->compValue);
20205 if (ret == -1) {
20206 /* TODO: Internal error */
20207 } else if (ret == 0)
20208 break;
20209
20210 }
20211 if (ret == 1)
20212 /*
20213 * The key-sequences are equal.
20214 */
20215 break;
20216 j++;
20217 }
20218 if (j != oldNum) {
20219 /*
20220 * Handle duplicates.
20221 */
20222 newDupls++;
20223 oldNum--;
20224 parBind->nbNodes--;
20225 /*
20226 * Move last old item to pos of duplicate.
20227 */
20228 parBind->nodeTable[j] =
20229 parBind->nodeTable[oldNum];
20230
20231 if (parBind->nbNodes != oldNum) {
20232 /*
20233 * If new items exist, move last new item to
20234 * last of old items.
20235 */
20236 parBind->nodeTable[oldNum] =
20237 parBind->nodeTable[parBind->nbNodes];
20238 }
20239 /*
20240 * Move duplicate to last pos of new/old items.
20241 */
20242 parBind->nodeTable[parBind->nbNodes] = parNode;
20243
20244 } else {
20245 /*
20246 * Add the node-table entry (node and key-sequence) of
20247 * the child node to the node table of the parent node.
20248 */
20249 if (parBind->nodeTable == NULL) {
20250 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020251 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020252 if (parBind->nodeTable == NULL) {
20253 xmlSchemaVErrMemory(NULL,
20254 "allocating IDC list of node-table items", NULL);
20255 return(-1);
20256 }
20257 parBind->sizeNodes = 1;
20258 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020259 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020260 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
20261 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
20262 sizeof(xmlSchemaPSVIIDCNodePtr));
20263 if (parBind->nodeTable == NULL) {
20264 xmlSchemaVErrMemory(NULL,
20265 "re-allocating IDC list of node-table items", NULL);
20266 return(-1);
20267 }
20268 }
20269
20270 /*
20271 * Move first old duplicate to last position
20272 * of old duplicates +1.
20273 */
20274 if (parBind->nbDupls != 0) {
20275 parBind->nodeTable[duplTop] =
20276 parBind->nodeTable[parBind->nbNodes + newDupls];
20277 }
20278 /*
20279 * Move first new duplicate to last position of
20280 * new duplicates +1.
20281 */
20282 if (newDupls != 0) {
20283 parBind->nodeTable[parBind->nbNodes + newDupls] =
20284 parBind->nodeTable[parBind->nbNodes];
20285 }
20286 /*
20287 * Append the new node-table entry to the 'new node-table
20288 * entries' section.
20289 */
20290 parBind->nodeTable[parBind->nbNodes] = node;
20291 parBind->nbNodes++;
20292 duplTop++;
20293 }
20294 }
20295 parBind->nbDupls += newDupls;
20296 break;
20297 }
20298 if (parBind->next == NULL)
20299 lastParBind = parBind;
20300 parBind = parBind->next;
20301 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020302 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020303 /*
20304 * No binding for the IDC was found: create a new one and
20305 * copy all node-tables.
20306 */
20307 parBind = xmlSchemaIDCNewBinding(bind->definition);
20308 if (parBind == NULL)
20309 return(-1);
20310
20311 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
20312 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
20313 if (parBind->nodeTable == NULL) {
20314 xmlSchemaVErrMemory(NULL,
20315 "allocating an array of IDC node-table items", NULL);
20316 xmlSchemaIDCFreeBinding(parBind);
20317 return(-1);
20318 }
20319 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020320 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020321 memcpy(parBind->nodeTable, bind->nodeTable,
20322 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020323 if (*parTable == NULL)
20324 *parTable = parBind;
20325 else
20326 lastParBind->next = parBind;
20327 }
20328 bind = bind->next;
20329 }
20330 return (0);
20331}
20332
20333/**
20334 * xmlSchemaCheckCVCIDCKeyRef:
20335 * @vctxt: the WXS validation context
20336 * @elemDecl: the element declaration
20337 *
20338 * Check the cvc-idc-keyref constraints.
20339 */
20340static int
20341xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
20342{
20343 xmlSchemaPSVIIDCBindingPtr refbind, bind;
20344
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020345 refbind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020346 /*
20347 * Find a keyref.
20348 */
20349 while (refbind != NULL) {
20350 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20351 int i, j, k, res;
20352 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
20353 xmlSchemaPSVIIDCKeyPtr refKey, key;
20354
20355 /*
20356 * Find the referred key/unique.
20357 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020358 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020359 do {
20360 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
20361 bind->definition)
20362 break;
20363 bind = bind->next;
20364 } while (bind != NULL);
20365
20366 /*
20367 * Search for a matching key-sequences.
20368 */
20369 for (i = 0; i < refbind->nbNodes; i++) {
20370 res = 0;
20371 if (bind != NULL) {
20372 refKeys = refbind->nodeTable[i]->keys;
20373 for (j = 0; j < bind->nbNodes; j++) {
20374 keys = bind->nodeTable[j]->keys;
20375 for (k = 0; k < bind->definition->nbFields; k++) {
20376 refKey = refKeys[k];
20377 key = keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020378 res = xmlSchemaAreValuesEqual(vctxt,
20379 key->type, key->compValue,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020380 refKey->type, refKey->compValue);
20381 if (res == 0)
20382 break;
20383 else if (res == -1) {
20384 return (-1);
20385 }
20386 }
20387 if (res == 1) {
20388 /*
20389 * Match found.
20390 */
20391 break;
20392 }
20393 }
20394 }
20395 if (res == 0) {
20396 /* TODO: Report the key-sequence. */
20397 xmlSchemaVCustomErr(vctxt,
20398 XML_SCHEMAV_CVC_IDC,
20399 refbind->nodeTable[i]->node,
20400 (xmlSchemaTypePtr) refbind->definition,
20401 "No matching key-sequence found", NULL);
20402 }
20403 }
20404 }
20405 refbind = refbind->next;
20406 }
20407 return (0);
20408}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020409
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020410/**
20411 * xmlSchemaBeginElement:
20412 * @vctxt: the WXS validation context
20413 *
20414 * Just a temporary workaround to simulate streaming validation
20415 * a bit.
20416 */
20417static void
20418xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
20419{
20420 vctxt->depth++;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020421 vctxt->nodeInfo = xmlSchemaGetFreshElemInfo(vctxt, vctxt->depth);
20422 vctxt->nodeInfo->node = vctxt->node;
20423 vctxt->nodeInfo->localName = vctxt->node->name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020424 if (vctxt->node->ns != NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020425 vctxt->nodeInfo->namespaceName = vctxt->node->ns->href;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020426 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020427 vctxt->nodeInfo->namespaceName = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020428}
20429
20430/**
20431 * xmlSchemaEndElement:
20432 * @vctxt: the WXS validation context
20433 *
20434 * Just a temporary workaround to simulate streaming validation
20435 * a bit.
20436 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020437static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020438xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
20439{
20440 if (vctxt->depth < 0) {
20441 /* TODO: raise error? */
20442 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020443 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020444 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020445 /*
20446 * Evaluate the history of changes of active state objects.
20447 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020448 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
20449 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020450
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020451 if (vctxt->nodeInfo->value != NULL) {
20452 xmlSchemaFreeValue(vctxt->nodeInfo->value);
20453 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020454 }
20455 /*
20456 * TODO: 6 The element information item must be ·valid· with respect to each of
20457 * the {identity-constraint definitions} as per Identity-constraint
20458 * Satisfied (§3.11.4).
20459 */
20460 /*
20461 * Validate IDC keyrefs.
20462 */
20463 xmlSchemaCheckCVCIDCKeyRef(vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020464
20465 /*
20466 * Merge/free the IDC table.
20467 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020468 if (vctxt->nodeInfo->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020469#ifdef DEBUG_IDC
20470 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020471 vctxt->nodeInfo->namespaceName,
20472 vctxt->nodeInfo->localName,
20473 vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020474#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020475 if (vctxt->depth > 0) {
20476 /*
20477 * Merge the IDC node table with the table of the parent node.
20478 */
20479 xmlSchemaBubbleIDCNodeTables(vctxt);
20480 }
20481 /*
20482 * TODO: Don't free the PSVI IDC tables if they are
20483 * requested for the PSVI.
20484 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020485 xmlSchemaIDCFreeIDCTable(vctxt->nodeInfo->idcTable);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020486 vctxt->nodeInfo->idcTable = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020487 }
20488
20489 /*
20490 * Cleanup IDC matchers.
20491 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020492 if (vctxt->nodeInfo->idcMatchers != NULL) {
20493 xmlSchemaIDCFreeMatcherList(vctxt->nodeInfo->idcMatchers);
20494 vctxt->nodeInfo->idcMatchers = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020495 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020496
20497 /*
20498 * Skip further processing if we are on the validation root.
20499 */
20500 if (vctxt->depth == 0) {
20501 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020502 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020503 }
20504
20505 /*
20506 * Reset the bubbleDepth if needed.
20507 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020508 if (vctxt->aidcs != NULL) {
20509 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
20510 do {
20511 if (aidc->bubbleDepth == vctxt->depth) {
20512 /*
20513 * A bubbleDepth of a key/unique IDC matches the current
20514 * depth, this means that we are leaving the scope of the
20515 * top-most keyref IDC.
20516 */
20517 aidc->bubbleDepth = -1;
20518 }
20519 aidc = aidc->next;
20520 } while (aidc != NULL);
20521 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020522 vctxt->depth--;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020523 /*
20524 * Clear the current elemInfo.
20525 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020526 if (vctxt->nodeInfo->value != NULL) {
20527 xmlSchemaFreeValue(vctxt->nodeInfo->value);
20528 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020529 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020530 vctxt->nodeInfo = vctxt->elemInfos[vctxt->depth];
20531 vctxt->node = vctxt->nodeInfo->node;
20532
20533 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020534}
20535
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020536/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020537 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000020538 * @ctxt: a schema validation context
20539 * @node: the top node.
20540 *
20541 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020542 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000020543 *
20544 * Returns 0 if the element is schemas valid, a positive error code
20545 * number otherwise and -1 in case of internal or API error.
20546 */
20547static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020548xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
20549 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020550{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020551 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020552 int ret = 0;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020553 xmlSchemaTypePtr actualType = NULL, localType = NULL, type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020554 xmlAttrPtr attr;
20555 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020556 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000020557
20558 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020559 * This one is called by xmlSchemaValidateElementByWildcardInternal,
20560 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020561 * Note that @elemDecl will be the declaration and never the
20562 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020563 */
Daniel Veillard3646d642004-06-02 19:19:14 +000020564
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020565 if (ctxt == NULL) {
20566 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
20567 "Internal error: xmlSchemaValidateElementByDeclaration, "
20568 "bad arguments.\n",
20569 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020570 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020571 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020572
20573 elem = ctxt->node;
20574
20575 /*
20576 * cvc-elt (3.3.4) : 1
20577 */
20578 if (elemDecl == NULL) {
20579 xmlSchemaVCustomErr(ctxt,
20580 XML_SCHEMAV_CVC_ELT_1,
20581 elem, NULL,
20582 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020583 /*
20584 * Evaluate IDCs even if an error occured.
20585 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020586 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020587 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020588 return (ctxt->err);
20589 }
20590 /*
20591 * cvc-elt (3.3.4) : 2
20592 */
20593 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
20594 xmlSchemaVCustomErr(ctxt,
20595 XML_SCHEMAV_CVC_ELT_2,
20596 elem, NULL,
20597 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020598 /*
20599 * Evaluate IDCs even if an error occured.
20600 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020601 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020602 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020603 return (ctxt->err);
20604 }
20605
20606 /*
20607 * cvc-elt (3.3.4) : 3
20608 * Handle 'xsi:nil'.
20609 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020610
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020611 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020612 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020613 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
20614 ctxt->node = (xmlNodePtr) attr;
20615 ctxt->cur = attr->children;
20616 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
20617 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
20618 BAD_CAST attrValue, 1, 1, 1, 1);
20619 ctxt->node = elem;
20620 ctxt->type = (xmlSchemaTypePtr) elemDecl;
20621 if (ret < 0) {
20622 xmlSchemaVCustomErr(ctxt,
20623 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020624 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020625 "Internal error: xmlSchemaValidateElementByDeclaration, "
20626 "validating the attribute 'xsi:nil'", NULL);
20627 if (attrValue != NULL)
20628 xmlFree(attrValue);
20629 return (-1);
20630 }
20631 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020632 /*
20633 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020634 */
20635 xmlSchemaVCustomErr(ctxt,
20636 XML_SCHEMAV_CVC_ELT_3_1,
20637 elem, NULL,
20638 "The element is not 'nillable'", NULL);
20639 } else {
20640 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020641 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020642 ret = 0;
20643 /*
20644 * cvc-elt (3.3.4) : 3.2.1
20645 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020646 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
20647 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020648 xmlSchemaVCustomErr(ctxt,
20649 XML_SCHEMAV_CVC_ELT_3_2_1,
20650 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020651 elem, (xmlSchemaTypePtr) elemDecl,
20652 "The 'nilled' element must have no character or "
20653 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020654 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
20655 }
20656 /*
20657 * cvc-elt (3.3.4) : 3.2.2
20658 */
20659 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
20660 (elemDecl->value != NULL)) {
20661 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
20662 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020663 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020664 "There is a fixed value constraint defined for "
20665 "the 'nilled' element", NULL);
20666 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
20667 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020668 if (ret == 0)
20669 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020670 }
20671 }
20672 if (attrValue != NULL)
20673 xmlFree(attrValue);
20674 }
20675
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020676 type = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020677 actualType = type;
20678
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020679 /*
20680 * cvc-elt (3.3.4) : 4
20681 * Handle 'xsi:type'.
20682 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020683
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020684 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
20685 if (attr != NULL) {
20686 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020687
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020688 /*
20689 * TODO: We should report a *warning* that the type was overriden
20690 * by the instance.
20691 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020692
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020693 /*
20694 * cvc-elt (3.3.4) : 4.1
20695 */
20696 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
20697 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
20698 &nsName, &local);
20699 if (ret < 0) {
20700 xmlSchemaVCustomErr(ctxt,
20701 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020702 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020703 "Internal error: xmlSchemaValidateElementByDeclaration, "
20704 "validating the attribute 'xsi:type'", NULL);;
20705 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020706 FREE_AND_NULL(nsName)
20707 FREE_AND_NULL(local)
20708 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020709 } else if (ret == 1) {
20710 xmlSchemaVSimpleTypeErr(ctxt,
20711 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
20712 (xmlNodePtr) attr, attrValue,
20713 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
20714 } else if (ret == 2) {
20715 xmlSchemaVCustomErr(ctxt,
20716 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
20717 (xmlNodePtr) attr,
20718 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20719 "The QName value '%s' has no "
20720 "corresponding namespace declaration in scope",
20721 attrValue);
20722 } else {
20723 /*
20724 * cvc-elt (3.3.4) : 4.2
20725 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020726 localType = xmlSchemaGetType(ctxt->schema, local, nsName);
20727 if (localType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020728 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020729
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020730 xmlSchemaVCustomErr(ctxt,
20731 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020732 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020733 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020734 "The value '%s' of the xsi:type attribute does not "
20735 "resolve to a type definition",
20736 xmlSchemaFormatQName(&strA, nsName, local));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020737 FREE_AND_NULL(strA);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020738 } else {
20739 int set = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020740 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020741 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
20742 * "The ·local type definition· must be validly
20743 * derived from the {type definition} given the union of
20744 * the {disallowed substitutions} and the {type definition}'s
20745 * {prohibited substitutions}, as defined in
20746 * Type Derivation OK (Complex) (§3.4.6)
20747 * (if it is a complex type definition),
20748 * or given {disallowed substitutions} as defined in Type
20749 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
20750 * definition)."
20751 *
20752 * {disallowed substitutions}: the "block" on the element decl.
20753 * {prohibited substitutions}: the "block" on the type def.
20754 */
20755 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
20756 (type->flags & XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
20757 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
20758
20759 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
20760 (type->flags & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
20761 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
20762
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020763 if (xmlSchemaCheckCOSDerivedOK(ctxt->schema, localType,
20764 type, set) != 0) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020765 xmlChar *strA = NULL, *strB = NULL;
20766
20767 xmlSchemaVCustomErrExt(ctxt,
20768 /* TODO: Error code */
20769 XML_SCHEMAV_CVC_ELT_4_2, elem, localType,
20770 "The xsi:type definition '%s' is not validly derived from "
20771 "the type definition '%s'",
20772 xmlSchemaFormatQName(&strA,
20773 localType->targetNamespace,
20774 localType->name),
20775 xmlSchemaFormatQName(&strB,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020776 ELEM_TYPE(elemDecl)->targetNamespace,
20777 ELEM_TYPE(elemDecl)->name), NULL);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020778 FREE_AND_NULL(strA)
20779 FREE_AND_NULL(strB)
20780 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020781 }
20782 }
20783 FREE_AND_NULL(attrValue)
20784 FREE_AND_NULL(nsName)
20785 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020786 }
20787 /* TODO: Change the handling of missing types according to
20788 * the spec.
20789 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020790 if (localType != NULL)
20791 actualType = localType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020792 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000020793 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020794 XML_SCHEMAV_CVC_TYPE_1,
20795 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000020796 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020797 /*
20798 * Evaluate IDCs even if an error occured.
20799 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020800 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020801 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020802 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020803 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020804
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020805 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020806 * Remember the actual-type definition.
20807 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020808 ctxt->nodeInfo->typeDef = actualType;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020809
20810 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020811 * TODO: Since this should be already checked by the content model automaton,
20812 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
20813 * has been changed to XML_SCHEMAV_INTERNAL.
20814 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020815 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000020816 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020817 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020818 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020819 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020820 "Element %s: missing child %s\n",
20821 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020822 }
20823 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020824 }
20825 */
Daniel Veillard4255d502002-04-16 15:50:10 +000020826 /*
20827 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020828 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020829 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000020830 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020831 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020832 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020833 "Element %s: missing child %s found %s\n",
20834 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020835 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000020836 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020837 */
20838 if (elemHasContent == -1)
20839 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020840
20841 /*
20842 * IDC: Register identity-constraint XPath matchers.
20843 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020844 if (elemDecl->idcs != NULL)
20845 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
20846 /*
20847 * Evaluate IDCs.
20848 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020849 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020850 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020851 /*
20852 * cvc-elt (3.3.4) : 5
20853 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020854 */
Daniel Veillard4255d502002-04-16 15:50:10 +000020855 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020856 * cvc-elt (3.3.4) : 5.1
20857 * If the declaration has a {value constraint},
20858 * the item has neither element nor character [children] and
20859 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020860 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020861 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
20862 /*
20863 * cvc-elt (3.3.4) : 5.1.1
20864 * If the ·actual type definition· is a ·local type definition·
20865 * then the canonical lexical representation of the {value constraint}
20866 * value must be a valid default for the ·actual type definition· as
20867 * defined in Element Default Valid (Immediate) (§3.3.6).
20868 */
20869 /*
20870 * NOTE: 'local' above means types aquired by xsi:type.
20871 */
20872 ret = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020873 if (actualType != ELEM_TYPE(elemDecl)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020874 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
20875 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020876 elemDecl->value, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020877 if (ret < 0) {
20878 xmlSchemaVCustomErr(ctxt,
20879 XML_SCHEMAV_INTERNAL,
20880 elem, actualType,
20881 "Internal error: xmlSchemaValidateElementByDeclaration, "
20882 "validating a default value", NULL);
20883 return (-1);
20884 }
20885 }
20886 /*
20887 * cvc-elt (3.3.4) : 5.1.2
20888 * The element information item with the canonical lexical
20889 * representation of the {value constraint} value used as its
20890 * ·normalized value· must be ·valid· with respect to the
20891 * ·actual type definition· as defined by Element Locally Valid (Type)
20892 * (§3.3.4).
20893 */
20894 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020895 * Disable validation of the simple content, if it was already
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020896 * done above.
20897 */
20898 if (ret == 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000020899 if (actualType != ELEM_TYPE(elemDecl))
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020900 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020901 else
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020902 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020903 ctxt->node = elem;
20904 if (ret < 0) {
20905 xmlSchemaVCustomErr(ctxt,
20906 XML_SCHEMAV_INTERNAL,
20907 elem, actualType,
20908 "Internal error: xmlSchemaValidateElementByDeclaration, "
20909 "validating against the type", NULL);
20910 return (-1);
20911 }
20912 /*
20913 * PSVI: Create a text node on the instance element.
20914 */
20915 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
20916 xmlNodePtr textChild;
20917
20918 textChild = xmlNewText(elemDecl->value);
20919 if (textChild == NULL) {
20920 xmlSchemaVCustomErr(ctxt,
20921 XML_SCHEMAV_INTERNAL,
20922 elem, actualType,
20923 "Internal error: xmlSchemaValidateElementByDeclaration, "
20924 "could not create a default text node for the instance",
20925 NULL);
20926 } else
20927 xmlAddChild(elem, textChild);
20928 }
20929 }
20930
20931 } else {
20932 /*
20933 * 5.2.1 The element information item must be ·valid· with respect
20934 * to the ·actual type definition· as defined by Element Locally
20935 * Valid (Type) (§3.3.4).
20936 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020937 ret = xmlSchemaValidateElementByType(ctxt, actualType, nilled, 1);
20938 /*
20939 * Consume the computed value for IDCs, ect. Note that default
20940 * values are not supported yet.
20941 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020942 if (ctxt->value != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020943 ctxt->nodeInfo->value = ctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020944 ctxt->value = NULL;
20945 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020946 ctxt->node = elem;
20947 if (ret < 0) {
20948 xmlSchemaVCustomErr(ctxt,
20949 XML_SCHEMAV_INTERNAL,
20950 elem, actualType,
20951 "Internal error: xmlSchemaValidateElementByDeclaration, "
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000020952 "calling validation by type", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020953 return (-1);
20954 }
20955 /*
20956 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
20957 * not applied, all of the following must be true:
20958 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020959 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
20960 /*
20961 * 5.2.2.1 The element information item must have no element
20962 * information item [children].
20963 *
20964 * TODO REDUNDANT: If the actual type exists, the above call to
20965 * xmlSchemaValidateElementByType will already check for element
20966 * nodes.
20967 */
20968 if (xmlSchemaHasElemContent(elem)) {
20969 xmlSchemaVCustomErr(ctxt,
20970 XML_SCHEMAV_CVC_ELT_5_2_2_1,
20971 elem, (xmlSchemaTypePtr) elemDecl,
20972 "Elements in the content are not allowed if it is "
20973 "constrained by a fixed value", NULL);
20974 } else {
20975 /*
20976 * 5.2.2.2 The appropriate case among the following must
20977 * be true:
20978 */
20979
20980 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
20981 xmlChar *value;
20982 /*
20983 * 5.2.2.2.1 If the {content type} of the ·actual type
20984 * definition· is mixed, then the *initial value* of the
20985 * item must match the canonical lexical representation
20986 * of the {value constraint} value.
20987 *
20988 * ... the *initial value* of an element information
20989 * item is the string composed of, in order, the
20990 * [character code] of each character information item in
20991 * the [children] of that element information item.
20992 */
20993 value = xmlNodeListGetString(elem->doc, elem->children, 1);
20994 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
20995 /*
20996 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020997 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020998 */
20999 xmlSchemaVCustomErr(ctxt,
21000 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
21001 elem, (xmlSchemaTypePtr) elemDecl,
21002 "The value does not match the cononical "
21003 "lexical representation of the fixed constraint",
21004 NULL);
21005 }
21006 if (value != NULL)
21007 xmlFree(value);
21008 } else if ((actualType->contentType ==
21009 XML_SCHEMA_CONTENT_SIMPLE) ||
21010 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
21011 xmlChar *value;
21012
21013 /*
21014 * 5.2.2.2.2 If the {content type} of the ·actual type
21015 * definition· is a simple type definition, then the
21016 * *actual value* of the item must match the canonical
21017 * lexical representation of the {value constraint} value.
21018 */
21019 /*
21020 * TODO: *actual value* is the normalized value, impl. this.
21021 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021022 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021023 *
21024 */
21025 value = xmlNodeListGetString(elem->doc, elem->children, 1);
21026 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
21027 xmlSchemaVCustomErr(ctxt,
21028 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
21029 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021030 "The normalized value does not match the canonical "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021031 "lexical representation of the fixed constraint",
21032 NULL);
21033 }
21034 if (value != NULL)
21035 xmlFree(value);
21036
21037 }
21038 /*
21039 * TODO: What if the content type is not 'mixed' or simple?
21040 */
21041
21042 }
21043
21044 }
21045 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021046 /*
21047 * TODO: 7 If the element information item is the ·validation root·, it must be
21048 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
21049 */
21050
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021051 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000021052}
21053
Daniel Veillard4255d502002-04-16 15:50:10 +000021054/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021055 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000021056 * @ctxt: a schema validation context
21057 * @node: the top node.
21058 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021059 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
21060 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021061 *
21062 * Returns 0 if the element is valid, a positive error code
21063 * number otherwise and -1 in case of an internal error.
21064 */
21065static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021066xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
21067 xmlSchemaWildcardPtr wild,
21068 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000021069{
21070 const xmlChar *uri;
21071 int ret = 0;
21072 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021073
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021074 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021075 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
21076 if (ret == -1) {
21077 xmlSchemaVCustomErr(ctxt,
21078 XML_SCHEMAV_INTERNAL,
21079 ctxt->node, NULL,
21080 "Internal error: xmlSchemaValidateElement, "
21081 "assembling schema by xsi", NULL);
21082 return (-1);
21083 }
21084 /*
21085 * NOTE: We won't react on schema parser errors here.
21086 * TODO: But a warning would be nice.
21087 */
21088 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000021089 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
21090 xmlSchemaElementPtr decl = NULL;
21091
21092 if (node->ns != NULL)
21093 decl = xmlHashLookup3(ctxt->schema->elemDecl,
21094 node->name, node->ns->href, NULL);
21095 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021096 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
21097 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021098 if (decl != NULL) {
21099 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021100 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021101 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021102 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000021103 "Internal error: xmlSchemaValidateAnyInternal, "
21104 "validating an element in the context of a wildcard.",
21105 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000021106 }
21107 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021108 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21109 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021110 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021111 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021112 /*
21113 * Evaluate IDCs even if a validation error occured.
21114 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021115 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021116 return(-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021117
Daniel Veillardc0826a72004-08-10 14:17:33 +000021118 return (ctxt->err);
21119 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021120 /*
21121 * Evaluate IDCs; we need to know if an IDC field resolves to
21122 * such a node. This node has no type definition and will
21123 * definitely result in an IDC validation error if an IDC field
21124 * resolves.
21125 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021126 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021127 return(-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000021128 }
21129 if (node->children != NULL) {
21130 child = node->children;
21131 do {
21132 if (child->type == XML_ELEMENT_NODE) {
21133 if (child->ns != NULL)
21134 uri = child->ns->href;
21135 else
21136 uri = NULL;
21137 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021138 /* TODO: error code. */
21139 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000021140 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021141 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000021142 return (ctxt->err);
21143 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021144
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021145 ctxt->node = child;
21146 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021147
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021148 /*
21149 * Recurse over the children.
21150 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021151 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
21152 wild, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021153 if (ret == -1)
21154 return (-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021155
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021156 if (xmlSchemaEndElement(ctxt) == -1)
21157 return (-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021158
Daniel Veillardc0826a72004-08-10 14:17:33 +000021159 if (ret != 0)
21160 return (ret);
21161 }
21162 child = child->next;
21163 } while (child != NULL);
21164 }
21165 return (0);
21166}
21167
21168/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021169 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000021170 * @ctxt: a schema validation context
21171 *
21172 * Returns 0 if the element is valid, a positive error code
21173 * number otherwise and -1 in case of an internal or API error.
21174 */
21175static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021176xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021177 xmlSchemaWildcardPtr wild)
Daniel Veillardc0826a72004-08-10 14:17:33 +000021178{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021179
21180 if ((wild == NULL) || (wild->type != XML_SCHEMA_TYPE_ANY) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021181 (ctxt->node == NULL)) {
21182 xmlSchemaVCustomErr(ctxt,
21183 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
21184 "Internal error: xmlSchemaValidateElementByWildcard, "
21185 "bad arguments", NULL);
21186 return (-1);
21187 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021188 if (wild->negNsSet != NULL) {
21189 /*
21190 * Workaround for negated namespaces.
21191 */
21192 if (ctxt->node->ns != NULL) {
21193 if (xmlSchemaMatchesWildcardNs(wild, ctxt->node->ns->href) == 0) {
21194 ctxt->flags |= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD;
21195 return (XML_SCHEMAV_ELEMENT_CONTENT);
21196 }
21197 } else if (xmlSchemaMatchesWildcardNs(wild, NULL) == 0) {
21198 ctxt->flags |= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD;
21199 return (XML_SCHEMAV_ELEMENT_CONTENT);
21200 }
21201 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021202 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021203 wild, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000021204}
21205
21206/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021207 * xmlSchemaValidateElementByAnyType:
William M. Brack2f2a6632004-08-20 23:09:47 +000021208 * @ctxt: a schema validation context
21209 * @node: the current element
21210 *
21211 * This one validates the content of an element of the type
21212 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
21213 * thus elements in the subtree will be validated, if a corresponding
21214 * declaration in the schema exists.
21215 *
21216 * Returns 0 if the element and its subtree is valid, a positive error code
21217 * otherwise and -1 in case of an internal or API error.
21218 */
21219static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021220xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
21221 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000021222{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021223 xmlSchemaTypePtr oldtype;
21224 xmlNodePtr top, cur;
21225 xmlSchemaElementPtr decl;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021226 int skipContent, ret, insub = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021227
21228 if ((type == NULL) || (ctxt->node == NULL))
21229 return (-1);
21230
21231 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000021232 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021233
21234 oldtype = ctxt->type;
21235 top = ctxt->node;
21236 /*
21237 * STREAM: Child nodes are processed.
21238 */
21239 cur = ctxt->node->children;
21240 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021241 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021242 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021243 /*
21244 * The process contents of the wildcard is "lax", thus
21245 * we need to validate the element if a declaration
21246 * exists.
21247 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021248 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000021249 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021250 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000021251 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021252 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
21253 ctxt->node = cur;
21254
21255 if (insub) {
21256 /*
21257 * BEGIN element.
21258 */
21259 xmlSchemaBeginElement(ctxt);
21260 } else
21261 insub = 1;
21262
21263 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021264 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
21265 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000021266 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021267 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000021268 "Internal error: xmlSchemaValidateAnyTypeContent, "
21269 "validating an element in the context of a wildcard.",
21270 NULL, NULL);
21271 return (ret);
21272 } else if (ret > 0)
21273 return (ret);
21274 skipContent = 1;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021275 } else {
21276 /*
21277 * IDCs.
21278 */
21279 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
21280 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000021281 }
21282 }
21283 /*
21284 * Browse the full subtree, deep first.
21285 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021286 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021287 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021288 cur = cur->children;
21289 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021290 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021291 cur = cur->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021292 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021293 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021294 while (cur != top) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021295 if (cur->type == XML_ELEMENT_NODE) {
21296 /*
21297 * END element.
21298 */
21299 xmlSchemaEndElement(ctxt);
21300 }
21301 if (cur->parent != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021302 cur = cur->parent;
21303 if ((cur != top) && (cur->next != NULL)) {
21304 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000021305 break;
21306 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021307 if (cur->parent == NULL) {
21308 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000021309 break;
21310 }
21311 }
21312 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021313 if (cur == top)
21314 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000021315 } else
21316 break;
21317 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021318 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000021319 return (0);
21320}
21321
21322/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021323 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000021324 * @ctxt: a schema validation context
21325 * @node: the top node.
21326 *
21327 * Validate the content of an element expected to be a complex type type
21328 * xmlschema-1.html#cvc-complex-type
21329 * Validation Rule: Element Locally Valid (Complex Type)
21330 *
21331 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000021332 * number otherwise and -1 in case of internal or API error.
21333 * Note on reported errors: Although it might be nice to report
21334 * the name of the simple/complex type, used to validate the content
21335 * of a node, it is quite unnecessary: for global defined types
21336 * the local name of the element is equal to the NCName of the type,
21337 * for local defined types it makes no sense to output the internal
21338 * computed name of the type. TODO: Instead, one should attach the
21339 * struct of the type involved to the error handler - this allows
21340 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000021341 */
21342static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021343xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021344 xmlSchemaTypePtr type,
21345 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021346{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021347 xmlSchemaTypePtr oldtype;
21348 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000021349 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000021350 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021351 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000021352
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021353 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
21354 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000021355
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021356 oldtype = ctxt->type;
21357 ctxt->type = type;
21358 elem = ctxt->node;
21359
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021360 /*
21361 * Verify the attributes
21362 */
21363 /*
21364 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021365 */
21366 /* NOTE: removed, since a check for abstract is
21367 * done in the cvc-type constraint.
21368 *
21369 *
21370 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
21371 * xmlSchemaVComplexTypeErr(ctxt,
21372 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
21373 * elem, type,
21374 * "The type definition is abstract");
21375 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
21376 *}
21377 */
21378
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021379 attrs = ctxt->attr;
21380 attrTop = ctxt->attrTop;
21381 /*
21382 * STREAM: Attribute nodes are processed.
21383 */
21384 xmlSchemaRegisterAttributes(ctxt, elem->properties);
21385 xmlSchemaValidateAttributes(ctxt, elem, type);
21386 if (ctxt->attr != NULL)
21387 xmlSchemaFreeAttributeStates(ctxt->attr);
21388 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021389 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021390
21391 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021392 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021393 * model was defined. Somehow ->contModel is always not NULL
21394 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021395 * TODO: Check if the obove still occurs.
21396 */
Daniel Veillard4255d502002-04-16 15:50:10 +000021397 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000021398 case XML_SCHEMA_CONTENT_EMPTY: {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021399 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021400 * 1 If the {content type} is empty, then the element information
21401 * item has no character or element information item [children].
21402 */
21403 /*
21404 * TODO: Is the entity stuff correct?
21405 */
21406 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
21407 xmlSchemaVComplexTypeErr(ctxt,
21408 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
21409 elem, type,
21410 "Character or element content is not allowed, "
21411 "because the content type is empty");
21412 }
21413 break;
21414 }
21415 case XML_SCHEMA_CONTENT_MIXED:
21416 /*
21417 * Some speedups for anyType or types derived directly from it.
21418 */
21419 if (IS_ANYTYPE(type)) {
21420 /*
21421 * Corresponds to <element name="foo" [type="xsd:anyType"]/>.
21422 */
21423 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
21424 /* TODO: Handle -1. */
21425 break;
21426 }
21427 if (IS_ANYTYPE(type->baseType) &&
21428 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
21429 (type->subtypes == type->baseType->subtypes)) {
21430 /*
21431 * Corresponds to an <extension> of anyType.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021432 */
21433 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
21434 /* TODO: Handle -1. */
21435 break;
21436 }
21437 /* No break on purpose. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021438 case XML_SCHEMA_CONTENT_ELEMENTS: {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021439 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021440 xmlChar *values[10];
21441 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021442 /*
21443 * SPEC (2.4) If the {content type} is element-only or mixed,
21444 * then the sequence of the element information item's
21445 * element information item [children], if any, taken in
21446 * order, is ·valid· with respect to the {content type}'s
21447 * particle, as defined in Element Sequence Locally Valid
21448 * (Particle) (§3.9.4).
21449 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021450 /*
21451 * Content model check initialization.
21452 */
21453 if (type->contModel != NULL) {
21454 oldregexp = ctxt->regexp;
21455 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
21456 (xmlRegExecCallbacks)
21457 xmlSchemaValidateCallback, ctxt);
21458#ifdef DEBUG_AUTOMATA
21459 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
21460#endif
21461 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021462 /*
21463 * STREAM: Children are processed.
21464 */
21465 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000021466 while (child != NULL) {
21467 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000021468 if (child->ns != NULL)
21469 nsUri = child->ns->href;
21470 else
21471 nsUri = NULL;
21472 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021473 child->name, nsUri, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021474 if (ctxt->err == XML_SCHEMAV_INTERNAL)
21475 return (-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021476 if (ctxt->flags & XML_SCHEMA_VALID_INVALID_NEG_WILDCARD) {
21477 ctxt->flags ^= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD;
21478 ret = -1;
21479 }
21480 /*
21481 * URGENT TODO: Could we anchor an error report
21482 * here to notify of invalid elements?
21483 * TODO: Perhaps it would be better to report
21484 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021485 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021486#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000021487 if (ret < 0)
21488 xmlGenericError(xmlGenericErrorContext,
21489 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000021490 else
21491 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000021492 " --> %s\n", child->name);
21493#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021494 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021495 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
21496 &values[0], &terminal);
21497 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021498 XML_SCHEMAV_ELEMENT_CONTENT,
21499 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021500 "This element is not expected",
21501 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021502 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021503 /*
21504 * Note that this will skip further validation of the
21505 * content.
21506 */
21507 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021508 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000021509 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
21510 /*
21511 * TODO: Ask Daniel if this are all character nodes.
21512 */
21513 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
21514 (child->type == XML_ENTITY_NODE) ||
21515 (child->type == XML_ENTITY_REF_NODE) ||
21516 (child->type == XML_CDATA_SECTION_NODE))) {
21517 /*
21518 * 2.3 If the {content type} is element-only, then the
21519 * element information item has no character information
21520 * item [children] other than those whose [character
21521 * code] is defined as a white space in [XML 1.0 (Second
21522 * Edition)].
21523 */
William M. Brack2f2a6632004-08-20 23:09:47 +000021524 xmlSchemaVComplexTypeErr(ctxt,
21525 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021526 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000021527 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021528 "because the content type is element-only");
21529 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000021530 break;
21531 }
21532 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021533 }
21534 /*
21535 * Content model check finalization.
21536 */
21537 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021538 if (ret == 0) {
21539 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021540 &values[0], &terminal);
Daniel Veillard0e460da2005-03-30 22:47:10 +000021541 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021542 * If a next value still exists, It does not have to
Daniel Veillard0e460da2005-03-30 22:47:10 +000021543 * mean that there's an element missing, since it
21544 * might be an optional element. So double check it.
21545 */
21546 ret = xmlRegExecPushString(ctxt->regexp,
21547 NULL, NULL);
21548 if (ret <= 0) {
21549 ret = 1;
21550 xmlSchemaVComplexTypeElemErr(ctxt,
21551 XML_SCHEMAV_ELEMENT_CONTENT,
21552 elem, type, "Missing child element(s)",
21553 nbval, nbneg, values);
21554 } else
21555 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021556#ifdef DEBUG_AUTOMATA
Daniel Veillard0e460da2005-03-30 22:47:10 +000021557 xmlGenericError(xmlGenericErrorContext,
21558 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021559#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021560#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021561 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021562 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021563 "Element %s content check succeeded\n",
21564 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021565#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021566 }
21567 xmlRegFreeExecCtxt(ctxt->regexp);
21568 ctxt->regexp = oldregexp;
21569 }
21570 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000021571 break;
21572 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021573 case XML_SCHEMA_CONTENT_BASIC:
21574 /*
21575 * If the simple content was already validated
21576 * (e.g. a default value), the content need not
21577 * to be validated again.
21578 */
21579 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000021580 xmlChar *value = NULL;
21581 /*
21582 * We hit a complexType with a simpleContent resolving
21583 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000021584 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000021585 /*
21586 * 2.2 If the {content type} is a simple type definition,
21587 * then the element information item has no element
21588 * information item [children], and the ·normalized value·
21589 * of the element information item is ·valid· with respect
21590 * to that simple type definition as defined by String
21591 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021592 */
21593 /*
21594 * STREAM: Children are processed.
21595 */
21596 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000021597 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021598 /*
21599 * TODO: Could the entity stuff produce elements
21600 * as well?
21601 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000021602 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021603 xmlSchemaVComplexTypeErr(ctxt,
21604 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021605 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000021606 "Element content is not allowed, because "
21607 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000021608 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
21609 break;
21610 }
21611 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021612 }
21613 ctxt->node = elem;
21614 ctxt->cur = elem->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021615 if (ret != 0) {
21616 FREE_AND_NULL(value)
21617 break;
21618 }
21619 /*
21620 * Validate the character content against a simple type.
21621 */
21622 if (elem->children == NULL)
21623 value = NULL;
21624 else
21625 value = xmlNodeGetContent(elem);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021626 /*
21627 * NOTE: This call won't check the correct types of the
21628 * content nodes, since this should be done here.
21629 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021630 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
21631 type->contentTypeDef, value, 1, 1, 1, 0);
21632 if (ret > 0) {
21633 /*
21634 * NOTE: Although an error will be reported by
21635 * xmlSchemaValidateSimpleTypeValue, the spec wants
21636 * a specific complex type error to be reported
21637 * additionally.
21638 */
21639 xmlSchemaVComplexTypeErr(ctxt,
21640 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
21641 elem, type,
21642 "The character content is not valid");
21643 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
21644 } else if (ret < 0) {
21645 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
21646 "Internal error: xmlSchemaValidateComplexType, "
21647 "Element '%s': Error while validating character "
21648 "content against complex type '%s'.\n",
21649 elem->name, type->name);
21650 if (value != NULL)
21651 xmlFree(value);
21652 ctxt->type = oldtype;
21653 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021654 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000021655 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021656 xmlFree(value);
21657
Daniel Veillard01fa6152004-06-29 17:04:39 +000021658 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021659 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021660 default:
21661 TODO xmlGenericError(xmlGenericErrorContext,
21662 "unimplemented content type %d\n",
21663 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000021664 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021665 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021666 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000021667}
21668
21669/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021670 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000021671 * @ctxt: a schema validation context
21672 * @elem: an element
21673 * @type: the list of type declarations
21674 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021675 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000021676 *
21677 * Returns 0 if the element is schemas valid, a positive error code
21678 * number otherwise and -1 in case of internal or API error.
21679 */
21680static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021681xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021682 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021683 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021684 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021685{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021686 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000021687
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021688
21689 if ((ctxt == NULL) || (type == NULL)) {
21690 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
21691 "Internal error: xmlSchemaValidateElementByType, "
21692 "bad arguments", NULL);
21693 return (-1);
21694 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021695 /*
21696 * This one is called by "xmlSchemaValidateElementByDeclaration".
21697 * It will forward to the proper validation
21698 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021699 */
21700 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021701 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021702 XML_SCHEMAV_CVC_TYPE_1,
21703 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021704 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021705 return (XML_SCHEMAV_CVC_TYPE_1);
21706 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021707
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021708 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021709 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021710 XML_SCHEMAV_CVC_TYPE_2,
21711 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021712 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021713 return (XML_SCHEMAV_CVC_TYPE_2);
21714 }
21715
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021716 switch (type->type) {
21717 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021718 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
21719 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021720 break;
21721 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021722 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021723 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021724 break;
21725 case XML_SCHEMA_TYPE_BASIC:
21726 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
21727 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
21728 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021729 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021730 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021731 break;
21732 default:
21733 ret = -1;
21734 break;
21735 }
21736 if (ret == -1)
21737 return (-1);
21738 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021739 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000021740}
21741
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021742static int
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021743xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021744 xmlSchemaTypePtr type,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021745 const xmlChar *value,
21746 xmlSchemaValPtr *val)
21747{
21748 xmlSchemaTypePtr prim;
21749
21750 if (val == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021751 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021752 XML_SCHEMAV_INTERNAL,
21753 "Internal error: xmlSchemaPostCreateVal, "
21754 "bad arguments", NULL, NULL);
21755 return (-1);
21756 }
21757 /*
21758 * Only string or anySimpleType values are expected to be post-created.
21759 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021760 prim = xmlSchemaGetPrimitiveType(type);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021761 if ((prim->builtInType == XML_SCHEMAS_STRING) ||
21762 (prim->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21763 {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021764 if (value == NULL)
21765 /* TODO: Can this happen at all? */
21766 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
21767 xmlStrdup(BAD_CAST ""));
21768 else
21769 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING, value);
21770 if ((*val) == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021771 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021772 XML_SCHEMAV_INTERNAL,
21773 "Internal error: xmlSchemaPostCreateVal, "
21774 "failed to create the value", NULL, NULL);
21775 return (-1);
21776 }
21777 return (0);
21778 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021779 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021780 XML_SCHEMAV_INTERNAL,
21781 "Internal error: xmlSchemaPostCreateVal, "
21782 "the given type is not supported", NULL, NULL);
21783 return (-1);
21784}
21785
21786static int
21787xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021788 xmlSchemaAttrStatePtr state)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021789{
21790 xmlChar *value;
21791 const xmlChar *defValue;
21792 xmlSchemaValPtr defVal;
21793 int fixed;
21794 int ret;
21795
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021796 if (vctxt->attrInfo->typeDef == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021797 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
21798 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
21799 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021800 vctxt->node = vctxt->attrInfo->node;
21801 vctxt->cur = vctxt->node->children;
21802 /* STREAM */
21803 value = xmlNodeListGetString(vctxt->node->doc, vctxt->cur, 1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021804
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021805 /*
21806 * NOTE: This call also checks the content nodes for correct type.
21807 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021808 ret = xmlSchemaValidateSimpleTypeValue(vctxt, vctxt->attrInfo->typeDef,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021809 value, 1, 1, 1, 1);
21810
21811 /*
21812 * Handle 'fixed' attributes.
21813 */
21814 if (ret > 0) {
21815 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21816 /*
21817 * NOTE: Fixed value constraints will be not
21818 * applied if the value was invalid, because:
21819 * 1. The validation process does not return a precomputed
21820 * value.
21821 * 2. An invalid value implies a violation of a fixed
21822 * value constraint.
21823 */
21824 } else if (ret == 0) {
21825 state->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021826 if (xmlSchemaGetEffectiveValueConstraint(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021827 (xmlSchemaAttributePtr) vctxt->attrInfo->decl,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021828 &fixed, &defValue, &defVal) && (fixed == 1)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000021829
21830 int ws = xmlSchemaGetWhiteSpaceFacetValue(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021831 vctxt->nodeInfo->typeDef);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021832 /*
21833 * cvc-au : Attribute Locally Valid (Use)
21834 * For an attribute information item to be·valid·
21835 * with respect to an attribute use its ·normalized
21836 * value· must match the canonical lexical representation
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021837 * of the attribute use's {value constraint} value, if it
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021838 * is present and fixed.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021839 *
21840 * TODO: Use somehow the *normalized* value and the *canonical*
21841 * fixed value. This here compares the canonical values of both.
21842 * The normalized value of, for example, a float type can differ
21843 * from its canonical representation. This all means that a fixed
21844 * value can only be OK, if it's present in the canonical form in
21845 * the instance.
21846 * NOTE: Since the value for string and anySimpleType is not always
21847 * precomputed during validation, we need to do it now.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021848 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021849 if (vctxt->value == NULL) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000021850 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021851 * Post-create the value.
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000021852 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021853 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
21854 value, &(vctxt->value)) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021855 ret = -1;
21856 goto exit;
21857 }
21858 value = NULL;
21859 }
21860 if (defVal == NULL) {
21861 xmlChar *str;
21862
21863 /*
21864 * Post-create the default/fixed value.
21865 */
21866 if (defValue == NULL)
21867 str = xmlStrdup(BAD_CAST "");
21868 else
21869 str = xmlStrdup(defValue);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021870 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
21871 str, &defVal) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021872 ret = -1;
21873 FREE_AND_NULL(str)
21874 goto exit;
21875 }
21876 ((xmlSchemaAttributePtr) vctxt->attrInfo->decl)->defVal = defVal;
21877 }
21878 if (xmlSchemaCompareValuesWhtsp(vctxt->value,
21879 (xmlSchemaWhitespaceValueType) ws,
21880 defVal,
21881 (xmlSchemaWhitespaceValueType) ws) != 0)
21882 {
21883 state->state = XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021884 }
21885 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021886 }
21887exit:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021888 if (value != NULL) {
21889 xmlFree(value);
21890 }
21891 return (ret);
21892}
21893
Daniel Veillard4255d502002-04-16 15:50:10 +000021894/**
21895 * xmlSchemaValidateAttributes:
21896 * @ctxt: a schema validation context
21897 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000021898 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000021899 *
21900 * Validate the attributes of an element.
21901 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000021902 * 1. Existent, invalid attributes are reported in the form
21903 * "prefix:localName".
21904 * Reason: readability - it is easier to find the actual XML
21905 * representation of the attributes QName.
21906 * 2. Missing attributes are reported in the form
21907 * {"URI", "localName"}.
21908 * This is necessary, since the the prefix need not to be declared
21909 * at all, and thus is not computable.
21910 *
Daniel Veillard4255d502002-04-16 15:50:10 +000021911 * Returns 0 if the element is schemas valid, a positive error code
21912 * number otherwise and -1 in case of internal or API error.
21913 */
21914static int
Daniel Veillard3646d642004-06-02 19:19:14 +000021915xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021916{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021917 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000021918 int ret;
21919 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021920 const xmlChar *defValue;
21921 xmlSchemaValPtr defVal;
21922 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021923 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000021924 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000021925 int found;
William M. Brack803812b2004-06-03 02:11:24 +000021926 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021927 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021928 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000021929#ifdef DEBUG_ATTR_VALIDATION
21930 int redundant = 0;
21931#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000021932
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021933
Daniel Veillardc0826a72004-08-10 14:17:33 +000021934 /*
21935 * Allow all attributes if the type is anyType.
21936 */
21937 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
21938 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021939
21940 oldnode = ctxt->node;
21941 if (type != NULL)
21942 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000021943 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000021944 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000021945 attrDecl = attrUse->attr;
21946#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021947 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000021948 printf("attr use - use: %d\n", attrDecl->occurs);
21949#endif
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021950 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
Daniel Veillard3646d642004-06-02 19:19:14 +000021951
21952 if (curState->decl == attrUse->attr) {
21953#ifdef DEBUG_ATTR_VALIDATION
21954 redundant = 1;
21955#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021956 }
Daniel Veillard3646d642004-06-02 19:19:14 +000021957 attr = curState->attr;
21958#ifdef DEBUG_ATTR_VALIDATION
21959 printf("attr - name: %s\n", attr->name);
21960 if (attr->ns != NULL)
21961 printf("attr - ns: %s\n", attr->ns->href);
21962 else
21963 printf("attr - ns: none\n");
21964#endif
21965 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021966 if (attr == NULL)
21967 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000021968 if (attrDecl->ref != NULL) {
21969 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021970 continue;
21971 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000021972 if ((attrDecl->refNs == NULL) ||
21973 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021974 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000021975 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021976 continue;
21977 }
21978 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000021979 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021980 continue;
21981 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000021982 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021983 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000021984 if (attr->ns == NULL) {
21985 /*
William M. Bracke7091952004-05-11 15:09:58 +000021986 * accept an unqualified attribute only if the target
21987 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000021988 */
Daniel Veillard3646d642004-06-02 19:19:14 +000021989 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000021990 /*
21991 * This check was removed, since the target namespace
21992 * was evaluated during parsing and already took
21993 * "attributeFormDefault" into account.
21994 */
21995 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000021996 continue;
21997 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000021998 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000021999 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000022000 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000022001 attr->ns->href))
22002 continue;
22003 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022004 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022005#ifdef DEBUG_ATTR_VALIDATION
22006 printf("found\n");
22007#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022008 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000022009 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022010 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
22011 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022012 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022013 */
Daniel Veillard3646d642004-06-02 19:19:14 +000022014 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022015 if (!found) {
22016 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
22017 xmlSchemaAttrStatePtr tmp;
22018
Daniel Veillard3646d642004-06-02 19:19:14 +000022019#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022020 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000022021#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022022 /*
22023 * Add a new dummy attribute state.
22024 */
22025 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
22026 if (tmp == NULL) {
22027 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
22028 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022029 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022030 }
22031 tmp->attr = NULL;
22032 tmp->state = XML_SCHEMAS_ATTR_MISSING;
22033 tmp->decl = attrDecl;
22034 tmp->next = NULL;
22035
22036 if (reqAttrStates == NULL) {
22037 reqAttrStates = tmp;
22038 reqAttrStatesTop = tmp;
22039 } else {
22040 reqAttrStatesTop->next = tmp;
22041 reqAttrStatesTop = tmp;
22042 }
22043 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
22044 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
22045 &fixed, &defValue, &defVal))) {
22046 xmlSchemaAttrStatePtr tmp;
22047 /*
22048 * Handle non existent default/fixed attributes.
22049 */
22050 tmp = (xmlSchemaAttrStatePtr)
22051 xmlMalloc(sizeof(xmlSchemaAttrState));
22052 if (tmp == NULL) {
22053 xmlSchemaVErrMemory(ctxt,
22054 "registering schema specified attributes", NULL);
22055 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022056 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022057 }
22058 tmp->attr = NULL;
22059 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
22060 tmp->decl = attrDecl;
22061 tmp->value = defValue;
22062 tmp->next = NULL;
Kasimier T. Buchcika62f75f2005-03-21 22:01:47 +000022063 if (defAttrStatesTop == NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022064 defAttrStates = tmp;
Kasimier T. Buchcika62f75f2005-03-21 22:01:47 +000022065 else
22066 defAttrStatesTop->next = tmp;
22067 defAttrStatesTop = tmp;
22068 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022069 }
22070 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000022071 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022072 /*
22073 * Add required attributes to the attribute states of the context.
22074 */
22075 if (reqAttrStates != NULL) {
22076 if (ctxt->attr == NULL) {
22077 ctxt->attr = reqAttrStates;
22078 } else {
22079 ctxt->attrTop->next = reqAttrStates;
22080 }
22081 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000022082 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022083 /*
22084 * Process wildcards.
22085 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022086
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022087 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000022088#ifdef DEBUG_ATTR_VALIDATION
22089 xmlSchemaWildcardNsPtr ns;
22090 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022091 if (type->attributeWildcard->processContents ==
22092 XML_SCHEMAS_ANY_LAX)
22093 printf("processContents: lax\n");
22094 else if (type->attributeWildcard->processContents ==
22095 XML_SCHEMAS_ANY_STRICT)
22096 printf("processContents: strict\n");
22097 else
22098 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000022099 if (type->attributeWildcard->any)
22100 printf("type: any\n");
22101 else if (type->attributeWildcard->negNsSet != NULL) {
22102 printf("type: negated\n");
22103 if (type->attributeWildcard->negNsSet->value == NULL)
22104 printf("ns: (absent)\n");
22105 else
22106 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
22107 } else if (type->attributeWildcard->nsSet != NULL) {
22108 printf("type: set\n");
22109 ns = type->attributeWildcard->nsSet;
22110 while (ns != NULL) {
22111 if (ns->value == NULL)
22112 printf("ns: (absent)\n");
22113 else
22114 printf("ns: %s\n", ns->value);
22115 ns = ns->next;
22116 }
22117 } else
22118 printf("empty\n");
22119
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022120
22121#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000022122 curState = ctxt->attr;
22123 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022124 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
22125 if (curState->attr->ns != NULL)
22126 nsURI = curState->attr->ns->href;
22127 else
22128 nsURI = NULL;
22129 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
22130 nsURI)) {
22131 /*
22132 * Handle processContents.
22133 */
22134 if ((type->attributeWildcard->processContents ==
22135 XML_SCHEMAS_ANY_LAX) ||
22136 (type->attributeWildcard->processContents ==
22137 XML_SCHEMAS_ANY_STRICT)) {
22138
22139 attr = curState->attr;
22140 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022141 attr->name, nsURI);
22142 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022143 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022144 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022145 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
22146 /* TODO
22147 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
22148 */
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022149 } else if (type->attributeWildcard->processContents ==
22150 XML_SCHEMAS_ANY_LAX) {
22151 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022152 } else
22153 curState->state = XML_SCHEMAS_ATTR_WILD_NO_DECL;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022154 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000022155 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022156 }
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000022157 }
Daniel Veillard3646d642004-06-02 19:19:14 +000022158 curState = curState->next;
22159 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022160 }
22161
Daniel Veillardc0826a72004-08-10 14:17:33 +000022162 if (ctxt->attr != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022163 int valueNeeded;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022164
22165 /*
22166 * Validate the value of the attribute.
22167 */
22168 if (ctxt->value != NULL) {
22169 xmlSchemaFreeValue(ctxt->value);
22170 ctxt->value = NULL;
22171 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000022172 curState = ctxt->attr;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022173 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022174 valueNeeded = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022175 switch (curState->state) {
22176 case XML_SCHEMAS_ATTR_VALIDATE_VALUE:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022177
22178 /*
22179 * Create an attribute info if needed.
22180 */
22181 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022182 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
22183 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022184 if (ctxt->attrInfo == NULL) {
22185 xmlSchemaVErrMemory(ctxt,
22186 "allocating an attribute info", NULL);
22187 goto fatal_exit;
22188 }
22189 }
22190 /*
22191 * Init the attribute info.
22192 */
22193 ctxt->attrInfo->flags = 0;
22194 ctxt->attrInfo->node = (xmlNodePtr) curState->attr;
22195 ctxt->attrInfo->decl = (xmlSchemaTypePtr) curState->decl;
22196 ctxt->attrInfo->value = NULL;
22197 if (curState->decl != NULL)
22198 ctxt->attrInfo->typeDef = curState->decl->subtypes;
22199 else
22200 ctxt->attrInfo->typeDef = NULL;
22201 if (curState->attr->ns != NULL)
22202 ctxt->attrInfo->namespaceName =
22203 curState->attr->ns->href;
22204 else
22205 ctxt->attrInfo->namespaceName = NULL;
22206 ctxt->attrInfo->localName = curState->attr->name;
22207
22208 ctxt->nodeInfo = ctxt->attrInfo;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022209 /*
22210 * Evaluate IDCs.
22211 */
22212 if (ctxt->xpathStates != NULL) {
22213 ret = xmlSchemaXPathEvaluate(ctxt,
22214 XML_ATTRIBUTE_NODE);
22215 if (ret == -1)
22216 goto fatal_exit;
22217 }
22218
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022219 ret = xmlSchemaCheckAttrLocallyValid(ctxt, curState);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022220 if (ret == -1)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022221 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022222 if ((ret != 0) && (ctxt->value != NULL)) {
22223 xmlSchemaFreeValue(ctxt->value);
22224 ctxt->value = NULL;
22225 }
22226 /* No break on purpose. */
22227 case XML_SCHEMAS_ATTR_CHECKED:
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022228 if (ctxt->xpathStates != NULL) {
22229 /*
22230 * Evaluate IDCs.
22231 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022232 if (ctxt->value != NULL) {
22233 ctxt->attrInfo->value = ctxt->value;
22234 ctxt->value = NULL;
22235 }
22236 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
22237 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022238 }
22239 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022240 default:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022241 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022242 }
22243 curState = curState->next;
22244 }
22245
22246 /*
22247 * Report missing and illegal attributes.
22248 */
22249 curState = ctxt->attr;
22250 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000022251 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
22252 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022253 if (curState->decl != NULL) {
22254 if (curState->decl->ref != NULL)
22255 attrDecl = curState->decl->refDecl;
22256 else
22257 attrDecl = curState->decl;
22258 } else
22259 attrDecl = NULL;
22260 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
22261 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
22262 } else if (curState->state ==
22263 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
22264 xmlSchemaVCustomErr(ctxt,
22265 XML_SCHEMAV_CVC_ATTRIBUTE_2,
22266 (xmlNodePtr) attr,
22267 (xmlSchemaTypePtr) attrDecl,
22268 "The type definition is absent",
22269 NULL);
22270 } else if (curState->state ==
22271 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
22272 xmlSchemaVCustomErr(ctxt,
22273 XML_SCHEMAV_CVC_AU,
22274 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
22275 "The value does not match the fixed value "
22276 "constraint", NULL);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022277 } else if (curState->state == XML_SCHEMAS_ATTR_WILD_NO_DECL) {
22278 xmlSchemaVWildcardErr(ctxt,
22279 XML_SCHEMAV_CVC_WILDCARD,
22280 (xmlNodePtr) attr,
22281 type->attributeWildcard,
22282 "No global attribute declaration found, but "
22283 "stipulated by the strict processContents of "
22284 "the wildcard");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022285 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000022286 /* TODO: "prohibited" won't ever be touched here!.
22287 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
22288 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022289 /*
22290 * TODO: One might report different error messages
22291 * for the following errors.
22292 */
22293 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000022294 xmlSchemaVIllegalAttrErr(ctxt,
22295 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
22296 } else {
22297 xmlSchemaVIllegalAttrErr(ctxt,
22298 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
22299 }
22300 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000022301 }
22302 curState = curState->next;
22303 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022304 }
22305
22306 /*
22307 * Add missing default/fixed attributes.
22308 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022309 if (defAttrStates != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022310 curState = defAttrStates;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022311
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022312 while (curState != NULL) {
22313 attrDecl = curState->decl;
22314 if (attrDecl->ref != NULL)
22315 attrDecl = attrDecl->refDecl;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022316 /*
22317 * Evaluate IDCs on default attributes.
22318 */
22319 if (ctxt->xpathStates != NULL) {
22320 /*
22321 * Create an attribute info if needed.
22322 */
22323 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022324 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
22325 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022326 if (ctxt->attrInfo == NULL) {
22327 xmlSchemaVErrMemory(ctxt,
22328 "allocating an attribute info", NULL);
22329 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022330 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022331 ctxt->attrInfo->value = NULL;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022332 }
22333 /*
22334 * Init the attribute info.
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000022335 * TODO: Hmm, maby a bit oversized this all.
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022336 */
22337 ctxt->attrInfo->flags = 0;
22338 ctxt->attrInfo->decl = (xmlSchemaTypePtr) attrDecl;
22339 ctxt->attrInfo->node = NULL;
22340 ctxt->attrInfo->typeDef = attrDecl->subtypes;
22341 ctxt->attrInfo->namespaceName = attrDecl->targetNamespace;
22342 ctxt->attrInfo->localName = attrDecl->name;
22343
22344 ctxt->nodeInfo = ctxt->attrInfo;
22345
22346 ret = xmlSchemaXPathEvaluate(ctxt,
22347 XML_ATTRIBUTE_NODE);
22348 if (ret == -1)
22349 goto fatal_exit;
22350 if (ctxt->attrInfo->value != NULL) {
22351 xmlSchemaFreeValue(ctxt->attrInfo->value);
22352 ctxt->attrInfo->value = NULL;
22353 }
22354 if (ret > 0) {
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000022355 /*
22356 * IDCs will consume the precomputed default value,
22357 * so we need to clone it somehow.
22358 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022359 /*
22360 * string or anySimpleType does not create a precomputed value
22361 * by default, so it will be created here on demand.
22362 * TODO: default/fixed attributes are a bit unoptimized:
22363 * the string value will be hold by ->defValue and inside
22364 * the precomputed value.
22365 */
22366 if (attrDecl->defVal == NULL) {
22367 xmlChar *str = xmlStrdup(attrDecl->defValue);
22368
22369 if (xmlSchemaPostCreateVal(ctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022370 ctxt->attrInfo->typeDef,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022371 str,
22372 &(attrDecl->defVal)) == -1) {
22373 FREE_AND_NULL(str)
22374 goto fatal_exit;
22375 }
22376 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022377 ctxt->attrInfo->value = xmlSchemaCopyValue(attrDecl->defVal);
22378 /* TODO: error on NULL return. */
22379 }
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000022380
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022381 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
22382 goto fatal_exit;
22383 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022384
22385 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
22386 /*
22387 * PSVI: Add a new attribute node to the current element.
22388 */
22389 if (attrDecl->targetNamespace == NULL) {
22390 xmlNewProp(elem, attrDecl->name, curState->value);
22391 } else {
22392 xmlNsPtr ns;
22393
22394 ns = xmlSearchNsByHref(elem->doc, elem,
22395 attrDecl->targetNamespace);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022396 if (ns == NULL) {
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022397 xmlChar prefix[12];
22398 int counter = 1;
22399
22400 attr = curState->attr;
22401 /*
22402 * Create a namespace declaration on the validation
22403 * root node if no namespace declaration is in scope.
22404 */
22405 snprintf((char *) prefix, sizeof(prefix), "p");
22406 /*
22407 * This is somehow not performant, since the ancestor
22408 * axis beyond @elem will be searched as well.
22409 */
22410 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
22411 while (ns != NULL) {
22412 if (counter > 1000) {
22413 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
22414 XML_SCHEMAV_INTERNAL,
22415 "Internal error: xmlSchemaValidateAttributes, "
22416 "could not compute a ns prefix for "
22417 "default/fixed attribute '%s'.\n",
22418 attrDecl->name, NULL);
22419
22420 break;
22421 }
22422 snprintf((char *) prefix,
22423 sizeof(prefix), "p%d", counter++);
22424 ns = xmlSearchNs(elem->doc, elem,
22425 BAD_CAST prefix);
22426 }
22427 if (ns == NULL) {
22428 ns = xmlNewNs(ctxt->validationRoot,
22429 attrDecl->targetNamespace, BAD_CAST prefix);
22430 xmlNewNsProp(elem, ns, attrDecl->name,
22431 curState->value);
22432 }
22433 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022434 xmlNewNsProp(elem, ns, attrDecl->name,
22435 curState->value);
22436 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022437 }
22438 }
22439 curState = curState->next;
22440 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000022441 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022442 ret = ctxt->err;
22443 goto exit;
22444
22445fatal_exit:
22446 ret = -1;
22447
22448exit:
22449
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022450 if (defAttrStates != NULL)
22451 xmlSchemaFreeAttributeStates(defAttrStates);
22452
Daniel Veillard3646d642004-06-02 19:19:14 +000022453#ifdef DEBUG_ATTR_VALIDATION
22454 if (redundant)
22455 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022456 "xmlSchemaValidateAttributes: redundant call by "
22457 "type: %s\n", type->name);
Daniel Veillard3646d642004-06-02 19:19:14 +000022458#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022459 ctxt->nodeInfo = ctxt->elemInfos[ctxt->depth];
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022460 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022461 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000022462}
22463
22464/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022465 * xmlSchemaStartValidation:
Daniel Veillard4255d502002-04-16 15:50:10 +000022466 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000022467 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022468 * The starting point of the validation, called by
22469 * xmlSchemaValidateDocument and xmlSchemaValidateOneElement.
Daniel Veillard4255d502002-04-16 15:50:10 +000022470 *
22471 * Returns 0 if the element is schemas valid, a positive error code
22472 * number otherwise and -1 in case of internal or API error.
22473 */
22474static int
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022475xmlSchemaStartValidation(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022476{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022477 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022478 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022479
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022480 ctxt->err = 0;
22481 ctxt->nberrors = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022482 if (ctxt->schema == NULL) {
22483 /*
22484 * No schema was specified at time of creation of the validation
22485 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
22486 * of the instance to build a schema.
22487 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022488 if (ctxt->pctxt == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022489 if (xmlSchemaCreatePCtxtOnVCtxt(ctxt) == -1)
22490 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022491 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
22492 if (ctxt->schema == NULL)
22493 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022494 ctxt->xsiAssemble = 1;
22495 } else
22496 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022497 /*
22498 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000022499 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022500 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022501 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
22502 if (ret == -1) {
22503 xmlSchemaVCustomErr(ctxt,
22504 XML_SCHEMAV_INTERNAL,
22505 ctxt->node, NULL,
22506 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022507 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022508 }
22509 /*
22510 * NOTE: We won't react on schema parser errors here.
22511 * TODO: But a warning would be nice.
22512 */
22513 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022514 if (ret != -1) {
22515 if (ctxt->node->ns != NULL)
22516 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
22517 ctxt->node->ns->href);
22518 else
22519 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
22520
22521 if (elemDecl == NULL) {
22522 xmlSchemaVCustomErr(ctxt,
22523 XML_SCHEMAV_CVC_ELT_1,
22524 ctxt->node, NULL,
22525 "No matching global declaration available", NULL);
22526 ret = XML_SCHEMAV_CVC_ELT_1;
22527 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022528 /*
22529 * Augment the IDC definitions.
22530 */
22531 if (ctxt->schema->idcDef != NULL) {
22532 xmlHashScan(ctxt->schema->idcDef,
22533 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
22534 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022535 ctxt->depth = -1;
22536 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022537 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022538 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022539 if (ret < 0) {
22540 xmlSchemaVCustomErr(ctxt,
22541 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
22542 "Internal error: xmlSchemaValidateElement, "
22543 "calling validation by declaration", NULL);
22544 }
22545 }
22546 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022547
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022548 if (ctxt->xsiAssemble) {
22549 if (ctxt->schema != NULL) {
22550 xmlSchemaFree(ctxt->schema);
22551 ctxt->schema = NULL;
22552 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022553 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022554 xmlSchemaClearValidCtxt(ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022555 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000022556}
22557
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022558
Daniel Veillard4255d502002-04-16 15:50:10 +000022559/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022560 * xmlSchemaValidateOneElement:
22561 * @ctxt: a schema validation context
22562 * @elem: an element node
22563 *
22564 * Validate a branch of a tree, starting with the given @elem.
22565 *
22566 * Returns 0 if the element and its subtree is valid, a positive error
22567 * code number otherwise and -1 in case of an internal or API error.
22568 */
22569int
22570xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
22571{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022572 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022573 return (-1);
22574
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022575 if (ctxt->schema == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022576 xmlSchemaVErr(ctxt, NULL,
22577 XML_SCHEMAV_INTERNAL,
22578 "API error: xmlSchemaValidateOneElement, "
22579 "no schema specified.\n", NULL, NULL);
22580 return (-1);
22581 }
22582
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022583 ctxt->doc = elem->doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022584 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022585 ctxt->validationRoot = elem;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022586 return (xmlSchemaStartValidation(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000022587}
22588
22589/************************************************************************
22590 * *
22591 * SAX Validation code *
22592 * *
22593 ************************************************************************/
22594
22595/************************************************************************
22596 * *
22597 * Validation interfaces *
22598 * *
22599 ************************************************************************/
22600
22601/**
22602 * xmlSchemaNewValidCtxt:
22603 * @schema: a precompiled XML Schemas
22604 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022605 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000022606 *
22607 * Returns the validation context or NULL in case of error
22608 */
22609xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022610xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
22611{
Daniel Veillard4255d502002-04-16 15:50:10 +000022612 xmlSchemaValidCtxtPtr ret;
22613
22614 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
22615 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022616 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000022617 return (NULL);
22618 }
22619 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000022620 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000022621 return (ret);
22622}
22623
22624/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022625 * xmlSchemaClearValidCtxt:
22626 * @ctxt: the schema validation context
22627 *
22628 * Free the resources associated to the schema validation context;
22629 * leaves some fields alive intended for reuse of the context.
22630 */
22631static void
22632xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
22633{
22634 if (vctxt == NULL)
22635 return;
22636
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022637 vctxt->flags = 0;
22638
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022639 vctxt->validationRoot = NULL;
22640 if (vctxt->attr != NULL) {
22641 xmlSchemaFreeAttributeStates(vctxt->attr);
22642 vctxt->attr = NULL;
22643 }
22644 if (vctxt->value != NULL) {
22645 xmlSchemaFreeValue(vctxt->value);
22646 vctxt->value = NULL;
22647 }
22648 /*
22649 * Augmented IDC information.
22650 */
22651 if (vctxt->aidcs != NULL) {
22652 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
22653 do {
22654 next = cur->next;
22655 xmlFree(cur);
22656 cur = next;
22657 } while (cur != NULL);
22658 vctxt->aidcs = NULL;
22659 }
22660 if (vctxt->idcNodes != NULL) {
22661 int i;
22662 xmlSchemaPSVIIDCNodePtr item;
22663
22664 for (i = 0; i < vctxt->nbIdcNodes; i++) {
22665 item = vctxt->idcNodes[i];
22666 xmlFree(item->keys);
22667 xmlFree(item);
22668 }
22669 xmlFree(vctxt->idcNodes);
22670 vctxt->idcNodes = NULL;
22671 }
22672 /*
22673 * Note that we won't delete the XPath state pool here.
22674 */
22675 if (vctxt->xpathStates != NULL) {
22676 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
22677 vctxt->xpathStates = NULL;
22678 }
22679 if (vctxt->attrInfo != NULL) {
22680 if (vctxt->attrInfo->value != NULL) {
22681 xmlSchemaFreeValue(vctxt->attrInfo->value);
22682 }
22683 memset(vctxt->attrInfo, 0, sizeof(xmlSchemaNodeInfo));
22684 }
22685 if (vctxt->elemInfos != NULL) {
22686 int i;
22687 xmlSchemaNodeInfoPtr info;
22688
22689 for (i = 0; i < vctxt->sizeElemInfos; i++) {
22690 info = vctxt->elemInfos[i];
22691 if (info == NULL)
22692 break;
22693 if (info->value != NULL) {
22694 xmlSchemaFreeValue(info->value);
22695 info->value = NULL;
22696 }
22697 if (info->idcMatchers != NULL) {
22698 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
22699 info->idcMatchers = NULL;
22700 }
22701 if (info->idcTable != NULL) {
22702 xmlSchemaIDCFreeIDCTable(info->idcTable);
22703 info->idcTable = NULL;
22704 }
22705 }
22706 }
22707}
22708
22709/**
Daniel Veillard4255d502002-04-16 15:50:10 +000022710 * xmlSchemaFreeValidCtxt:
22711 * @ctxt: the schema validation context
22712 *
22713 * Free the resources associated to the schema validation context
22714 */
22715void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022716xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
22717{
Daniel Veillard4255d502002-04-16 15:50:10 +000022718 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022719 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000022720 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000022721 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000022722 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022723 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022724 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022725 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022726 if (ctxt->idcNodes != NULL) {
22727 int i;
22728 xmlSchemaPSVIIDCNodePtr item;
22729
22730 for (i = 0; i < ctxt->nbIdcNodes; i++) {
22731 item = ctxt->idcNodes[i];
22732 xmlFree(item->keys);
22733 xmlFree(item);
22734 }
22735 xmlFree(ctxt->idcNodes);
22736 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022737 if (ctxt->idcKeys != NULL) {
22738 int i;
22739 for (i = 0; i < ctxt->nbIdcKeys; i++)
22740 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
22741 xmlFree(ctxt->idcKeys);
22742 }
22743
22744 if (ctxt->xpathStates != NULL)
22745 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
22746 if (ctxt->xpathStatePool != NULL)
22747 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
22748
22749 /*
22750 * Augmented IDC information.
22751 */
22752 if (ctxt->aidcs != NULL) {
22753 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
22754 do {
22755 next = cur->next;
22756 xmlFree(cur);
22757 cur = next;
22758 } while (cur != NULL);
22759 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022760 if (ctxt->attrInfo != NULL) {
22761 if (ctxt->attrInfo->value != NULL)
22762 xmlSchemaFreeValue(ctxt->attrInfo->value);
22763 xmlFree(ctxt->attrInfo);
22764 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022765 if (ctxt->elemInfos != NULL) {
22766 int i;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022767 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022768
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022769 for (i = 0; i < ctxt->sizeElemInfos; i++) {
22770 info = ctxt->elemInfos[i];
22771 if (info == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022772 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022773 if (info->value != NULL)
22774 xmlSchemaFreeValue(info->value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022775 if (info->idcMatchers != NULL)
22776 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022777 if (info->idcTable != NULL)
22778 xmlSchemaIDCFreeIDCTable(info->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022779 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022780 * TODO: Don't know if those will have to be freed if in streaming
22781 * mode.
22782 *
22783 * xmlFree(info->localName);
22784 * if (info->namespaceName != NULL)
22785 * xmlFree(info->namespaceName);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022786 */
22787 xmlFree(info);
22788 }
22789 xmlFree(ctxt->elemInfos);
22790 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022791 xmlFree(ctxt);
22792}
22793
22794/**
22795 * xmlSchemaSetValidErrors:
22796 * @ctxt: a schema validation context
22797 * @err: the error function
22798 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000022799 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000022800 *
William M. Brack2f2a6632004-08-20 23:09:47 +000022801 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000022802 */
22803void
22804xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022805 xmlSchemaValidityErrorFunc err,
22806 xmlSchemaValidityWarningFunc warn, void *ctx)
22807{
Daniel Veillard4255d502002-04-16 15:50:10 +000022808 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022809 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000022810 ctxt->error = err;
22811 ctxt->warning = warn;
22812 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022813 if (ctxt->pctxt != NULL)
22814 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000022815}
22816
22817/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000022818 * xmlSchemaGetValidErrors:
22819 * @ctxt: a XML-Schema validation context
22820 * @err: the error function result
22821 * @warn: the warning function result
22822 * @ctx: the functions context result
22823 *
22824 * Get the error and warning callback informations
22825 *
22826 * Returns -1 in case of error and 0 otherwise
22827 */
22828int
22829xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
22830 xmlSchemaValidityErrorFunc * err,
22831 xmlSchemaValidityWarningFunc * warn, void **ctx)
22832{
22833 if (ctxt == NULL)
22834 return (-1);
22835 if (err != NULL)
22836 *err = ctxt->error;
22837 if (warn != NULL)
22838 *warn = ctxt->warning;
22839 if (ctx != NULL)
22840 *ctx = ctxt->userData;
22841 return (0);
22842}
22843
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022844
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022845/**
Daniel Veillard6927b102004-10-27 17:29:04 +000022846 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022847 * @ctxt: a schema validation context
22848 * @options: a combination of xmlSchemaValidOption
22849 *
22850 * Sets the options to be used during the validation.
22851 *
22852 * Returns 0 in case of success, -1 in case of an
22853 * API error.
22854 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022855int
22856xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
22857 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022858
22859{
22860 int i;
22861
22862 if (ctxt == NULL)
22863 return (-1);
22864 /*
22865 * WARNING: Change the start value if adding to the
22866 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022867 * TODO: Is there an other, more easy to maintain,
22868 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022869 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022870 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022871 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022872 xmlSchemaVErr(ctxt, NULL,
22873 XML_SCHEMAV_INTERNAL,
22874 "Internal error: xmlSchemaSetValidOptions, "
22875 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022876 return (-1);
22877 }
22878 }
22879 ctxt->options = options;
22880 return (0);
22881}
22882
22883/**
Daniel Veillard6927b102004-10-27 17:29:04 +000022884 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022885 * @ctxt: a schema validation context
22886 *
William M. Brack21e4ef22005-01-02 09:53:13 +000022887 * Get the validation context options.
22888 *
22889 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022890 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022891int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022892xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
22893
22894{
22895 if (ctxt == NULL)
22896 return (-1);
22897 else
22898 return (ctxt->options);
22899}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022900
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022901
Daniel Veillard259f0df2004-08-18 09:13:18 +000022902/**
Daniel Veillard4255d502002-04-16 15:50:10 +000022903 * xmlSchemaValidateDoc:
22904 * @ctxt: a schema validation context
22905 * @doc: a parsed document tree
22906 *
22907 * Validate a document tree in memory.
22908 *
22909 * Returns 0 if the document is schemas valid, a positive error code
22910 * number otherwise and -1 in case of internal or API error.
22911 */
22912int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022913xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
22914{
Daniel Veillard4255d502002-04-16 15:50:10 +000022915 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022916 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022917
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022918 ctxt->doc = doc;
22919 ctxt->node = xmlDocGetRootElement(doc);
22920 if (ctxt->node == NULL) {
22921 xmlSchemaVCustomErr(ctxt,
22922 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
22923 (xmlNodePtr) doc, NULL,
22924 "The document has no document element", NULL);
22925 return (ctxt->err);
22926 }
22927 ctxt->validationRoot = ctxt->node;
22928 xmlSchemaStartValidation(ctxt);
22929
22930 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000022931}
22932
22933/**
22934 * xmlSchemaValidateStream:
22935 * @ctxt: a schema validation context
22936 * @input: the input to use for reading the data
22937 * @enc: an optional encoding information
22938 * @sax: a SAX handler for the resulting events
22939 * @user_data: the context to provide to the SAX handler.
22940 *
22941 * Validate a document tree in memory.
22942 *
22943 * Returns 0 if the document is schemas valid, a positive error code
22944 * number otherwise and -1 in case of internal or API error.
22945 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022946int
Daniel Veillard4255d502002-04-16 15:50:10 +000022947xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022948 xmlParserInputBufferPtr input, xmlCharEncoding enc,
22949 xmlSAXHandlerPtr sax, void *user_data)
22950{
Daniel Veillard4255d502002-04-16 15:50:10 +000022951 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022952 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022953 ctxt->input = input;
22954 ctxt->enc = enc;
22955 ctxt->sax = sax;
22956 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022957 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022958}
22959
Daniel Veillard5d4644e2005-04-01 13:11:58 +000022960#define bottom_xmlschemas
22961#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000022962#endif /* LIBXML_SCHEMAS_ENABLED */