blob: cb13635ccd2ae2c4e17745c3d428bfe118e61000 [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
157#if 0
158#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
159#endif
160
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +0000161/*
Daniel Veillardc0826a72004-08-10 14:17:33 +0000162#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
163#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
164#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +0000165*/
Daniel Veillardc0826a72004-08-10 14:17:33 +0000166
Daniel Veillard4255d502002-04-16 15:50:10 +0000167#define XML_SCHEMAS_PARSE_ERROR 1
168
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000169#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
170
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000171
172/*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000173* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
174* locate schemata to be imported
175* using the namespace name; otherwise
176* the location URI will be used */
177
178/*
179* xmlSchemaParserOption:
180*
181* This is the set of XML Schema parser options.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000182*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000183typedef enum {
184 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000185 * locate schemata to be imported
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000186 * using the namespace name; otherwise
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000187 * the location URI will be used *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000188} xmlSchemaParserOption;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000189*/
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000190
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000191typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000192typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000193
194typedef struct _xmlSchemaItemList xmlSchemaItemList;
195typedef xmlSchemaItemList *xmlSchemaItemListPtr;
196
197struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000198 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000199 int nbItems; /* used for dynamic addition of schemata */
200 int sizeItems; /* used for dynamic addition of schemata */
201};
202
Daniel Veillard4255d502002-04-16 15:50:10 +0000203struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000204 void *userData; /* user specific data block */
205 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
206 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000207 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000208 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000209 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000210
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000211 xmlSchemaPtr topschema; /* The main schema */
212 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
213
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000214 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000215 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000216 int counter;
217
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000218 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000219 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000220 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000221
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000222 const char *buffer;
223 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000224
Daniel Veillard4255d502002-04-16 15:50:10 +0000225 /*
226 * Used to build complex element content models
227 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000228 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000229 xmlAutomataStatePtr start;
230 xmlAutomataStatePtr end;
231 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000232
233 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000234 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000235 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
236 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000237 xmlSchemaAssemblePtr assemble;
238 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000239 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000240 const xmlChar **localImports; /* list of locally imported namespaces */
241 int sizeLocalImports;
242 int nbLocalImports;
Daniel Veillard4255d502002-04-16 15:50:10 +0000243};
244
245
246#define XML_SCHEMAS_ATTR_UNKNOWN 1
247#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000248#define XML_SCHEMAS_ATTR_PROHIBITED 3
249#define XML_SCHEMAS_ATTR_MISSING 4
250#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
251#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000252#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
253#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000254#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
255#define XML_SCHEMAS_ATTR_WILD_NO_DECL 10
Daniel Veillard4255d502002-04-16 15:50:10 +0000256
257typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
258typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
259struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000260 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000261 xmlAttrPtr attr;
262 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000263 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000264 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000265};
266
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000267/**
268 * xmlSchemaBasicItem:
269 *
270 * The abstract base type for schema components.
271 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000272typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
273typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
274struct _xmlSchemaBasicItem {
275 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000276};
277
278/**
279 * xmlSchemaAnnotItem:
280 *
281 * The abstract base type for annotated schema components.
282 * (Extends xmlSchemaBasicItem)
283 */
284typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
285typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
286struct _xmlSchemaAnnotItem {
287 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000288 xmlSchemaAnnotPtr annot;
289};
290
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000291/**
292 * xmlSchemaTreeItem:
293 *
294 * The abstract base type for tree-like structured schema components.
295 * (Extends xmlSchemaAnnotItem)
296 */
297typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
298typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
299struct _xmlSchemaTreeItem {
300 xmlSchemaTypeType type;
301 xmlSchemaAnnotPtr annot;
302 xmlSchemaTreeItemPtr next;
303 xmlSchemaTreeItemPtr children;
304};
305
306/**
307 * xmlSchemaQNameRef:
308 *
309 * A component reference item (not a schema component)
310 * (Extends xmlSchemaBasicItem)
311 */
312typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
313typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
314struct _xmlSchemaQNameRef {
315 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000316 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000317 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000318 const xmlChar *name;
319 const xmlChar *targetNamespace;
320};
321
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000322/**
323 * xmlSchemaParticle:
324 *
325 * A particle component.
326 * (Extends xmlSchemaTreeItem)
327 */
328typedef struct _xmlSchemaParticle xmlSchemaParticle;
329typedef xmlSchemaParticle *xmlSchemaParticlePtr;
330struct _xmlSchemaParticle {
331 xmlSchemaTypeType type;
332 xmlSchemaAnnotPtr annot;
333 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
334 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
335 int minOccurs;
336 int maxOccurs;
337 xmlNodePtr node;
338};
339
340/**
341 * xmlSchemaModelGroup:
342 *
343 * A model group component.
344 * (Extends xmlSchemaTreeItem)
345 */
346typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
347typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
348struct _xmlSchemaModelGroup {
349 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
350 xmlSchemaAnnotPtr annot;
351 xmlSchemaTreeItemPtr next; /* not used */
352 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
353 xmlNodePtr node;
354};
355
356/**
357 * xmlSchemaModelGroupDef:
358 *
359 * A model group definition component.
360 * (Extends xmlSchemaTreeItem)
361 */
362typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
363typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
364struct _xmlSchemaModelGroupDef {
365 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
366 xmlSchemaAnnotPtr annot;
367 xmlSchemaTreeItemPtr next; /* not used */
368 xmlSchemaTreeItemPtr children; /* the "model group" */
369 const xmlChar *name;
370 const xmlChar *targetNamespace;
371 xmlNodePtr node;
372};
373
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000374typedef struct _xmlSchemaIDC xmlSchemaIDC;
375typedef xmlSchemaIDC *xmlSchemaIDCPtr;
376
377/**
378 * xmlSchemaIDCSelect:
379 *
380 * The identity-constraint "field" and "selector" item, holding the
381 * XPath expression.
382 */
383typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
384typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
385struct _xmlSchemaIDCSelect {
386 xmlSchemaIDCSelectPtr next;
387 xmlSchemaIDCPtr idc;
388 int index; /* an index position if significant for IDC key-sequences */
389 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000390 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000391};
392
393/**
394 * xmlSchemaIDC:
395 *
396 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000397 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000398 */
399
400struct _xmlSchemaIDC {
401 xmlSchemaTypeType type;
402 xmlSchemaAnnotPtr annot;
403 xmlSchemaIDCPtr next;
404 xmlNodePtr node;
405 const xmlChar *name;
406 const xmlChar *targetNamespace;
407 xmlSchemaIDCSelectPtr selector;
408 xmlSchemaIDCSelectPtr fields;
409 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000410 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000411};
412
413/**
414 * xmlSchemaIDCAug:
415 *
416 * The augmented IDC information used for validation.
417 */
418typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
419typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
420struct _xmlSchemaIDCAug {
421 xmlSchemaIDCAugPtr next; /* next in a list */
422 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000423 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000424 tables need to be bubbled upwards */
425};
426
427/**
428 * xmlSchemaPSVIIDCKeySequence:
429 *
430 * The key sequence of a node table item.
431 */
432typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
433typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
434struct _xmlSchemaPSVIIDCKey {
435 xmlSchemaTypePtr type;
436 xmlSchemaValPtr compValue;
437};
438
439/**
440 * xmlSchemaPSVIIDCNode:
441 *
442 * The node table item of a node table.
443 */
444typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
445typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
446struct _xmlSchemaPSVIIDCNode {
447 xmlNodePtr node;
448 xmlSchemaPSVIIDCKeyPtr *keys;
449};
450
451/**
452 * xmlSchemaPSVIIDCBinding:
453 *
454 * The identity-constraint binding item of the [identity-constraint table].
455 */
456typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
457typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
458struct _xmlSchemaPSVIIDCBinding {
459 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
460 xmlSchemaIDCPtr definition; /* the IDC definition */
461 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
462 int nbNodes; /* number of entries in the node table */
463 int sizeNodes; /* size of the node table */
464 int nbDupls; /* number of already identified duplicates in the node
465 table */
466 /* int nbKeys; number of keys in each key-sequence */
467};
468
469#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
470#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
471
472#define XPATH_STATE_OBJ_MATCHES -2
473#define XPATH_STATE_OBJ_BLOCKED -3
474
475typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
476typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
477
478/**
479 * xmlSchemaIDCStateObj:
480 *
481 * The state object used to evaluate XPath expressions.
482 */
483typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
484typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
485struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000486 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000487 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000488 int depth; /* depth of creation */
489 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000490 int nbHistory;
491 int sizeHistory;
492 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
493 matcher */
494 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000495 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000496};
497
498#define IDC_MATCHER 0
499
500/**
501 * xmlSchemaIDCMatcher:
502 *
503 * Used to IDC selectors (and fields) successively.
504 */
505struct _xmlSchemaIDCMatcher {
506 int type;
507 int depth; /* the tree depth at creation time */
508 xmlSchemaIDCMatcherPtr next; /* next in the list */
509 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
510 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
511 elements */
512 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000513 int targetDepth;
514};
515
516/*
517* Element info flags.
518*/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000519#define XML_SCHEMA_ELEM_INFO_VALUE_NEEDED 1
520/* #define XML_SCHEMA_ELEM_INFO_ATTR 2 */
521/* #define XML_SCHEMA_ELEM_INFO_ELEM 4 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000522
523/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000524 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000525 *
526 * Holds information of an element node.
527 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000528typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
529typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
530struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000531 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000532 int flags; /* combination of node info flags */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000533 xmlNodePtr node;
534 const xmlChar *localName;
535 const xmlChar *namespaceName;
536 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +0000537 xmlSchemaTypePtr decl; /* the element/attribute declaration */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000538 xmlSchemaValPtr value; /* the pre-computed value if any */
539 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
540 for the scope element*/
541 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
542 element */
543};
544
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000545#define XML_SCHEMA_VALID_INVALID_NEG_WILDCARD 1<<0
546
Daniel Veillard4255d502002-04-16 15:50:10 +0000547/**
548 * xmlSchemaValidCtxt:
549 *
550 * A Schemas validation context
551 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000552struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000553 void *userData; /* user specific data block */
554 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000555 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000556 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000557
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000558 xmlSchemaPtr schema; /* The schema in use */
559 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000560 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000561 xmlCharEncoding enc;
562 xmlSAXHandlerPtr sax;
563 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000564
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000565 xmlDocPtr myDoc;
566 int err;
567 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000568
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000569 xmlNodePtr node;
570 xmlNodePtr cur;
571 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000572
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000573 xmlRegExecCtxtPtr regexp;
574 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000575
Daniel Veillard3646d642004-06-02 19:19:14 +0000576 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000577 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000578 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000579 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000580 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000581 xmlNodePtr validationRoot;
582 xmlSchemaParserCtxtPtr pctxt;
583 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000584
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000585 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000586 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000587 int sizeElemInfos;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000588 xmlSchemaNodeInfoPtr nodeInfo; /* the current element information */
589 xmlSchemaNodeInfoPtr attrInfo; /* node infor for the current attribute */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000590
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000591 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
592
593 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
594 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
595
596 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
597 int nbIdcNodes;
598 int sizeIdcNodes;
599
600 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
601 int nbIdcKeys;
602 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000603
604 int flags;
Daniel Veillard4255d502002-04-16 15:50:10 +0000605};
606
Daniel Veillard1d913862003-11-21 00:28:39 +0000607/*
608 * These are the entries in the schemas importSchemas hash table
609 */
610typedef struct _xmlSchemaImport xmlSchemaImport;
611typedef xmlSchemaImport *xmlSchemaImportPtr;
612struct _xmlSchemaImport {
613 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000614 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000615 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000616 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000617};
Daniel Veillard4255d502002-04-16 15:50:10 +0000618
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000619/*
620 * These are the entries associated to includes in a schemas
621 */
622typedef struct _xmlSchemaInclude xmlSchemaInclude;
623typedef xmlSchemaInclude *xmlSchemaIncludePtr;
624struct _xmlSchemaInclude {
625 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000626 const xmlChar *schemaLocation;
627 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000628 const xmlChar *origTargetNamespace;
629 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000630};
631
Daniel Veillard4255d502002-04-16 15:50:10 +0000632/************************************************************************
633 * *
634 * Some predeclarations *
635 * *
636 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000637
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000638static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
639 xmlSchemaPtr schema,
640 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000641static void
642xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
643 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000644static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000645xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
646static int
647xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000648 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000649 const xmlChar *value,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000650 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000651 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000652 int normalize,
653 int checkNodes);
654static int
655xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
656 xmlSchemaElementPtr elemDecl);
657static int
658xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000659 xmlSchemaWildcardPtr wild);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000660static int
661xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000662static int
663xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
664 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000665static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000666xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
667 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000668static void
669xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000670static int
671xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
672 xmlSchemaTypePtr type,
673 const xmlChar *value,
674 xmlSchemaValPtr *val);
675static xmlSchemaTypePtr
676xmlSchemaGetSimpleContentType(xmlSchemaTypePtr complexType);
677static int
678xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000679static xmlSchemaTreeItemPtr
680xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
681 xmlNodePtr node, xmlSchemaTypeType type,
682 int withParticle);
683static const xmlChar *
684xmlSchemaCompTypeToString(xmlSchemaTypeType type);
685static xmlSchemaTypeLinkPtr
686xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
William M. Brack87640d52004-04-17 14:58:15 +0000687
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000688/************************************************************************
689 * *
690 * Datatype error handlers *
691 * *
692 ************************************************************************/
693
694/**
695 * xmlSchemaPErrMemory:
696 * @node: a context node
697 * @extra: extra informations
698 *
699 * Handle an out of memory condition
700 */
701static void
702xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
703 const char *extra, xmlNodePtr node)
704{
705 if (ctxt != NULL)
706 ctxt->nberrors++;
707 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
708 extra);
709}
710
711/**
712 * xmlSchemaPErr:
713 * @ctxt: the parsing context
714 * @node: the context node
715 * @error: the error code
716 * @msg: the error message
717 * @str1: extra data
718 * @str2: extra data
719 *
720 * Handle a parser error
721 */
722static void
723xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
724 const char *msg, const xmlChar * str1, const xmlChar * str2)
725{
726 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000727 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000728 void *data = NULL;
729
730 if (ctxt != NULL) {
731 ctxt->nberrors++;
732 channel = ctxt->error;
733 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000734 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000735 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000736 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000737 error, XML_ERR_ERROR, NULL, 0,
738 (const char *) str1, (const char *) str2, NULL, 0, 0,
739 msg, str1, str2);
740}
741
742/**
743 * xmlSchemaPErr2:
744 * @ctxt: the parsing context
745 * @node: the context node
746 * @node: the current child
747 * @error: the error code
748 * @msg: the error message
749 * @str1: extra data
750 * @str2: extra data
751 *
752 * Handle a parser error
753 */
754static void
755xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
756 xmlNodePtr child, int error,
757 const char *msg, const xmlChar * str1, const xmlChar * str2)
758{
759 if (child != NULL)
760 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
761 else
762 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
763}
764
Daniel Veillard01fa6152004-06-29 17:04:39 +0000765
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000766/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000767 * xmlSchemaPErrExt:
768 * @ctxt: the parsing context
769 * @node: the context node
770 * @error: the error code
771 * @strData1: extra data
772 * @strData2: extra data
773 * @strData3: extra data
774 * @msg: the message
775 * @str1: extra parameter for the message display
776 * @str2: extra parameter for the message display
777 * @str3: extra parameter for the message display
778 * @str4: extra parameter for the message display
779 * @str5: extra parameter for the message display
780 *
781 * Handle a parser error
782 */
783static void
784xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
785 const xmlChar * strData1, const xmlChar * strData2,
786 const xmlChar * strData3, const char *msg, const xmlChar * str1,
787 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
788 const xmlChar * str5)
789{
790
791 xmlGenericErrorFunc channel = NULL;
792 xmlStructuredErrorFunc schannel = NULL;
793 void *data = NULL;
794
795 if (ctxt != NULL) {
796 ctxt->nberrors++;
797 channel = ctxt->error;
798 data = ctxt->userData;
799 schannel = ctxt->serror;
800 }
801 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
802 error, XML_ERR_ERROR, NULL, 0,
803 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000804 (const char *) strData3, 0, 0, msg, str1, str2,
805 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000806}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000807
Daniel Veillard3646d642004-06-02 19:19:14 +0000808
809/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000810 * xmlSchemaVTypeErrMemory:
811 * @node: a context node
812 * @extra: extra informations
813 *
814 * Handle an out of memory condition
815 */
816static void
817xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
818 const char *extra, xmlNodePtr node)
819{
820 if (ctxt != NULL) {
821 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000822 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000823 }
824 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
825 extra);
826}
827
828/**
829 * xmlSchemaVErr3:
830 * @ctxt: the validation context
831 * @node: the context node
832 * @error: the error code
833 * @msg: the error message
834 * @str1: extra data
835 * @str2: extra data
836 * @str3: extra data
837 *
838 * Handle a validation error
839 */
840static void
841xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
842 const char *msg, const xmlChar *str1, const xmlChar *str2,
843 const xmlChar *str3)
844{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000845 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000846 xmlGenericErrorFunc channel = NULL;
847 void *data = NULL;
848
849 if (ctxt != NULL) {
850 ctxt->nberrors++;
851 ctxt->err = error;
852 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000853 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000854 data = ctxt->userData;
855 }
856 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000857 /* Removed, since the old schema error codes have been
858 * substituted for the global error codes.
859 *
860 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
861 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000862 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000863 error, XML_ERR_ERROR, NULL, 0,
864 (const char *) str1, (const char *) str2,
865 (const char *) str3, 0, 0,
866 msg, str1, str2, str3);
867}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000868
869/**
870 * xmlSchemaVErrExt:
871 * @ctxt: the validation context
872 * @node: the context node
873 * @error: the error code
874 * @msg: the message
875 * @str1: extra parameter for the message display
876 * @str2: extra parameter for the message display
877 * @str3: extra parameter for the message display
878 * @str4: extra parameter for the message display
879 * @str5: extra parameter for the message display
880 *
881 * Handle a validation error
882 */
883static void
884xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
885 const char *msg, const xmlChar * str1,
886 const xmlChar * str2, const xmlChar * str3,
887 const xmlChar * str4, const xmlChar * str5)
888{
889 xmlStructuredErrorFunc schannel = NULL;
890 xmlGenericErrorFunc channel = NULL;
891 void *data = NULL;
892
893 if (ctxt != NULL) {
894 ctxt->nberrors++;
895 ctxt->err = error;
896 channel = ctxt->error;
897 schannel = ctxt->serror;
898 data = ctxt->userData;
899 }
900 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000901 /* Removed, since the old schema error codes have been
902 * substituted for the global error codes.
903 *
904 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
905 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000906 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000907 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
908 msg, str1, str2, str3, str4, str5);
909}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000910/**
911 * xmlSchemaVErr:
912 * @ctxt: the validation context
913 * @node: the context node
914 * @error: the error code
915 * @msg: the error message
916 * @str1: extra data
917 * @str2: extra data
918 *
919 * Handle a validation error
920 */
921static void
922xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
923 const char *msg, const xmlChar * str1, const xmlChar * str2)
924{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000925 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000926 xmlGenericErrorFunc channel = NULL;
927 void *data = NULL;
928
929 if (ctxt != NULL) {
930 ctxt->nberrors++;
931 ctxt->err = error;
932 channel = ctxt->error;
933 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000934 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000935 }
936 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000937 /* Removed, since the old schema error codes have been
938 * substituted for the global error codes.
939 *
940 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
941 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000942 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000943 error, XML_ERR_ERROR, NULL, 0,
944 (const char *) str1, (const char *) str2, NULL, 0, 0,
945 msg, str1, str2);
946}
Daniel Veillard4255d502002-04-16 15:50:10 +0000947
Daniel Veillardc0826a72004-08-10 14:17:33 +0000948/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000949 * xmlSchemaGetComponentNode:
950 * @item: a schema component
951 *
952 * Returns node associated with the schema component.
953 * NOTE that such a node need not be available; plus, a component's
954 * node need not to reflect the component directly, since there is no
955 * one-to-one relationship between the XML Schema representation and
956 * the component representation.
957 */
958static xmlNodePtr
959xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
960{
961 switch (item->type) {
962 case XML_SCHEMA_TYPE_ELEMENT:
963 return (((xmlSchemaElementPtr) item)->node);
964 case XML_SCHEMA_TYPE_ATTRIBUTE:
965 return (((xmlSchemaAttributePtr) item)->node);
966 case XML_SCHEMA_TYPE_COMPLEX:
967 case XML_SCHEMA_TYPE_SIMPLE:
968 return (((xmlSchemaTypePtr) item)->node);
969 case XML_SCHEMA_TYPE_ANY:
970 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
971 return (((xmlSchemaWildcardPtr) item)->node);
972 case XML_SCHEMA_TYPE_PARTICLE:
973 return (((xmlSchemaParticlePtr) item)->node);
974 case XML_SCHEMA_TYPE_SEQUENCE:
975 case XML_SCHEMA_TYPE_CHOICE:
976 case XML_SCHEMA_TYPE_ALL:
977 return (((xmlSchemaModelGroupPtr) item)->node);
978 case XML_SCHEMA_TYPE_GROUP:
979 return (((xmlSchemaModelGroupDefPtr) item)->node);
980 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
981 return (((xmlSchemaAttributeGroupPtr) item)->node);
982 case XML_SCHEMA_TYPE_IDC_UNIQUE:
983 case XML_SCHEMA_TYPE_IDC_KEY:
984 case XML_SCHEMA_TYPE_IDC_KEYREF:
985 return (((xmlSchemaIDCPtr) item)->node);
986 default:
987 return (NULL);
988 }
989}
990
991#if 0
992/**
993 * xmlSchemaGetNextComponent:
994 * @item: a schema component
995 *
996 * Returns the next sibling of the schema component.
997 */
998static xmlSchemaBasicItemPtr
999xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1000{
1001 switch (item->type) {
1002 case XML_SCHEMA_TYPE_ELEMENT:
1003 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1004 case XML_SCHEMA_TYPE_ATTRIBUTE:
1005 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1006 case XML_SCHEMA_TYPE_COMPLEX:
1007 case XML_SCHEMA_TYPE_SIMPLE:
1008 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1009 case XML_SCHEMA_TYPE_ANY:
1010 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1011 return (NULL);
1012 case XML_SCHEMA_TYPE_PARTICLE:
1013 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1014 case XML_SCHEMA_TYPE_SEQUENCE:
1015 case XML_SCHEMA_TYPE_CHOICE:
1016 case XML_SCHEMA_TYPE_ALL:
1017 return (NULL);
1018 case XML_SCHEMA_TYPE_GROUP:
1019 return (NULL);
1020 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1021 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1022 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1023 case XML_SCHEMA_TYPE_IDC_KEY:
1024 case XML_SCHEMA_TYPE_IDC_KEYREF:
1025 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1026 default:
1027 return (NULL);
1028 }
1029}
1030#endif
1031
1032/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001033 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001034 * @attr: the attribute declaration/use
1035 *
1036 * Returns the name of the attribute; if the attribute
1037 * is a reference, the name of the referenced global type will be returned.
1038 */
1039static const xmlChar *
1040xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
1041{
1042 if (attr->ref != NULL)
1043 return(attr->ref);
1044 else
1045 return(attr->name);
1046}
1047
1048/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001049 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001050 * @type: the type (element or attribute)
1051 *
1052 * Returns the target namespace URI of the type; if the type is a reference,
1053 * the target namespace of the referenced type will be returned.
1054 */
1055static const xmlChar *
1056xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
1057{
1058 if (attr->ref != NULL)
1059 return (attr->refNs);
1060 else
1061 return(attr->targetNamespace);
1062}
1063
1064/**
1065 * xmlSchemaFormatNsUriLocal:
1066 * @buf: the string buffer
1067 * @uri: the namespace URI
1068 * @local: the local name
1069 *
1070 * Returns a representation of the given URI used
1071 * for error reports.
1072 *
1073 * Returns an empty string, if @ns is NULL, a formatted
1074 * string otherwise.
1075 */
1076static const xmlChar*
1077xmlSchemaFormatNsUriLocal(xmlChar **buf,
1078 const xmlChar *uri, const xmlChar *local)
1079{
1080 if (*buf != NULL)
1081 xmlFree(*buf);
1082 if (uri == NULL) {
1083 *buf = xmlStrdup(BAD_CAST "{'");
1084 *buf = xmlStrcat(*buf, local);
1085 } else {
1086 *buf = xmlStrdup(BAD_CAST "{'");
1087 *buf = xmlStrcat(*buf, uri);
1088 *buf = xmlStrcat(*buf, BAD_CAST "', '");
1089 *buf = xmlStrcat(*buf, local);
1090 }
1091 *buf = xmlStrcat(*buf, BAD_CAST "'}");
1092 return ((const xmlChar *) *buf);
1093}
1094
1095/**
1096 * xmlSchemaFormatNsPrefixLocal:
1097 * @buf: the string buffer
1098 * @ns: the namespace
1099 * @local: the local name
1100 *
1101 * Returns a representation of the given URI used
1102 * for error reports.
1103 *
1104 * Returns an empty string, if @ns is NULL, a formatted
1105 * string otherwise.
1106 */
1107static const xmlChar*
1108xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
1109 xmlNsPtr ns, const xmlChar *local)
1110{
1111 if (*buf != NULL) {
1112 xmlFree(*buf);
1113 *buf = NULL;
1114 }
1115 if ((ns == NULL) || (ns->prefix == NULL))
1116 return(local);
1117 else {
1118 *buf = xmlStrdup(ns->prefix);
1119 *buf = xmlStrcat(*buf, BAD_CAST ":");
1120 *buf = xmlStrcat(*buf, local);
1121 }
1122 return ((const xmlChar *) *buf);
1123}
1124
1125/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001126 * xmlSchemaFormatQName:
1127 * @buf: the string buffer
1128 * @namespaceName: the namespace name
1129 * @localName: the local name
1130 *
1131 * Returns the given QName in the format "{namespaceName}localName" or
1132 * just "localName" if @namespaceName is NULL.
1133 *
1134 * Returns the localName if @namespaceName is NULL, a formatted
1135 * string otherwise.
1136 */
1137static const xmlChar*
1138xmlSchemaFormatQName(xmlChar **buf,
1139 const xmlChar *namespaceName,
1140 const xmlChar *localName)
1141{
1142 FREE_AND_NULL(*buf)
1143 if (namespaceName == NULL)
1144 return(localName);
1145
1146 *buf = xmlStrdup(BAD_CAST "{");
1147 *buf = xmlStrcat(*buf, namespaceName);
1148 *buf = xmlStrcat(*buf, BAD_CAST "}");
1149 *buf = xmlStrcat(*buf, localName);
1150
1151 return ((const xmlChar *) *buf);
1152}
1153
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001154static const xmlChar *
1155xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1156{
1157 switch (item->type) {
1158 case XML_SCHEMA_TYPE_ELEMENT:
1159 return (((xmlSchemaElementPtr) item)->name);
1160 case XML_SCHEMA_TYPE_ATTRIBUTE:
1161 return (((xmlSchemaAttributePtr) item)->name);
1162 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1163 return (((xmlSchemaAttributeGroupPtr) item)->name);
1164 case XML_SCHEMA_TYPE_SIMPLE:
1165 case XML_SCHEMA_TYPE_COMPLEX:
1166 return (((xmlSchemaTypePtr) item)->name);
1167 case XML_SCHEMA_TYPE_GROUP:
1168 return (((xmlSchemaModelGroupDefPtr) item)->name);
1169 case XML_SCHEMA_TYPE_IDC_KEY:
1170 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1171 case XML_SCHEMA_TYPE_IDC_KEYREF:
1172 return (((xmlSchemaIDCPtr) item)->name);
1173 default:
1174 /*
1175 * Other components cannot have names.
1176 */
1177 break;
1178 }
1179 return (NULL);
1180}
1181
1182static const xmlChar *
1183xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1184{
1185 switch (item->type) {
1186 case XML_SCHEMA_TYPE_ELEMENT:
1187 return (((xmlSchemaElementPtr) item)->targetNamespace);
1188 case XML_SCHEMA_TYPE_ATTRIBUTE:
1189 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1190 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1191 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1192 case XML_SCHEMA_TYPE_SIMPLE:
1193 case XML_SCHEMA_TYPE_COMPLEX:
1194 return (((xmlSchemaTypePtr) item)->targetNamespace);
1195 case XML_SCHEMA_TYPE_GROUP:
1196 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1197 case XML_SCHEMA_TYPE_IDC_KEY:
1198 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1199 case XML_SCHEMA_TYPE_IDC_KEYREF:
1200 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1201 default:
1202 /*
1203 * Other components cannot have names.
1204 */
1205 break;
1206 }
1207 return (NULL);
1208}
1209
1210static const xmlChar*
1211xmlSchemaGetComponentQName(xmlChar **buf,
1212 void *item)
1213{
1214 return (xmlSchemaFormatQName(buf,
1215 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1216 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1217}
1218
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001219/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001220 * xmlSchemaWildcardPCToString:
1221 * @pc: the type of processContents
1222 *
1223 * Returns a string representation of the type of
1224 * processContents.
1225 */
1226static const xmlChar *
1227xmlSchemaWildcardPCToString(int pc)
1228{
1229 switch (pc) {
1230 case XML_SCHEMAS_ANY_SKIP:
1231 return (BAD_CAST "skip");
1232 case XML_SCHEMAS_ANY_LAX:
1233 return (BAD_CAST "lax");
1234 case XML_SCHEMAS_ANY_STRICT:
1235 return (BAD_CAST "strict");
1236 default:
1237 return (BAD_CAST "invalid process contents");
1238 }
1239}
1240
1241/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001242 * xmlSchemaFormatItemForReport:
1243 * @buf: the string buffer
1244 * @itemDes: the designation of the item
1245 * @itemName: the name of the item
1246 * @item: the item as an object
1247 * @itemNode: the node of the item
1248 * @local: the local name
1249 * @parsing: if the function is used during the parse
1250 *
1251 * Returns a representation of the given item used
1252 * for error reports.
1253 *
1254 * The following order is used to build the resulting
1255 * designation if the arguments are not NULL:
1256 * 1a. If itemDes not NULL -> itemDes
1257 * 1b. If (itemDes not NULL) and (itemName not NULL)
1258 * -> itemDes + itemName
1259 * 2. If the preceding was NULL and (item not NULL) -> item
1260 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1261 *
1262 * If the itemNode is an attribute node, the name of the attribute
1263 * will be appended to the result.
1264 *
1265 * Returns the formatted string and sets @buf to the resulting value.
1266 */
1267static xmlChar*
1268xmlSchemaFormatItemForReport(xmlChar **buf,
1269 const xmlChar *itemDes,
1270 xmlSchemaTypePtr item,
1271 xmlNodePtr itemNode,
1272 int parsing)
1273{
1274 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00001275 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001276
1277 if (*buf != NULL) {
1278 xmlFree(*buf);
1279 *buf = NULL;
1280 }
1281
William M. Brack2f2a6632004-08-20 23:09:47 +00001282 if (itemDes != NULL) {
1283 *buf = xmlStrdup(itemDes);
1284 } else if (item != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001285 switch (item->type) {
1286 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001287 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
1288 *buf = xmlStrdup(BAD_CAST "'anyType'");
1289 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
1290 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
1291 else {
1292 /* *buf = xmlStrdup(BAD_CAST "bi "); */
1293 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
1294 *buf = xmlStrdup(BAD_CAST "'");
1295 *buf = xmlStrcat(*buf, item->name);
1296 *buf = xmlStrcat(*buf, BAD_CAST "'");
1297 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001298 break;
1299 case XML_SCHEMA_TYPE_SIMPLE:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001300 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1301 *buf = xmlStrdup(xmlSchemaElemDesST);
1302 *buf = xmlStrcat(*buf, BAD_CAST " '");
1303 *buf = xmlStrcat(*buf, item->name);
1304 *buf = xmlStrcat(*buf, BAD_CAST "'");
1305 } else {
1306 *buf = xmlStrdup(xmlSchemaElemDesST);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001307 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001308 break;
1309 case XML_SCHEMA_TYPE_COMPLEX:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001310 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1311 *buf = xmlStrdup(xmlSchemaElemDesCT);
1312 *buf = xmlStrcat(*buf, BAD_CAST " '");
1313 *buf = xmlStrcat(*buf, item->name);
1314 *buf = xmlStrcat(*buf, BAD_CAST "'");
1315 } else {
1316 *buf = xmlStrdup(xmlSchemaElemDesCT);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001317 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001318 break;
1319 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1320 xmlSchemaAttributePtr attr;
1321
1322 attr = (xmlSchemaAttributePtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001323 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001324 (attr->ref == NULL)) {
1325 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1326 *buf = xmlStrcat(*buf, BAD_CAST " '");
1327 *buf = xmlStrcat(*buf, attr->name);
1328 *buf = xmlStrcat(*buf, BAD_CAST "'");
1329 } else {
1330 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1331 *buf = xmlStrcat(*buf, BAD_CAST " '");
1332 *buf = xmlStrcat(*buf, attr->refPrefix);
1333 *buf = xmlStrcat(*buf, BAD_CAST ":");
1334 *buf = xmlStrcat(*buf, attr->ref);
1335 *buf = xmlStrcat(*buf, BAD_CAST "'");
1336 }
1337 }
1338 break;
1339 case XML_SCHEMA_TYPE_ELEMENT: {
1340 xmlSchemaElementPtr elem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001341
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001342 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001343 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001344 (elem->ref == NULL)) {
1345 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1346 *buf = xmlStrcat(*buf, BAD_CAST " '");
1347 *buf = xmlStrcat(*buf, elem->name);
1348 *buf = xmlStrcat(*buf, BAD_CAST "'");
1349 } else {
1350 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
1351 *buf = xmlStrcat(*buf, BAD_CAST " '");
1352 *buf = xmlStrcat(*buf, elem->refPrefix);
1353 *buf = xmlStrcat(*buf, BAD_CAST ":");
1354 *buf = xmlStrcat(*buf, elem->ref);
1355 *buf = xmlStrcat(*buf, BAD_CAST "'");
1356 }
1357 }
1358 break;
1359 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1360 case XML_SCHEMA_TYPE_IDC_KEY:
1361 case XML_SCHEMA_TYPE_IDC_KEYREF:
1362 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1363 *buf = xmlStrdup(BAD_CAST "unique '");
1364 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1365 *buf = xmlStrdup(BAD_CAST "key '");
1366 else
1367 *buf = xmlStrdup(BAD_CAST "keyRef '");
1368 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1369 *buf = xmlStrcat(*buf, BAD_CAST "'");
1370 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001371 case XML_SCHEMA_TYPE_ANY:
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001372 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001373 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1374 ((xmlSchemaWildcardPtr) item)->processContents));
1375 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1376 break;
1377 case XML_SCHEMA_FACET_MININCLUSIVE:
1378 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1379 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1380 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1381 case XML_SCHEMA_FACET_TOTALDIGITS:
1382 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1383 case XML_SCHEMA_FACET_PATTERN:
1384 case XML_SCHEMA_FACET_ENUMERATION:
1385 case XML_SCHEMA_FACET_WHITESPACE:
1386 case XML_SCHEMA_FACET_LENGTH:
1387 case XML_SCHEMA_FACET_MAXLENGTH:
1388 case XML_SCHEMA_FACET_MINLENGTH:
1389 *buf = xmlStrdup(BAD_CAST "facet '");
1390 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1391 *buf = xmlStrcat(*buf, BAD_CAST "'");
1392 break;
1393 case XML_SCHEMA_TYPE_NOTATION:
1394 *buf = xmlStrdup(BAD_CAST "notation");
1395 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001396 case XML_SCHEMA_TYPE_GROUP: {
1397 xmlChar *s = NULL;
1398
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001399 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1400 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001401 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&s,
1402 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1403 ((xmlSchemaModelGroupDefPtr) item)->name));
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001404 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001405 FREE_AND_NULL(s)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001406 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001407 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001408 case XML_SCHEMA_TYPE_SEQUENCE:
1409 case XML_SCHEMA_TYPE_CHOICE:
1410 case XML_SCHEMA_TYPE_ALL:
1411 case XML_SCHEMA_TYPE_PARTICLE:
1412 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1413 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001414 default:
William M. Brack2f2a6632004-08-20 23:09:47 +00001415 named = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001416 }
William M. Brack2f2a6632004-08-20 23:09:47 +00001417 } else
1418 named = 0;
1419
1420 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00001421 xmlNodePtr elem;
1422
1423 if (itemNode->type == XML_ATTRIBUTE_NODE)
1424 elem = itemNode->parent;
1425 else
1426 elem = itemNode;
1427 *buf = xmlStrdup(BAD_CAST "Element '");
1428 if (parsing)
1429 *buf = xmlStrcat(*buf, elem->name);
1430 else
1431 *buf = xmlStrcat(*buf,
1432 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
1433 *buf = xmlStrcat(*buf, BAD_CAST "'");
1434 }
1435 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1436 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1437 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
1438 itemNode->ns, itemNode->name));
1439 *buf = xmlStrcat(*buf, BAD_CAST "'");
1440 }
1441 FREE_AND_NULL(str);
1442
1443 return (*buf);
1444}
1445
1446/**
1447 * xmlSchemaPFormatItemDes:
1448 * @buf: the string buffer
1449 * @item: the item as a schema object
1450 * @itemNode: the item as a node
1451 *
1452 * If the pointer to @buf is not NULL and @but holds no value,
1453 * the value is set to a item designation using
1454 * xmlSchemaFormatItemForReport. This one avoids adding
1455 * an attribute designation postfix.
1456 *
1457 * Returns a string of all enumeration elements.
1458 */
1459static void
1460xmlSchemaPRequestItemDes(xmlChar **buf,
1461 xmlSchemaTypePtr item,
1462 xmlNodePtr itemNode)
1463{
1464 if ((buf == 0) || (*buf != NULL))
1465 return;
1466 if (itemNode->type == XML_ATTRIBUTE_NODE)
1467 itemNode = itemNode->parent;
1468 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
1469}
1470
1471/**
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001472 * xmlSchemaGetCanonValueWhtsp:
1473 * @val: the precomputed value
1474 * @retValue: the returned value
1475 * @ws: the whitespace type of the value
1476 *
1477 * Get a the cononical representation of the value.
1478 * The caller has to free the returned retValue.
1479 *
1480 * Returns 0 if the value could be built and -1 in case of
1481 * API errors or if the value type is not supported yet.
1482 */
1483static int
1484xmlSchemaGetCanonValueWhtsp(const xmlChar *value,
1485 xmlSchemaValPtr val,
1486 xmlSchemaWhitespaceValueType ws,
1487 const xmlChar **retValue)
1488{
1489 xmlSchemaValType valType;
1490
1491 if ((retValue == NULL) || (value == NULL) || (val == NULL))
1492 return (-1);
1493 *retValue = NULL;
1494 valType = xmlSchemaGetValType(val);
1495 switch (valType) {
1496 case XML_SCHEMAS_STRING:
1497 if (value == NULL)
1498 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001499 else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1500 *retValue = xmlSchemaCollapseString(value);
1501 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1502 *retValue = xmlSchemaWhiteSpaceReplace(value);
1503 if ((*retValue) == NULL)
1504 *retValue = BAD_CAST xmlStrdup(value);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001505 break;
1506 case XML_SCHEMAS_NORMSTRING:
1507 if (value == NULL)
1508 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
1509 else {
1510 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1511 *retValue = xmlSchemaCollapseString(value);
1512 else
1513 *retValue = xmlSchemaWhiteSpaceReplace(value);
1514 if ((*retValue) == NULL)
1515 *retValue = BAD_CAST xmlStrdup(value);
1516 }
1517 break;
1518 default:
1519 return (xmlSchemaGetCanonValue(val, retValue));
1520 }
1521 return (0);
1522}
1523
1524/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001525 * xmlSchemaFormatFacetEnumSet:
1526 * @buf: the string buffer
1527 * @type: the type holding the enumeration facets
1528 *
1529 * Builds a string consisting of all enumeration elements.
1530 *
1531 * Returns a string of all enumeration elements.
1532 */
1533static const xmlChar *
1534xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
1535{
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001536 xmlSchemaFacetPtr facet;
1537 xmlSchemaWhitespaceValueType ws;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001538 const xmlChar *value = NULL;
1539 int res, found = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001540
1541 if (*buf != NULL)
1542 xmlFree(*buf);
1543 *buf = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001544
1545 do {
1546 /*
1547 * Use the whitespace type of the base type.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001548 */
1549 ws = (xmlSchemaWhitespaceValueType)
1550 xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001551 for (facet = type->facets; facet != NULL; facet = facet->next) {
1552 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1553 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001554 found = 1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001555 res = xmlSchemaGetCanonValueWhtsp(facet->value, facet->val,
1556 ws, &value);
1557 if (res == -1) {
1558 xmlSchemaVErr(NULL, NULL,
1559 XML_SCHEMAV_INTERNAL,
1560 "Internal error: xmlSchemaFormatFacetEnumSet, failed to "
1561 "compute the canonical lexical representation.\n",
1562 NULL, NULL);
1563 if (*buf != NULL)
1564 xmlFree(*buf);
1565 *buf = NULL;
1566 return (NULL);
1567 }
1568 if (*buf == NULL) {
1569 *buf = xmlStrdup(BAD_CAST "'");
1570 *buf = xmlStrcat(*buf, value);
1571 *buf = xmlStrcat(*buf, BAD_CAST "'");
1572 } else {
1573 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1574 *buf = xmlStrcat(*buf, value);
1575 *buf = xmlStrcat(*buf, BAD_CAST "'");
1576 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001577 if (value != NULL) {
1578 xmlFree((xmlChar *)value);
1579 value = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001580 }
1581 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001582 type = type->baseType;
1583 } while ((! found) && (type != NULL) &&
1584 (type->type != XML_SCHEMA_TYPE_BASIC));
1585
Daniel Veillardc0826a72004-08-10 14:17:33 +00001586 return ((const xmlChar *) *buf);
1587}
1588
1589/**
1590 * xmlSchemaVFacetErr:
1591 * @ctxt: the schema validation context
1592 * @error: the error code
1593 * @node: the node to be validated
1594 * @value: the value of the node
1595 * @type: the type holding the facet
1596 * @facet: the facet
1597 * @message: the error message of NULL
1598 * @str1: extra data
1599 * @str2: extra data
1600 * @str3: extra data
1601 *
1602 * Reports a facet validation error.
1603 * TODO: Should this report the value of an element as well?
1604 */
1605static void
1606xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
1607 xmlParserErrors error,
1608 xmlNodePtr node,
1609 const xmlChar *value,
1610 unsigned long length,
1611 xmlSchemaTypePtr type,
1612 xmlSchemaFacetPtr facet,
1613 const char *message,
1614 const xmlChar *str1,
1615 const xmlChar *str2,
1616 const xmlChar *str3)
1617{
1618 xmlChar *str = NULL, *msg = NULL;
1619 xmlSchemaTypeType facetType;
1620
1621 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1622 msg = xmlStrcat(msg, BAD_CAST " [");
1623 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1624 msg = xmlStrcat(msg, BAD_CAST ", facet '");
1625 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1626 facetType = XML_SCHEMA_FACET_ENUMERATION;
1627 /*
1628 * If enumerations are validated, one must not expect the
1629 * facet to be given.
1630 */
1631 } else
1632 facetType = facet->type;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001633 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001634 msg = xmlStrcat(msg, BAD_CAST "']: ");
1635 if (message == NULL) {
1636 /*
1637 * Use a default message.
1638 */
1639 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1640 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1641 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1642
1643 char len[25], actLen[25];
1644
1645 /* FIXME, TODO: What is the max expected string length of the
1646 * this value?
1647 */
1648 if (node->type == XML_ATTRIBUTE_NODE)
1649 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1650 else
1651 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1652
1653 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1654 snprintf(actLen, 24, "%lu", length);
1655
1656 if (facetType == XML_SCHEMA_FACET_LENGTH)
1657 msg = xmlStrcat(msg,
1658 BAD_CAST "this differs from the allowed length of '%s'.\n");
1659 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
1660 msg = xmlStrcat(msg,
1661 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
1662 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
1663 msg = xmlStrcat(msg,
1664 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
1665
1666 if (node->type == XML_ATTRIBUTE_NODE)
1667 xmlSchemaVErrExt(ctxt, node, error,
1668 (const char *) msg,
1669 value, (const xmlChar *) actLen, (const xmlChar *) len,
1670 NULL, NULL);
1671 else
1672 xmlSchemaVErr(ctxt, node, error,
1673 (const char *) msg,
1674 (const xmlChar *) actLen, (const xmlChar *) len);
1675
1676 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
1677 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
1678 "of the set {%s}.\n");
1679 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1680 xmlSchemaFormatFacetEnumSet(&str, type));
1681 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1682 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1683 "by the pattern '%s'.\n");
1684 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001685 facet->value);
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001686 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
1687 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
1688 "minimum value allowed ('%s').\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001689 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001690 facet->value);
1691 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
1692 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
1693 "maximum value allowed ('%s').\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001694 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001695 facet->value);
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001696 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
Daniel Veillardf3598452005-04-05 11:10:45 +00001697 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
1698 "'%s'.\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001699 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1700 facet->value);
1701 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
Daniel Veillardf3598452005-04-05 11:10:45 +00001702 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
1703 "'%s'.\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001704 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1705 facet->value);
Daniel Veillardf3598452005-04-05 11:10:45 +00001706 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001707 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
Daniel Veillardf3598452005-04-05 11:10:45 +00001708 "digits than are allowed ('%s').\n");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001709 xmlSchemaVErr(ctxt, node, error, (const char*) msg, value,
Daniel Veillardf3598452005-04-05 11:10:45 +00001710 facet->value);
1711 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001712 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
Daniel Veillardf3598452005-04-05 11:10:45 +00001713 "digits than are allowed ('%s').\n");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001714 xmlSchemaVErr(ctxt, node, error, (const char*) msg, value,
Daniel Veillardf3598452005-04-05 11:10:45 +00001715 facet->value);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001716 } else if (node->type == XML_ATTRIBUTE_NODE) {
1717 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00001718 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001719 } else {
1720 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1721 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1722 }
1723 } else {
1724 msg = xmlStrcat(msg, (const xmlChar *) message);
1725 msg = xmlStrcat(msg, BAD_CAST ".\n");
1726 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1727 }
1728 FREE_AND_NULL(str)
1729 xmlFree(msg);
1730}
1731
1732/**
1733 * xmlSchemaVSimpleTypeErr:
1734 * @ctxt: the schema validation context
1735 * @error: the error code
1736 * @type: the type used for validation
1737 * @node: the node containing the validated value
1738 * @value: the validated value
1739 *
1740 * Reports a simple type validation error.
1741 * TODO: Should this report the value of an element as well?
1742 */
1743static void
1744xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1745 xmlParserErrors error,
1746 xmlNodePtr node,
1747 const xmlChar *value,
1748 xmlSchemaTypePtr type)
1749{
1750 xmlChar *str = NULL, *msg = NULL;
1751
1752 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1753 msg = xmlStrcat(msg, BAD_CAST " [");
1754 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1755 if (node->type == XML_ATTRIBUTE_NODE) {
1756 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1757 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1758 } else {
1759 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1760 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1761 }
1762 FREE_AND_NULL(str)
1763 xmlFree(msg);
1764}
1765
1766/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001767 * xmlSchemaVComplexTypeErr:
1768 * @ctxt: the schema validation context
1769 * @error: the error code
1770 * @node: the node containing the validated value
1771 * @type: the complex type used for validation
1772 * @message: the error message
1773 *
1774 * Reports a complex type validation error.
1775 */
1776static void
1777xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1778 xmlParserErrors error,
1779 xmlNodePtr node,
1780 xmlSchemaTypePtr type,
1781 const char *message)
1782{
1783 xmlChar *str = NULL, *msg = NULL;
1784
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001785 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001786 /* Specify the complex type only if it is global. */
1787 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001788 msg = xmlStrcat(msg, BAD_CAST " [");
1789 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1790 msg = xmlStrcat(msg, BAD_CAST "]");
1791 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001792 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1793 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001794 (const xmlChar *) message, NULL);
1795 FREE_AND_NULL(str)
1796 xmlFree(msg);
1797}
1798
1799/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001800 * xmlSchemaVComplexTypeElemErr:
1801 * @ctxt: the schema validation context
1802 * @error: the error code
1803 * @node: the node containing the validated value
1804 * @type: the complex type used for validation
1805 * @message: the error message
1806 *
1807 * Reports a complex type validation error.
1808 */
1809static void
1810xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1811 xmlParserErrors error,
1812 xmlNodePtr node,
1813 xmlSchemaTypePtr type,
1814 const char *message,
1815 int nbval,
1816 int nbneg,
1817 xmlChar **values)
1818{
1819 xmlChar *str = NULL, *msg = NULL;
1820 xmlChar *localName, *nsName;
1821 const xmlChar *cur, *end;
1822 int i;
1823
1824 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1825 /* Specify the complex type only if it is global. */
1826 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1827 msg = xmlStrcat(msg, BAD_CAST " [");
1828 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1829 msg = xmlStrcat(msg, BAD_CAST "]");
1830 FREE_AND_NULL(str)
1831 }
1832 msg = xmlStrcat(msg, BAD_CAST ": ");
1833 msg = xmlStrcat(msg, (const xmlChar *) message);
1834 /*
1835 * Note that is does not make sense to report that we have a
1836 * wildcard here, since the wildcard might be unfolded into
1837 * multiple transitions.
1838 */
1839 if (nbval + nbneg > 0) {
1840 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001841 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001842 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001843 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001844 nsName = NULL;
1845
1846 for (i = 0; i < nbval + nbneg; i++) {
1847 cur = values[i];
1848 /*
1849 * Get the local name.
1850 */
1851 localName = NULL;
1852
1853 end = cur;
1854 if (*end == '*') {
1855 localName = xmlStrdup(BAD_CAST "*");
1856 *end++;
1857 } else {
1858 while ((*end != 0) && (*end != '|'))
1859 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001860 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001861 }
1862 if (*end != 0) {
1863 *end++;
1864 /*
1865 * Skip "*|*" if they come with negated expressions, since
1866 * they represent the same negated wildcard.
1867 */
1868 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1869 /*
1870 * Get the namespace name.
1871 */
1872 cur = end;
1873 if (*end == '*') {
1874 nsName = xmlStrdup(BAD_CAST "{*}");
1875 } else {
1876 while (*end != 0)
1877 end++;
1878
1879 if (i >= nbval)
1880 nsName = xmlStrdup(BAD_CAST "{##other:");
1881 else
1882 nsName = xmlStrdup(BAD_CAST "{");
1883
1884 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1885 nsName = xmlStrcat(nsName, BAD_CAST "}");
1886 }
1887 str = xmlStrcat(str, BAD_CAST nsName);
1888 FREE_AND_NULL(nsName)
1889 } else {
1890 FREE_AND_NULL(localName);
1891 continue;
1892 }
1893 }
1894 str = xmlStrcat(str, BAD_CAST localName);
1895 FREE_AND_NULL(localName);
1896
1897 if (i < nbval + nbneg -1)
1898 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001899 }
1900 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001901 msg = xmlStrcat(msg, BAD_CAST str);
1902 FREE_AND_NULL(str)
1903 }
1904 msg = xmlStrcat(msg, BAD_CAST ".\n");
1905 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1906 xmlFree(msg);
1907}
1908
1909/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001910 * xmlSchemaPMissingAttrErr:
1911 * @ctxt: the schema validation context
1912 * @ownerDes: the designation of the owner
1913 * @ownerName: the name of the owner
1914 * @ownerItem: the owner as a schema object
1915 * @ownerElem: the owner as an element node
1916 * @node: the parent element node of the missing attribute node
1917 * @type: the corresponding type of the attribute node
1918 *
1919 * Reports an illegal attribute.
1920 */
1921static void
1922xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1923 xmlParserErrors error,
1924 xmlChar **ownerDes,
1925 xmlSchemaTypePtr ownerItem,
1926 xmlNodePtr ownerElem,
1927 const char *name,
1928 const char *message)
1929{
1930 xmlChar *des = NULL;
1931
1932 if (ownerDes == NULL)
1933 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1934 else if (*ownerDes == NULL) {
1935 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1936 des = *ownerDes;
1937 } else
1938 des = *ownerDes;
1939 if (message != NULL)
1940 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1941 else
1942 xmlSchemaPErr(ctxt, ownerElem, error,
1943 "%s: The attribute '%s' is required but missing.\n",
1944 BAD_CAST des, BAD_CAST name);
1945 if (ownerDes == NULL)
1946 FREE_AND_NULL(des);
1947}
1948
William M. Brack2f2a6632004-08-20 23:09:47 +00001949/**
1950 * xmlSchemaCompTypeToString:
1951 * @type: the type of the schema item
1952 *
1953 * Returns the component name of a schema item.
1954 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001955static const xmlChar *
Daniel Veillardc0826a72004-08-10 14:17:33 +00001956xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1957{
1958 switch (type) {
1959 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001960 return(BAD_CAST "simple type definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001961 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001962 return(BAD_CAST "complex type definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001963 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001964 return(BAD_CAST "element declaration");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001965 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001966 return(BAD_CAST "attribute declaration");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001967 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001968 return(BAD_CAST "model group definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001969 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001970 return(BAD_CAST "attribute group definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001971 case XML_SCHEMA_TYPE_NOTATION:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001972 return(BAD_CAST "notation declaration");
1973 case XML_SCHEMA_TYPE_SEQUENCE:
1974 return(BAD_CAST "model group (sequence)");
1975 case XML_SCHEMA_TYPE_CHOICE:
1976 return(BAD_CAST "model group (choice)");
1977 case XML_SCHEMA_TYPE_ALL:
1978 return(BAD_CAST "model group (all)");
1979 case XML_SCHEMA_TYPE_PARTICLE:
1980 return(BAD_CAST "particle");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001981 default:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001982 return(BAD_CAST "Not a schema component");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001983 }
1984}
1985/**
1986 * xmlSchemaPResCompAttrErr:
1987 * @ctxt: the schema validation context
1988 * @error: the error code
1989 * @ownerDes: the designation of the owner
1990 * @ownerItem: the owner as a schema object
1991 * @ownerElem: the owner as an element node
1992 * @name: the name of the attribute holding the QName
1993 * @refName: the referenced local name
1994 * @refURI: the referenced namespace URI
1995 * @message: optional message
1996 *
1997 * Used to report QName attribute values that failed to resolve
1998 * to schema components.
1999 */
2000static void
2001xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2002 xmlParserErrors error,
2003 xmlChar **ownerDes,
2004 xmlSchemaTypePtr ownerItem,
2005 xmlNodePtr ownerElem,
2006 const char *name,
2007 const xmlChar *refName,
2008 const xmlChar *refURI,
2009 xmlSchemaTypeType refType,
2010 const char *refTypeStr)
2011{
2012 xmlChar *des = NULL, *strA = NULL;
2013
2014 if (ownerDes == NULL)
2015 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
2016 else if (*ownerDes == NULL) {
2017 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
2018 des = *ownerDes;
2019 } else
2020 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002021 if (refTypeStr == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002022 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002023 xmlSchemaPErrExt(ctxt, ownerElem, error,
2024 NULL, NULL, NULL,
2025 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
2026 "%s.\n", BAD_CAST des, BAD_CAST name,
2027 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
2028 BAD_CAST refTypeStr, NULL);
2029 if (ownerDes == NULL)
2030 FREE_AND_NULL(des)
2031 FREE_AND_NULL(strA)
2032}
2033
William M. Brack2f2a6632004-08-20 23:09:47 +00002034/**
2035 * xmlSchemaPCustomAttrErr:
2036 * @ctxt: the schema parser context
2037 * @error: the error code
2038 * @ownerDes: the designation of the owner
2039 * @ownerItem: the owner as a schema object
2040 * @attr: the illegal attribute node
2041 *
2042 * Reports an illegal attribute during the parse.
2043 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002044static void
2045xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00002046 xmlParserErrors error,
2047 xmlChar **ownerDes,
2048 xmlSchemaTypePtr ownerItem,
2049 xmlAttrPtr attr,
2050 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002051{
2052 xmlChar *des = NULL;
2053
2054 if (ownerDes == NULL)
2055 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2056 else if (*ownerDes == NULL) {
2057 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2058 des = *ownerDes;
2059 } else
2060 des = *ownerDes;
2061 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2062 "%s, attribute '%s': %s.\n",
2063 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2064 if (ownerDes == NULL)
2065 FREE_AND_NULL(des);
2066}
2067
2068/**
2069 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002070 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002071 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002072 * @ownerDes: the designation of the attribute's owner
2073 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00002074 * @attr: the illegal attribute node
2075 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002076 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002077 */
2078static void
2079xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2080 xmlParserErrors error,
2081 xmlChar **ownerDes,
2082 xmlSchemaTypePtr ownerItem,
2083 xmlAttrPtr attr)
2084{
2085 xmlChar *des = NULL, *strA = NULL;
2086
2087 if (ownerDes == NULL)
2088 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2089 else if (*ownerDes == NULL) {
2090 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2091 des = *ownerDes;
2092 } else
2093 des = *ownerDes;
2094 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2095 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2096 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2097 if (ownerDes == NULL)
2098 FREE_AND_NULL(des);
2099 FREE_AND_NULL(strA);
2100}
2101
William M. Brack2f2a6632004-08-20 23:09:47 +00002102/**
2103 * xmlSchemaPAquireDes:
2104 * @des: the first designation
2105 * @itemDes: the second designation
2106 * @item: the schema item
2107 * @itemElem: the node of the schema item
2108 *
2109 * Creates a designation for an item.
2110 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002111static void
2112xmlSchemaPAquireDes(xmlChar **des,
2113 xmlChar **itemDes,
2114 xmlSchemaTypePtr item,
2115 xmlNodePtr itemElem)
2116{
2117 if (itemDes == NULL)
2118 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
2119 else if (*itemDes == NULL) {
2120 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
2121 *des = *itemDes;
2122 } else
2123 *des = *itemDes;
2124}
2125
William M. Brack2f2a6632004-08-20 23:09:47 +00002126/**
2127 * xmlSchemaPCustomErr:
2128 * @ctxt: the schema parser context
2129 * @error: the error code
2130 * @itemDes: the designation of the schema item
2131 * @item: the schema item
2132 * @itemElem: the node of the schema item
2133 * @message: the error message
2134 * @str1: an optional param for the error message
2135 * @str2: an optional param for the error message
2136 * @str3: an optional param for the error message
2137 *
2138 * Reports an error during parsing.
2139 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002140static void
2141xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2142 xmlParserErrors error,
2143 xmlChar **itemDes,
2144 xmlSchemaTypePtr item,
2145 xmlNodePtr itemElem,
2146 const char *message,
2147 const xmlChar *str1,
2148 const xmlChar *str2,
2149 const xmlChar *str3)
2150{
2151 xmlChar *des = NULL, *msg = NULL;
2152
2153 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
2154 msg = xmlStrdup(BAD_CAST "%s: ");
2155 msg = xmlStrcat(msg, (const xmlChar *) message);
2156 msg = xmlStrcat(msg, BAD_CAST ".\n");
2157 if ((itemElem == NULL) && (item != NULL))
2158 itemElem = item->node;
2159 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2160 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2161 if (itemDes == NULL)
2162 FREE_AND_NULL(des);
2163 FREE_AND_NULL(msg);
2164}
2165
William M. Brack2f2a6632004-08-20 23:09:47 +00002166/**
2167 * xmlSchemaPCustomErr:
2168 * @ctxt: the schema parser context
2169 * @error: the error code
2170 * @itemDes: the designation of the schema item
2171 * @item: the schema item
2172 * @itemElem: the node of the schema item
2173 * @message: the error message
2174 * @str1: the optional param for the error message
2175 *
2176 * Reports an error during parsing.
2177 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002178static void
2179xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2180 xmlParserErrors error,
2181 xmlChar **itemDes,
2182 xmlSchemaTypePtr item,
2183 xmlNodePtr itemElem,
2184 const char *message,
2185 const xmlChar *str1)
2186{
2187 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2188 str1, NULL, NULL);
2189}
2190
William M. Brack2f2a6632004-08-20 23:09:47 +00002191/**
2192 * xmlSchemaPAttrUseErr:
2193 * @ctxt: the schema parser context
2194 * @error: the error code
2195 * @itemDes: the designation of the schema type
2196 * @item: the schema type
2197 * @itemElem: the node of the schema type
2198 * @attr: the invalid schema attribute
2199 * @message: the error message
2200 * @str1: the optional param for the error message
2201 *
2202 * Reports an attribute use error during parsing.
2203 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002204static void
2205xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
2206 xmlParserErrors error,
2207 xmlChar **itemDes,
2208 xmlSchemaTypePtr item,
2209 xmlNodePtr itemElem,
2210 const xmlSchemaAttributePtr attr,
2211 const char *message,
2212 const xmlChar *str1)
2213{
2214 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
2215
2216 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
2217 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
2218 xmlSchemaGetAttrName(attr));
2219 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
2220 msg = xmlStrcat(msg, (const xmlChar *) message);
2221 msg = xmlStrcat(msg, BAD_CAST ".\n");
2222 if ((itemElem == NULL) && (item != NULL))
2223 itemElem = item->node;
2224 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2225 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
2226 if (itemDes == NULL)
2227 FREE_AND_NULL(des);
2228 FREE_AND_NULL(strA);
2229 xmlFree(msg);
2230}
2231
William M. Brack2f2a6632004-08-20 23:09:47 +00002232/**
2233 * xmlSchemaPIllegalFacetAtomicErr:
2234 * @ctxt: the schema parser context
2235 * @error: the error code
2236 * @itemDes: the designation of the type
2237 * @item: the schema type
2238 * @baseItem: the base type of type
2239 * @facet: the illegal facet
2240 *
2241 * Reports an illegal facet for atomic simple types.
2242 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002243static void
2244xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
2245 xmlParserErrors error,
2246 xmlChar **itemDes,
2247 xmlSchemaTypePtr item,
2248 xmlSchemaTypePtr baseItem,
2249 xmlSchemaFacetPtr facet)
2250{
2251 xmlChar *des = NULL, *strT = NULL;
2252
2253 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2254 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2255 "%s: The facet '%s' is not allowed on types derived from the "
2256 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002257 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002258 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
2259 NULL, NULL);
2260 if (itemDes == NULL)
2261 FREE_AND_NULL(des);
2262 FREE_AND_NULL(strT);
2263}
2264
William M. Brack2f2a6632004-08-20 23:09:47 +00002265/**
2266 * xmlSchemaPIllegalFacetListUnionErr:
2267 * @ctxt: the schema parser context
2268 * @error: the error code
2269 * @itemDes: the designation of the schema item involved
2270 * @item: the schema item involved
2271 * @facet: the illegal facet
2272 *
2273 * Reports an illegal facet for <list> and <union>.
2274 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002275static void
2276xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
2277 xmlParserErrors error,
2278 xmlChar **itemDes,
2279 xmlSchemaTypePtr item,
2280 xmlSchemaFacetPtr facet)
2281{
2282 xmlChar *des = NULL, *strT = NULL;
2283
2284 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2285 xmlSchemaPErr(ctxt, item->node, error,
2286 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002287 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002288 if (itemDes == NULL)
2289 FREE_AND_NULL(des);
2290 FREE_AND_NULL(strT);
2291}
2292
2293/**
2294 * xmlSchemaPMutualExclAttrErr:
2295 * @ctxt: the schema validation context
2296 * @error: the error code
2297 * @elemDes: the designation of the parent element node
2298 * @attr: the bad attribute node
2299 * @type: the corresponding type of the attribute node
2300 *
2301 * Reports an illegal attribute.
2302 */
2303static void
2304xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2305 xmlParserErrors error,
2306 xmlChar **ownerDes,
2307 xmlSchemaTypePtr ownerItem,
2308 xmlAttrPtr attr,
2309 const char *name1,
2310 const char *name2)
2311{
2312 xmlChar *des = NULL;
2313
2314 if (ownerDes == NULL)
2315 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2316 else if (*ownerDes == NULL) {
2317 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2318 des = *ownerDes;
2319 } else
2320 des = *ownerDes;
2321 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2322 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
2323 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2324 if (ownerDes == NULL)
2325 FREE_AND_NULL(des)
2326}
2327
2328/**
2329 * xmlSchemaPSimpleTypeErr:
2330 * @ctxt: the schema validation context
2331 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002332 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002333 * @ownerDes: the designation of the owner
2334 * @ownerItem: the schema object if existent
2335 * @node: the validated node
2336 * @value: the validated value
2337 *
2338 * Reports a simple type validation error.
2339 * TODO: Should this report the value of an element as well?
2340 */
2341static void
2342xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2343 xmlParserErrors error,
2344 xmlChar **ownerDes,
2345 xmlSchemaTypePtr ownerItem,
2346 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002347 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002348 const char *typeDes,
2349 const xmlChar *value,
2350 const char *message,
2351 const xmlChar *str1,
2352 const xmlChar *str2)
2353{
William M. Brack2f2a6632004-08-20 23:09:47 +00002354 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002355
2356 if (ownerDes == NULL)
2357 xmlSchemaPRequestItemDes(&des, ownerItem, node);
2358 else if (*ownerDes == NULL) {
2359 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
2360 des = *ownerDes;
2361 } else
2362 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00002363 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002364 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002365 if (message == NULL) {
2366 /*
2367 * Use default messages.
2368 */
2369 if (node->type == XML_ATTRIBUTE_NODE) {
2370 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2371 "%s, attribute '%s' [%s]: The value '%s' is not "
2372 "valid.\n",
2373 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
2374 node->name), BAD_CAST typeDes, value, NULL);
2375 } else {
2376 xmlSchemaPErr(ctxt, node, error,
2377 "%s [%s]: The character content is not valid.\n",
2378 BAD_CAST des, BAD_CAST typeDes);
2379 }
2380 } else {
2381 xmlChar *msg;
2382
2383 msg = xmlStrdup(BAD_CAST "%s");
2384 if (node->type == XML_ATTRIBUTE_NODE)
2385 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
2386 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
2387 msg = xmlStrcat(msg, (const xmlChar *) message);
2388 msg = xmlStrcat(msg, BAD_CAST ".\n");
2389 if (node->type == XML_ATTRIBUTE_NODE) {
2390 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2391 (const char *) msg,
2392 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
2393 node->ns, node->name), BAD_CAST typeDes, str1, str2);
2394 } else {
2395 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2396 (const char *) msg,
2397 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
2398 }
2399 xmlFree(msg);
2400 }
2401 /* Cleanup. */
2402 FREE_AND_NULL(strA)
2403 FREE_AND_NULL(strT)
2404 if (ownerDes == NULL)
2405 FREE_AND_NULL(des)
2406}
2407
William M. Brack2f2a6632004-08-20 23:09:47 +00002408/**
2409 * xmlSchemaPContentErr:
2410 * @ctxt: the schema parser context
2411 * @error: the error code
2412 * @onwerDes: the designation of the holder of the content
2413 * @ownerItem: the owner item of the holder of the content
2414 * @ownerElem: the node of the holder of the content
2415 * @child: the invalid child node
2416 * @message: the optional error message
2417 * @content: the optional string describing the correct content
2418 *
2419 * Reports an error concerning the content of a schema element.
2420 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002421static void
2422xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
2423 xmlParserErrors error,
2424 xmlChar **ownerDes,
2425 xmlSchemaTypePtr ownerItem,
2426 xmlNodePtr ownerElem,
2427 xmlNodePtr child,
2428 const char *message,
2429 const char *content)
2430{
2431 xmlChar *des = NULL;
2432
2433 if (ownerDes == NULL)
2434 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
2435 else if (*ownerDes == NULL) {
2436 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
2437 des = *ownerDes;
2438 } else
2439 des = *ownerDes;
2440 if (message != NULL)
2441 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2442 "%s: %s.\n",
2443 BAD_CAST des, BAD_CAST message);
2444 else {
2445 if (content != NULL) {
2446 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2447 "%s: The content is not valid. Expected is %s.\n",
2448 BAD_CAST des, BAD_CAST content);
2449 } else {
2450 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2451 "%s: The content is not valid.\n",
2452 BAD_CAST des, NULL);
2453 }
2454 }
2455 if (ownerDes == NULL)
2456 FREE_AND_NULL(des)
2457}
2458
2459/**
2460 * xmlSchemaVIllegalAttrErr:
2461 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002462 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00002463 * @attr: the illegal attribute node
2464 *
2465 * Reports an illegal attribute.
2466 */
2467static void
2468xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002469 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002470 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002471{
2472 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002473
2474 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
2475 error,
2476 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002477 "%s: The attribute '%s' is not allowed.\n",
2478 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
2479 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2480 FREE_AND_NULL(strE)
2481 FREE_AND_NULL(strA)
2482}
2483
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002484
2485static int
2486xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2487{
2488 switch (item->type) {
2489 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002490 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002491 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2492 return(1);
2493 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002494 case XML_SCHEMA_TYPE_GROUP:
2495 return (1);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002496 case XML_SCHEMA_TYPE_ELEMENT:
2497 if ( ((xmlSchemaElementPtr) item)->flags &
2498 XML_SCHEMAS_ELEM_GLOBAL)
2499 return(1);
2500 break;
2501 case XML_SCHEMA_TYPE_ATTRIBUTE:
2502 if ( ((xmlSchemaAttributePtr) item)->flags &
2503 XML_SCHEMAS_ATTR_GLOBAL)
2504 return(1);
2505 break;
2506 /* Note that attribute groups are always global. */
2507 default:
2508 return(1);
2509 }
2510 return (0);
2511}
2512
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002513
2514static void
2515xmlSchemaStreamVCustomErr(xmlSchemaValidCtxtPtr vctxt,
2516 xmlParserErrors error,
2517 xmlSchemaNodeInfoPtr nodeInfo,
2518 xmlSchemaTypePtr type,
2519 const char *message,
2520 const xmlChar *str1,
2521 const xmlChar *str2)
2522{
2523 xmlChar *msg = NULL, *str = NULL;
2524
2525 msg = xmlStrdup(BAD_CAST "Element '");
2526
2527 if (vctxt->elemInfos[vctxt->depth] != nodeInfo) {
2528 xmlSchemaNodeInfoPtr elemInfo;
2529 /*
2530 * The node info is an attribute info.
2531 */
2532 elemInfo = vctxt->elemInfos[vctxt->depth];
2533 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2534 elemInfo->namespaceName, elemInfo->localName));
2535 msg = xmlStrcat(msg, BAD_CAST "', ");
2536 msg = xmlStrcat(msg, BAD_CAST "attribute '");
2537 }
2538 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2539 nodeInfo->namespaceName, nodeInfo->localName));
2540 msg = xmlStrcat(msg, BAD_CAST "'");
2541
2542 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2543 msg = xmlStrcat(msg, BAD_CAST " [");
2544 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str,
2545 NULL, type, NULL, 0));
2546 msg = xmlStrcat(msg, BAD_CAST "]");
2547 }
2548 msg = xmlStrcat(msg, BAD_CAST ": ");
2549
2550 msg = xmlStrcat(msg, (const xmlChar *) message);
2551 msg = xmlStrcat(msg, BAD_CAST ".\n");
2552 xmlSchemaVErr(vctxt, nodeInfo->node, error, (const char *) msg,
2553 str1, str2);
2554 FREE_AND_NULL(msg)
2555 FREE_AND_NULL(str)
2556}
2557
William M. Brack2f2a6632004-08-20 23:09:47 +00002558/**
2559 * xmlSchemaVCustomErr:
2560 * @ctxt: the schema validation context
2561 * @error: the error code
2562 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002563 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00002564 * @message: the error message
2565 * @str1: the optional param for the message
2566 *
2567 * Reports a validation error.
2568 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002569static void
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00002570xmlSchemaVCustomErrExt(xmlSchemaValidCtxtPtr ctxt,
2571 xmlParserErrors error,
2572 xmlNodePtr node,
2573 xmlSchemaTypePtr type,
2574 const char *message,
2575 const xmlChar *str1,
2576 const xmlChar *str2,
2577 const xmlChar *str3)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002578{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002579 xmlChar *msg = NULL, *str = NULL;
2580
2581 if (node == NULL) {
2582 xmlSchemaVErr(ctxt, NULL,
2583 XML_SCHEMAV_INTERNAL,
2584 "Internal error: xmlSchemaVCustomErr, no node "
2585 "given.\n", NULL, NULL);
2586 return;
2587 }
2588 /* TODO: Are the HTML and DOCB doc nodes expected here? */
2589 if (node->type != XML_DOCUMENT_NODE) {
2590 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002591 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002592 msg = xmlStrcat(msg, BAD_CAST " [");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00002593 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL,
2594 type, NULL, 0));
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002595 msg = xmlStrcat(msg, BAD_CAST "]");
2596 }
2597 msg = xmlStrcat(msg, BAD_CAST ": ");
2598 } else
2599 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002600 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002601 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00002602 xmlSchemaVErrExt(ctxt, node, error, (const char *) msg, str1, str2,
2603 str3, NULL, NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002604 FREE_AND_NULL(msg)
2605 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002606}
2607
William M. Brack2f2a6632004-08-20 23:09:47 +00002608/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00002609 * xmlSchemaVCustomErr:
2610 * @ctxt: the schema validation context
2611 * @error: the error code
2612 * @node: the validated node
2613 * @type: the schema type of the validated node
2614 * @message: the error message
2615 * @str1: the optional param for the message
2616 *
2617 * Reports a validation error.
2618 */
2619static void
2620xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
2621 xmlParserErrors error,
2622 xmlNodePtr node,
2623 xmlSchemaTypePtr type,
2624 const char *message,
2625 const xmlChar *str1)
2626{
2627 xmlSchemaVCustomErrExt(ctxt, error, node, type, message, str1, NULL, NULL);
2628}
2629
2630/**
William M. Brack2f2a6632004-08-20 23:09:47 +00002631 * xmlSchemaVWildcardErr:
2632 * @ctxt: the schema validation context
2633 * @error: the error code
2634 * @node: the validated node
2635 * @wild: the wildcard used
2636 * @message: the error message
2637 *
2638 * Reports an validation-by-wildcard error.
2639 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002640static void
2641xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
2642 xmlParserErrors error,
2643 xmlNodePtr node,
2644 xmlSchemaWildcardPtr wild,
2645 const char *message)
2646{
2647 xmlChar *des = NULL, *msg = NULL;
2648
2649 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00002650 msg = xmlStrdup(BAD_CAST "%s [");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002651 msg = xmlStrcat(msg, xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002652 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002653 msg = xmlStrcat(msg, (const xmlChar *) message);
2654 msg = xmlStrcat(msg, BAD_CAST ".\n");
2655 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
2656 FREE_AND_NULL(des);
2657 FREE_AND_NULL(msg);
2658}
2659
2660/**
2661 * xmlSchemaVMissingAttrErr:
2662 * @ctxt: the schema validation context
2663 * @node: the parent element node of the missing attribute node
2664 * @type: the corresponding type of the attribute node
2665 *
2666 * Reports an illegal attribute.
2667 */
2668static void
2669xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
2670 xmlNodePtr elem,
2671 xmlSchemaAttributePtr type)
2672{
2673 const xmlChar *name, *uri;
2674 xmlChar *strE = NULL, *strA = NULL;
2675
2676 if (type->ref != NULL) {
2677 name = type->ref;
2678 uri = type->refNs;
2679 } else {
2680 name = type->name;
2681 uri = type->targetNamespace;
2682 }
2683 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002684 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
2685 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002686 "%s: The attribute %s is required but missing.\n",
2687 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
2688 xmlSchemaFormatNsUriLocal(&strA, uri, name));
2689 FREE_AND_NULL(strE)
2690 FREE_AND_NULL(strA)
2691}
2692
Daniel Veillard4255d502002-04-16 15:50:10 +00002693/************************************************************************
2694 * *
2695 * Allocation functions *
2696 * *
2697 ************************************************************************/
2698
2699/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002700 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002701 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002702 *
2703 * Allocate a new Schema structure.
2704 *
2705 * Returns the newly allocated structure or NULL in case or error
2706 */
2707static xmlSchemaPtr
2708xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2709{
2710 xmlSchemaPtr ret;
2711
2712 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2713 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002714 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002715 return (NULL);
2716 }
2717 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002718 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002719 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002720
2721 return (ret);
2722}
2723
2724/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002725 * xmlSchemaNewSchema:
2726 * @ctxt: a schema validation context
2727 *
2728 * Allocate a new Schema structure.
2729 *
2730 * Returns the newly allocated structure or NULL in case or error
2731 */
2732static xmlSchemaAssemblePtr
2733xmlSchemaNewAssemble(void)
2734{
2735 xmlSchemaAssemblePtr ret;
2736
2737 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2738 if (ret == NULL) {
2739 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2740 return (NULL);
2741 }
2742 memset(ret, 0, sizeof(xmlSchemaAssemble));
2743 ret->items = NULL;
2744 return (ret);
2745}
2746
2747/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002748 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002749 *
2750 * Allocate a new Facet structure.
2751 *
2752 * Returns the newly allocated structure or NULL in case or error
2753 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002754xmlSchemaFacetPtr
2755xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002756{
2757 xmlSchemaFacetPtr ret;
2758
2759 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2760 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002761 return (NULL);
2762 }
2763 memset(ret, 0, sizeof(xmlSchemaFacet));
2764
2765 return (ret);
2766}
2767
2768/**
2769 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002770 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002771 * @node: a node
2772 *
2773 * Allocate a new annotation structure.
2774 *
2775 * Returns the newly allocated structure or NULL in case or error
2776 */
2777static xmlSchemaAnnotPtr
2778xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2779{
2780 xmlSchemaAnnotPtr ret;
2781
2782 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2783 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002784 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002785 return (NULL);
2786 }
2787 memset(ret, 0, sizeof(xmlSchemaAnnot));
2788 ret->content = node;
2789 return (ret);
2790}
2791
2792/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002793 * xmlSchemaFreeAnnot:
2794 * @annot: a schema type structure
2795 *
2796 * Deallocate a annotation structure
2797 */
2798static void
2799xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2800{
2801 if (annot == NULL)
2802 return;
2803 xmlFree(annot);
2804}
2805
2806/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002807 * xmlSchemaFreeImport:
2808 * @import: a schema import structure
2809 *
2810 * Deallocate an import structure
2811 */
2812static void
2813xmlSchemaFreeImport(xmlSchemaImportPtr import)
2814{
2815 if (import == NULL)
2816 return;
2817
2818 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002819 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002820 xmlFree(import);
2821}
2822
2823/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002824 * xmlSchemaFreeInclude:
2825 * @include: a schema include structure
2826 *
2827 * Deallocate an include structure
2828 */
2829static void
2830xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2831{
2832 if (include == NULL)
2833 return;
2834
2835 xmlFreeDoc(include->doc);
2836 xmlFree(include);
2837}
2838
2839/**
2840 * xmlSchemaFreeIncludeList:
2841 * @includes: a schema include list
2842 *
2843 * Deallocate an include structure
2844 */
2845static void
2846xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2847{
2848 xmlSchemaIncludePtr next;
2849
2850 while (includes != NULL) {
2851 next = includes->next;
2852 xmlSchemaFreeInclude(includes);
2853 includes = next;
2854 }
2855}
2856
2857/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002858 * xmlSchemaFreeNotation:
2859 * @schema: a schema notation structure
2860 *
2861 * Deallocate a Schema Notation structure.
2862 */
2863static void
2864xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2865{
2866 if (nota == NULL)
2867 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002868 xmlFree(nota);
2869}
2870
2871/**
2872 * xmlSchemaFreeAttribute:
2873 * @schema: a schema attribute structure
2874 *
2875 * Deallocate a Schema Attribute structure.
2876 */
2877static void
2878xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2879{
2880 if (attr == NULL)
2881 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002882 if (attr->annot != NULL)
2883 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002884 if (attr->defVal != NULL)
2885 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002886 xmlFree(attr);
2887}
2888
2889/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002890 * xmlSchemaFreeWildcardNsSet:
2891 * set: a schema wildcard namespace
2892 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002893 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002894 */
2895static void
2896xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2897{
2898 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002899
Daniel Veillard3646d642004-06-02 19:19:14 +00002900 while (set != NULL) {
2901 next = set->next;
2902 xmlFree(set);
2903 set = next;
2904 }
2905}
2906
2907/**
2908 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002909 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002910 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002911 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002912 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002913void
Daniel Veillard3646d642004-06-02 19:19:14 +00002914xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2915{
2916 if (wildcard == NULL)
2917 return;
2918 if (wildcard->annot != NULL)
2919 xmlSchemaFreeAnnot(wildcard->annot);
2920 if (wildcard->nsSet != NULL)
2921 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2922 if (wildcard->negNsSet != NULL)
2923 xmlFree(wildcard->negNsSet);
2924 xmlFree(wildcard);
2925}
2926
2927/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002928 * xmlSchemaFreeAttributeGroup:
2929 * @schema: a schema attribute group structure
2930 *
2931 * Deallocate a Schema Attribute Group structure.
2932 */
2933static void
2934xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2935{
2936 if (attr == NULL)
2937 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002938 if (attr->annot != NULL)
2939 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002940 xmlFree(attr);
2941}
2942
2943/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002944 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002945 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002946 *
2947 * Deallocate a list of schema attribute uses.
2948 */
2949static void
2950xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2951{
2952 xmlSchemaAttributeLinkPtr next;
2953
2954 while (attrUse != NULL) {
2955 next = attrUse->next;
2956 xmlFree(attrUse);
2957 attrUse = next;
2958 }
2959}
2960
2961/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002962 * xmlSchemaFreeQNameRef:
2963 * @item: a QName reference structure
2964 *
2965 * Deallocatea a QName reference structure.
2966 */
2967static void
2968xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
2969{
2970 xmlFree(item);
2971}
2972
2973static int
2974xmlSchemaAddVolatile(xmlSchemaPtr schema,
2975 xmlSchemaBasicItemPtr item)
2976{
2977 xmlSchemaItemListPtr list;
2978
2979 if (schema->volatiles == NULL) {
2980 schema->volatiles = (void *) xmlMalloc(sizeof(xmlSchemaItemList));
2981 if (schema->volatiles == NULL) {
2982 xmlSchemaPErrMemory(NULL,
2983 "allocating list of volatiles", NULL);
2984 return (-1);
2985 }
2986 memset(schema->volatiles, 0, sizeof(xmlSchemaItemList));
2987
2988 }
2989 list = (xmlSchemaItemListPtr) schema->volatiles;
2990 if (list->items == NULL) {
2991 list->items = (void **) xmlMalloc(
2992 20 * sizeof(xmlSchemaBasicItemPtr));
2993 if (list->items == NULL) {
2994 xmlSchemaPErrMemory(NULL,
2995 "allocating new volatile item buffer", NULL);
2996 return (-1);
2997 }
2998 list->sizeItems = 20;
2999 } else if (list->sizeItems <= list->nbItems) {
3000 list->sizeItems *= 2;
3001 list->items = (void **) xmlRealloc(list->items,
3002 list->sizeItems * sizeof(xmlSchemaTypePtr));
3003 if (list->items == NULL) {
3004 xmlSchemaPErrMemory(NULL,
3005 "growing volatile item buffer", NULL);
3006 list->sizeItems = 0;
3007 return (-1);
3008 }
3009 }
3010 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3011 return (0);
3012}
3013
3014/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003015 * xmlSchemaFreeTypeLinkList:
3016 * @alink: a type link
3017 *
3018 * Deallocate a list of types.
3019 */
3020static void
3021xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3022{
3023 xmlSchemaTypeLinkPtr next;
3024
3025 while (link != NULL) {
3026 next = link->next;
3027 xmlFree(link);
3028 link = next;
3029 }
3030}
3031
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003032static void
3033xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3034{
3035 xmlSchemaIDCStateObjPtr next;
3036 while (sto != NULL) {
3037 next = sto->next;
3038 if (sto->history != NULL)
3039 xmlFree(sto->history);
3040 if (sto->xpathCtxt != NULL)
3041 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3042 xmlFree(sto);
3043 sto = next;
3044 }
3045}
3046
3047/**
3048 * xmlSchemaFreeIDC:
3049 * @idc: a identity-constraint definition
3050 *
3051 * Deallocates an identity-constraint definition.
3052 */
3053static void
3054xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3055{
3056 xmlSchemaIDCSelectPtr cur, prev;
3057
3058 if (idcDef == NULL)
3059 return;
3060 if (idcDef->annot != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003061 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003062 /* Selector */
3063 if (idcDef->selector != NULL) {
3064 if (idcDef->selector->xpathComp != NULL)
3065 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3066 xmlFree(idcDef->selector);
3067 }
3068 /* Fields */
3069 if (idcDef->fields != NULL) {
3070 cur = idcDef->fields;
3071 do {
3072 prev = cur;
3073 cur = cur->next;
3074 if (prev->xpathComp != NULL)
3075 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3076 xmlFree(prev);
3077 } while (cur != NULL);
3078 }
3079 xmlFree(idcDef);
3080}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003081
Daniel Veillard01fa6152004-06-29 17:04:39 +00003082/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003083 * xmlSchemaFreeElement:
3084 * @schema: a schema element structure
3085 *
3086 * Deallocate a Schema Element structure.
3087 */
3088static void
3089xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3090{
3091 if (elem == NULL)
3092 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003093 if (elem->annot != NULL)
3094 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003095 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003096 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003097 if (elem->defVal != NULL)
3098 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003099 xmlFree(elem);
3100}
3101
3102/**
3103 * xmlSchemaFreeFacet:
3104 * @facet: a schema facet structure
3105 *
3106 * Deallocate a Schema Facet structure.
3107 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003108void
Daniel Veillard4255d502002-04-16 15:50:10 +00003109xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3110{
3111 if (facet == NULL)
3112 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003113 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003114 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003115 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003116 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003117 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003118 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003119 xmlFree(facet);
3120}
3121
3122/**
3123 * xmlSchemaFreeType:
3124 * @type: a schema type structure
3125 *
3126 * Deallocate a Schema Type structure.
3127 */
3128void
3129xmlSchemaFreeType(xmlSchemaTypePtr type)
3130{
3131 if (type == NULL)
3132 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003133 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003134 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003135 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003136 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003137
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003138 facet = type->facets;
3139 while (facet != NULL) {
3140 next = facet->next;
3141 xmlSchemaFreeFacet(facet);
3142 facet = next;
3143 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003144 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003145 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3146 if (type->attributeUses != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003147 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003148 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003149 if (type->memberTypes != NULL)
3150 xmlSchemaFreeTypeLinkList(type->memberTypes);
3151 if (type->facetSet != NULL) {
3152 xmlSchemaFacetLinkPtr next, link;
3153
3154 link = type->facetSet;
3155 do {
3156 next = link->next;
3157 xmlFree(link);
3158 link = next;
3159 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003160 }
3161 if (type->contModel != NULL)
3162 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003163 xmlFree(type);
3164}
3165
3166/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003167 * xmlSchemaFreeModelGroupDef:
3168 * @item: a schema model group definition
3169 *
3170 * Deallocates a schema model group definition.
3171 */
3172static void
3173xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3174{
3175 if (item->annot != NULL)
3176 xmlSchemaFreeAnnot(item->annot);
3177 xmlFree(item);
3178}
3179
3180/**
3181 * xmlSchemaFreeModelGroup:
3182 * @item: a schema model group
3183 *
3184 * Deallocates a schema model group structure.
3185 */
3186static void
3187xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3188{
3189 if (item->annot != NULL)
3190 xmlSchemaFreeAnnot(item->annot);
3191 xmlFree(item);
3192}
3193
3194/**
3195 * xmlSchemaFreeParticle:
3196 * @type: a schema type structure
3197 *
3198 * Deallocate a Schema Type structure.
3199 */
3200static void
3201xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3202{
3203 if (item->annot != NULL)
3204 xmlSchemaFreeAnnot(item->annot);
3205 xmlFree(item);
3206}
3207
3208/**
3209 * xmlSchemaFreeMiscComponents:
3210 * @item: a schema component
3211 *
3212 * Deallocates misc. schema component structures.
3213 */
3214static void
3215xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3216{
3217 if (item == NULL)
3218 return;
3219 switch (item->type) {
3220 case XML_SCHEMA_TYPE_PARTICLE:
3221 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3222 return;
3223 case XML_SCHEMA_TYPE_SEQUENCE:
3224 case XML_SCHEMA_TYPE_CHOICE:
3225 case XML_SCHEMA_TYPE_ALL:
3226 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3227 return;
3228 case XML_SCHEMA_TYPE_ANY:
3229 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3230 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3231 break;
3232 default:
3233 /* TODO: This should never be hit. */
3234 TODO
3235 return;
3236 }
3237}
3238
3239static void
3240xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3241{
3242 if (schema->volatiles == NULL)
3243 return;
3244 {
3245 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3246 xmlSchemaTreeItemPtr item;
3247 int i;
3248
3249 for (i = 0; i < list->nbItems; i++) {
3250 if (list->items[i] != NULL) {
3251 item = (xmlSchemaTreeItemPtr) list->items[i];
3252 switch (item->type) {
3253 case XML_SCHEMA_EXTRA_QNAMEREF:
3254 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3255 break;
3256 default:
3257 xmlSchemaFreeMiscComponents(item);
3258 }
3259 }
3260 }
3261 if (list->items != NULL)
3262 xmlFree(list->items);
3263 xmlFree(list);
3264 }
3265}
3266/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003267 * xmlSchemaFreeTypeList:
3268 * @type: a schema type structure
3269 *
3270 * Deallocate a Schema Type structure.
3271 */
3272static void
3273xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3274{
3275 xmlSchemaTypePtr next;
3276
3277 while (type != NULL) {
3278 next = type->redef;
3279 xmlSchemaFreeType(type);
3280 type = next;
3281 }
3282}
3283
3284/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003285 * xmlSchemaFree:
3286 * @schema: a schema structure
3287 *
3288 * Deallocate a Schema structure.
3289 */
3290void
3291xmlSchemaFree(xmlSchemaPtr schema)
3292{
3293 if (schema == NULL)
3294 return;
3295
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003296 if (schema->volatiles != NULL)
3297 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003298 if (schema->notaDecl != NULL)
3299 xmlHashFree(schema->notaDecl,
3300 (xmlHashDeallocator) xmlSchemaFreeNotation);
3301 if (schema->attrDecl != NULL)
3302 xmlHashFree(schema->attrDecl,
3303 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3304 if (schema->attrgrpDecl != NULL)
3305 xmlHashFree(schema->attrgrpDecl,
3306 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3307 if (schema->elemDecl != NULL)
3308 xmlHashFree(schema->elemDecl,
3309 (xmlHashDeallocator) xmlSchemaFreeElement);
3310 if (schema->typeDecl != NULL)
3311 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003312 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003313 if (schema->groupDecl != NULL)
3314 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003315 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003316 if (schema->idcDef != NULL)
3317 xmlHashFree(schema->idcDef,
3318 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003319 if (schema->schemasImports != NULL)
3320 xmlHashFree(schema->schemasImports,
3321 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003322 if (schema->includes != NULL) {
3323 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3324 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003325 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003326 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003327 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003328 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003329 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003330 xmlFree(schema);
3331}
3332
3333/************************************************************************
3334 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003335 * Debug functions *
3336 * *
3337 ************************************************************************/
3338
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003339#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003340
Daniel Veillard4255d502002-04-16 15:50:10 +00003341/**
3342 * xmlSchemaElementDump:
3343 * @elem: an element
3344 * @output: the file output
3345 *
3346 * Dump the element
3347 */
3348static void
3349xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003350 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003351 const xmlChar * namespace ATTRIBUTE_UNUSED,
3352 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003353{
3354 if (elem == NULL)
3355 return;
3356
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003357 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3358 fprintf(output, "Particle: %s", name);
3359 fprintf(output, ", term element: %s", elem->ref);
3360 if (elem->refNs != NULL)
3361 fprintf(output, " ns %s", elem->refNs);
3362 } else {
3363 fprintf(output, "Element");
3364 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3365 fprintf(output, " (global)");
3366 fprintf(output, ": %s ", elem->name);
3367 if (namespace != NULL)
3368 fprintf(output, "ns %s", namespace);
3369 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003370 fprintf(output, "\n");
3371 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003372 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003373 if (elem->maxOccurs >= UNBOUNDED)
3374 fprintf(output, "max: unbounded\n");
3375 else if (elem->maxOccurs != 1)
3376 fprintf(output, "max: %d\n", elem->maxOccurs);
3377 else
3378 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003379 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003380 /*
3381 * Misc other properties.
3382 */
3383 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3384 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3385 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3386 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3387 (elem->id != NULL)) {
3388 fprintf(output, " props: ");
3389 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3390 fprintf(output, "[fixed] ");
3391 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3392 fprintf(output, "[default] ");
3393 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3394 fprintf(output, "[abstract] ");
3395 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3396 fprintf(output, "[nillable] ");
3397 if (elem->id != NULL)
3398 fprintf(output, "[id: '%s'] ", elem->id);
3399 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003400 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003401 /*
3402 * Default/fixed value.
3403 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003404 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003405 fprintf(output, " value: '%s'\n", elem->value);
3406 /*
3407 * Type.
3408 */
3409 if (elem->namedType != NULL) {
3410 fprintf(output, " type: %s ", elem->namedType);
3411 if (elem->namedTypeNs != NULL)
3412 fprintf(output, "ns %s\n", elem->namedTypeNs);
3413 else
3414 fprintf(output, "\n");
3415 }
3416 /*
3417 * Substitution group.
3418 */
3419 if (elem->substGroup != NULL) {
3420 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3421 if (elem->substGroupNs != NULL)
3422 fprintf(output, "ns %s\n", elem->substGroupNs);
3423 else
3424 fprintf(output, "\n");
3425 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003426}
3427
3428/**
3429 * xmlSchemaAnnotDump:
3430 * @output: the file output
3431 * @annot: a annotation
3432 *
3433 * Dump the annotation
3434 */
3435static void
3436xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3437{
3438 xmlChar *content;
3439
3440 if (annot == NULL)
3441 return;
3442
3443 content = xmlNodeGetContent(annot->content);
3444 if (content != NULL) {
3445 fprintf(output, " Annot: %s\n", content);
3446 xmlFree(content);
3447 } else
3448 fprintf(output, " Annot: empty\n");
3449}
3450
3451/**
3452 * xmlSchemaTypeDump:
3453 * @output: the file output
3454 * @type: a type structure
3455 *
3456 * Dump a SchemaType structure
3457 */
3458static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003459xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3460{
3461 xmlChar *str = NULL;
3462 xmlSchemaTreeItemPtr term;
3463 char shift[100];
3464 int i;
3465
3466 if (particle == NULL)
3467 return;
3468 for (i = 0;((i < depth) && (i < 25));i++)
3469 shift[2 * i] = shift[2 * i + 1] = ' ';
3470 shift[2 * i] = shift[2 * i + 1] = 0;
3471 fprintf(output, shift);
3472 if (particle->children == NULL) {
3473 fprintf(output, "MISSING particle term\n");
3474 return;
3475 }
3476 term = particle->children;
3477 switch (term->type) {
3478 case XML_SCHEMA_TYPE_ELEMENT:
3479 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
3480 ((xmlSchemaElementPtr)term)->targetNamespace,
3481 ((xmlSchemaElementPtr)term)->name));
3482 break;
3483 case XML_SCHEMA_TYPE_SEQUENCE:
3484 fprintf(output, "SEQUENCE");
3485 break;
3486 case XML_SCHEMA_TYPE_CHOICE:
3487 fprintf(output, "CHOICE");
3488 break;
3489 case XML_SCHEMA_TYPE_ALL:
3490 fprintf(output, "ALL");
3491 break;
3492 case XML_SCHEMA_TYPE_ANY:
3493 fprintf(output, "ANY");
3494 break;
3495 default:
3496 fprintf(output, "UNKNOWN\n");
3497 return;
3498 }
3499 if (particle->minOccurs != 1)
3500 fprintf(output, " min: %d", particle->minOccurs);
3501 if (particle->maxOccurs >= UNBOUNDED)
3502 fprintf(output, " max: unbounded");
3503 else if (particle->maxOccurs != 1)
3504 fprintf(output, " max: %d", particle->maxOccurs);
3505 fprintf(output, "\n");
3506 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3507 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3508 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3509 (term->children != NULL)) {
3510 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3511 output, depth +1);
3512 }
3513 if (particle->next != NULL)
3514 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3515 output, depth);
3516}
3517/**
3518 * xmlSchemaTypeDump:
3519 * @output: the file output
3520 * @type: a type structure
3521 *
3522 * Dump a SchemaType structure
3523 */
3524static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003525xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3526{
3527 if (type == NULL) {
3528 fprintf(output, "Type: NULL\n");
3529 return;
3530 }
3531 fprintf(output, "Type: ");
3532 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003533 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003534 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003535 fprintf(output, "no name ");
3536 if (type->targetNamespace != NULL)
3537 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003538 switch (type->type) {
3539 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003540 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003541 break;
3542 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003543 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003544 break;
3545 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003546 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003547 break;
3548 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003549 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003550 break;
3551 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003552 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003553 break;
3554 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003555 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003556 break;
3557 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003558 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003559 break;
3560 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003561 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003562 break;
3563 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003564 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003565 break;
3566 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003567 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003568 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003569 }
3570 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003571 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003572 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003573 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003574 break;
3575 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003576 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003577 break;
3578 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003579 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003580 break;
3581 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003582 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003583 break;
3584 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003585 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003586 break;
3587 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003588 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003589 break;
3590 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003591 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003592 break;
3593 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003594 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003595 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003596 }
3597 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003598 if (type->base != NULL) {
3599 fprintf(output, " base type: %s", type->base);
3600 if (type->baseNs != NULL)
3601 fprintf(output, " ns %s\n", type->baseNs);
3602 else
3603 fprintf(output, "\n");
3604 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003605 if (type->annot != NULL)
3606 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003607#ifdef DUMP_CONTENT_MODEL
3608 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3609 (type->subtypes != NULL)) {
3610 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3611 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003612 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003613#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003614}
3615
3616/**
3617 * xmlSchemaDump:
3618 * @output: the file output
3619 * @schema: a schema structure
3620 *
3621 * Dump a Schema structure.
3622 */
3623void
3624xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3625{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003626 if (output == NULL)
3627 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003628 if (schema == NULL) {
3629 fprintf(output, "Schemas: NULL\n");
3630 return;
3631 }
3632 fprintf(output, "Schemas: ");
3633 if (schema->name != NULL)
3634 fprintf(output, "%s, ", schema->name);
3635 else
3636 fprintf(output, "no name, ");
3637 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003638 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003639 else
3640 fprintf(output, "no target namespace");
3641 fprintf(output, "\n");
3642 if (schema->annot != NULL)
3643 xmlSchemaAnnotDump(output, schema->annot);
3644
3645 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3646 output);
3647 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003648 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003649}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003650
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003651#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003652/**
3653 * xmlSchemaDebugDumpIDCTable:
3654 * @vctxt: the WXS validation context
3655 *
3656 * Displays the current IDC table for debug purposes.
3657 */
3658static void
3659xmlSchemaDebugDumpIDCTable(FILE * output,
3660 const xmlChar *namespaceName,
3661 const xmlChar *localName,
3662 xmlSchemaPSVIIDCBindingPtr bind)
3663{
3664 xmlChar *str = NULL, *value;
3665 xmlSchemaPSVIIDCNodePtr tab;
3666 xmlSchemaPSVIIDCKeyPtr key;
3667 int i, j, res;
3668
3669 fprintf(output, "IDC: TABLES on %s\n",
3670 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
3671 FREE_AND_NULL(str)
3672
3673 if (bind == NULL)
3674 return;
3675 do {
3676 fprintf(output, "IDC: BINDING %s\n",
3677 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
3678 bind->definition->name));
3679 FREE_AND_NULL(str)
3680 for (i = 0; i < bind->nbNodes; i++) {
3681 tab = bind->nodeTable[i];
3682 fprintf(output, " ( ");
3683 for (j = 0; j < bind->definition->nbFields; j++) {
3684 key = tab->keys[j];
3685 if ((key != NULL) && (key->compValue != NULL)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003686 res = xmlSchemaGetCanonValue(key->compValue, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003687 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003688 fprintf(output, "\"%s\" ", value);
3689 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003690 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003691 if (res == 0)
3692 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003693 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003694 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003695 else
3696 fprintf(output, "(key missing), ");
3697 }
3698 fprintf(output, ")\n");
3699 }
3700 bind = bind->next;
3701 } while (bind != NULL);
3702}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003703#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003704#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003705
3706/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003707 * *
3708 * Utilities *
3709 * *
3710 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003711
Daniel Veillardc0826a72004-08-10 14:17:33 +00003712/**
3713 * xmlSchemaGetPropNode:
3714 * @node: the element node
3715 * @name: the name of the attribute
3716 *
3717 * Seeks an attribute with a name of @name in
3718 * no namespace.
3719 *
3720 * Returns the attribute or NULL if not present.
3721 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003722static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003723xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003724{
3725 xmlAttrPtr prop;
3726
Daniel Veillardc0826a72004-08-10 14:17:33 +00003727 if ((node == NULL) || (name == NULL))
3728 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003729 prop = node->properties;
3730 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003731 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3732 return(prop);
3733 prop = prop->next;
3734 }
3735 return (NULL);
3736}
3737
3738/**
3739 * xmlSchemaGetPropNodeNs:
3740 * @node: the element node
3741 * @uri: the uri
3742 * @name: the name of the attribute
3743 *
3744 * Seeks an attribute with a local name of @name and
3745 * a namespace URI of @uri.
3746 *
3747 * Returns the attribute or NULL if not present.
3748 */
3749static xmlAttrPtr
3750xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3751{
3752 xmlAttrPtr prop;
3753
3754 if ((node == NULL) || (name == NULL))
3755 return(NULL);
3756 prop = node->properties;
3757 while (prop != NULL) {
3758 if ((prop->ns != NULL) &&
3759 xmlStrEqual(prop->name, BAD_CAST name) &&
3760 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003761 return(prop);
3762 prop = prop->next;
3763 }
3764 return (NULL);
3765}
3766
3767static const xmlChar *
3768xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3769{
3770 xmlChar *val;
3771 const xmlChar *ret;
3772
3773 val = xmlNodeGetContent(node);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003774 if (val == NULL)
3775 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003776 ret = xmlDictLookup(ctxt->dict, val, -1);
3777 xmlFree(val);
3778 return(ret);
3779}
3780
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003781/**
3782 * xmlSchemaGetProp:
3783 * @ctxt: the parser context
3784 * @node: the node
3785 * @name: the property name
3786 *
3787 * Read a attribute value and internalize the string
3788 *
3789 * Returns the string or NULL if not present.
3790 */
3791static const xmlChar *
3792xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3793 const char *name)
3794{
3795 xmlChar *val;
3796 const xmlChar *ret;
3797
3798 val = xmlGetProp(node, BAD_CAST name);
3799 if (val == NULL)
3800 return(NULL);
3801 ret = xmlDictLookup(ctxt->dict, val, -1);
3802 xmlFree(val);
3803 return(ret);
3804}
3805
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003806/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003807 * *
3808 * Parsing functions *
3809 * *
3810 ************************************************************************/
3811
3812/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003813 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003814 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003815 * @name: the element name
3816 * @ns: the element namespace
3817 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003818 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003819 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003820 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003821 */
3822static xmlSchemaElementPtr
3823xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003824 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003825{
3826 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003827
3828 if ((name == NULL) || (schema == NULL))
3829 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003830
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003831 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003832 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003833 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003834 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003835 } else
3836 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003837 /*
3838 * This one was removed, since top level element declarations have
3839 * the target namespace specified in targetNamespace of the <schema>
3840 * information element, even if elementFormDefault is "unqualified".
3841 */
3842
3843 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003844 if (xmlStrEqual(namespace, schema->targetNamespace))
3845 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3846 else
3847 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003848 if ((ret != NULL) &&
3849 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003850 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003851 }
William M. Bracke7091952004-05-11 15:09:58 +00003852 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003853
William M. Brack2f2a6632004-08-20 23:09:47 +00003854 /*
3855 * Removed since imported components will be hold by the main schema only.
3856 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003857 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003858 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003859 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003860 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003861 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003862 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003863 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3864 return (ret);
3865 } else
3866 ret = NULL;
3867 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003868 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003869#ifdef DEBUG
3870 if (ret == NULL) {
3871 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003872 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003873 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003874 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003875 namespace);
3876 }
3877#endif
3878 return (ret);
3879}
3880
3881/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003882 * xmlSchemaGetType:
3883 * @schema: the schemas context
3884 * @name: the type name
3885 * @ns: the type namespace
3886 *
3887 * Lookup a type in the schemas or the predefined types
3888 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003889 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003890 */
3891static xmlSchemaTypePtr
3892xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003893 const xmlChar * namespace)
3894{
Daniel Veillard4255d502002-04-16 15:50:10 +00003895 xmlSchemaTypePtr ret;
3896
3897 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003898 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003899 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003900 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003901 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003902 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003903 }
3904 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003905 if (ret != NULL)
3906 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003907 /*
3908 * Removed, since the imported components will be grafted on the
3909 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003910 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003911 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003912 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003913 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003914 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003915 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003916 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3917 return (ret);
3918 } else
3919 ret = NULL;
3920 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003921 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003922#ifdef DEBUG
3923 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003924 if (namespace == NULL)
3925 fprintf(stderr, "Unable to lookup type %s", name);
3926 else
3927 fprintf(stderr, "Unable to lookup type %s:%s", name,
3928 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003929 }
3930#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003931 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003932}
3933
Daniel Veillard3646d642004-06-02 19:19:14 +00003934/**
3935 * xmlSchemaGetAttribute:
3936 * @schema: the context of the schema
3937 * @name: the name of the attribute
3938 * @ns: the target namespace of the attribute
3939 *
3940 * Lookup a an attribute in the schema or imported schemas
3941 *
3942 * Returns the attribute declaration or NULL if not found.
3943 */
3944static xmlSchemaAttributePtr
3945xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
3946 const xmlChar * namespace)
3947{
3948 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003949
3950 if ((name == NULL) || (schema == NULL))
3951 return (NULL);
3952
3953
3954 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
3955 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
3956 return (ret);
3957 else
3958 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003959 /*
3960 * Removed, since imported components will be hold by the main schema only.
3961 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003962 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003963 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003964 else
3965 import = xmlHashLookup(schema->schemasImports, namespace);
3966 if (import != NULL) {
3967 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
3968 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
3969 return (ret);
3970 } else
3971 ret = NULL;
3972 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003973 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003974#ifdef DEBUG
3975 if (ret == NULL) {
3976 if (namespace == NULL)
3977 fprintf(stderr, "Unable to lookup attribute %s", name);
3978 else
3979 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
3980 namespace);
3981 }
3982#endif
3983 return (ret);
3984}
3985
3986/**
3987 * xmlSchemaGetAttributeGroup:
3988 * @schema: the context of the schema
3989 * @name: the name of the attribute group
3990 * @ns: the target namespace of the attribute group
3991 *
3992 * Lookup a an attribute group in the schema or imported schemas
3993 *
3994 * Returns the attribute group definition or NULL if not found.
3995 */
3996static xmlSchemaAttributeGroupPtr
3997xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
3998 const xmlChar * namespace)
3999{
4000 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004001
4002 if ((name == NULL) || (schema == NULL))
4003 return (NULL);
4004
4005
4006 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4007 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4008 return (ret);
4009 else
4010 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004011 /*
4012 * Removed since imported components will be hold by the main schema only.
4013 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004014 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004015 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004016 else
4017 import = xmlHashLookup(schema->schemasImports, namespace);
4018 if (import != NULL) {
4019 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4020 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4021 return (ret);
4022 else
4023 ret = NULL;
4024 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004025 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004026#ifdef DEBUG
4027 if (ret == NULL) {
4028 if (namespace == NULL)
4029 fprintf(stderr, "Unable to lookup attribute group %s", name);
4030 else
4031 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4032 namespace);
4033 }
4034#endif
4035 return (ret);
4036}
4037
4038/**
4039 * xmlSchemaGetGroup:
4040 * @schema: the context of the schema
4041 * @name: the name of the group
4042 * @ns: the target namespace of the group
4043 *
4044 * Lookup a group in the schema or imported schemas
4045 *
4046 * Returns the group definition or NULL if not found.
4047 */
4048static xmlSchemaTypePtr
4049xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4050 const xmlChar * namespace)
4051{
4052 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004053
4054 if ((name == NULL) || (schema == NULL))
4055 return (NULL);
4056
Daniel Veillard3646d642004-06-02 19:19:14 +00004057 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004058 /*
4059 * Removed since imported components will be hold by the main schema only.
4060 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004061 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004062 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004063 else
4064 import = xmlHashLookup(schema->schemasImports, namespace);
4065 if (import != NULL) {
4066 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4067 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4068 return (ret);
4069 else
4070 ret = NULL;
4071 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004072 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004073#ifdef DEBUG
4074 if (ret == NULL) {
4075 if (namespace == NULL)
4076 fprintf(stderr, "Unable to lookup group %s", name);
4077 else
4078 fprintf(stderr, "Unable to lookup group %s:%s", name,
4079 namespace);
4080 }
4081#endif
4082 return (ret);
4083}
4084
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004085/**
4086 * xmlSchemaGetNamedComponent:
4087 * @schema: the schema
4088 * @name: the name of the group
4089 * @ns: the target namespace of the group
4090 *
4091 * Lookup a group in the schema or imported schemas
4092 *
4093 * Returns the group definition or NULL if not found.
4094 */
4095static xmlSchemaTreeItemPtr
4096xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4097 xmlSchemaTypeType itemType,
4098 const xmlChar *name,
4099 const xmlChar *targetNs)
4100{
4101 switch (itemType) {
4102 case XML_SCHEMA_TYPE_GROUP:
4103 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4104 name, targetNs));
4105 case XML_SCHEMA_TYPE_ELEMENT:
4106 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4107 name, targetNs));
4108 default:
4109 return (NULL);
4110 }
4111}
4112
Daniel Veillard4255d502002-04-16 15:50:10 +00004113/************************************************************************
4114 * *
4115 * Parsing functions *
4116 * *
4117 ************************************************************************/
4118
4119#define IS_BLANK_NODE(n) \
4120 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
4121
4122/**
4123 * xmlSchemaIsBlank:
4124 * @str: a string
4125 *
4126 * Check if a string is ignorable
4127 *
4128 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4129 */
4130static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004131xmlSchemaIsBlank(xmlChar * str)
4132{
Daniel Veillard4255d502002-04-16 15:50:10 +00004133 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004134 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004135 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00004136 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004137 return (0);
4138 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004139 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004140 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004141}
4142
4143/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004144 * xmlSchemaAddAssembledItem:
4145 * @ctxt: a schema parser context
4146 * @schema: the schema being built
4147 * @item: the item
4148 *
4149 * Add a item to the schema's list of current items.
4150 * This is used if the schema was already constructed and
4151 * new schemata need to be added to it.
4152 * *WARNING* this interface is highly subject to change.
4153 *
4154 * Returns 0 if suceeds and -1 if an internal error occurs.
4155 */
4156static int
4157xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4158 xmlSchemaTypePtr item)
4159{
4160 static int growSize = 100;
4161 xmlSchemaAssemblePtr ass;
4162
4163 ass = ctxt->assemble;
4164 if (ass->sizeItems < 0) {
4165 /* If disabled. */
4166 return (0);
4167 }
4168 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004169 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004170 if (ass->items == NULL) {
4171 xmlSchemaPErrMemory(ctxt,
4172 "allocating new item buffer", NULL);
4173 return (-1);
4174 }
4175 ass->sizeItems = growSize;
4176 } else if (ass->sizeItems <= ass->nbItems) {
4177 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004178 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004179 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4180 if (ass->items == NULL) {
4181 xmlSchemaPErrMemory(ctxt,
4182 "growing item buffer", NULL);
4183 ass->sizeItems = 0;
4184 return (-1);
4185 }
4186 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004187 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004188 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4189 return (0);
4190}
4191
4192/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004193 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004194 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004195 * @schema: the schema being built
4196 * @name: the item name
4197 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004198 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004199 * *WARNING* this interface is highly subject to change
4200 *
4201 * Returns the new struture or NULL in case of error
4202 */
4203static xmlSchemaNotationPtr
4204xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004205 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004206{
4207 xmlSchemaNotationPtr ret = NULL;
4208 int val;
4209
4210 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4211 return (NULL);
4212
4213 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004214 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004215 if (schema->notaDecl == NULL)
4216 return (NULL);
4217
4218 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4219 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004220 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004221 return (NULL);
4222 }
4223 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004224 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004225 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4226 ret);
4227 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004228 /*
4229 * TODO: This should never happen, since a unique name will be computed.
4230 * If it fails, then an other internal error must have occured.
4231 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004232 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4233 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004234 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004235 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004236 xmlFree(ret);
4237 return (NULL);
4238 }
4239 return (ret);
4240}
4241
4242
4243/**
4244 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004245 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004246 * @schema: the schema being built
4247 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004248 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004249 *
4250 * Add an XML schema Attrribute declaration
4251 * *WARNING* this interface is highly subject to change
4252 *
4253 * Returns the new struture or NULL in case of error
4254 */
4255static xmlSchemaAttributePtr
4256xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004257 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004258 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004259{
4260 xmlSchemaAttributePtr ret = NULL;
4261 int val;
4262
4263 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4264 return (NULL);
4265
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004266#ifdef DEBUG
4267 fprintf(stderr, "Adding attribute %s\n", name);
4268 if (namespace != NULL)
4269 fprintf(stderr, " target namespace %s\n", namespace);
4270#endif
4271
Daniel Veillard4255d502002-04-16 15:50:10 +00004272 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004273 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004274 if (schema->attrDecl == NULL)
4275 return (NULL);
4276
4277 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4278 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004279 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004280 return (NULL);
4281 }
4282 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004283 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004284 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004285 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004286 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004287 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004288 if (topLevel) {
4289 xmlSchemaPCustomErr(ctxt,
4290 XML_SCHEMAP_REDEFINED_ATTR,
4291 NULL, NULL, node,
4292 "A global attribute declaration with the name '%s' does "
4293 "already exist", name);
4294 xmlFree(ret);
4295 return (NULL);
4296 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004297 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004298 /*
4299 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4300 * in the scenario:
4301 * 1. multiple top-level complex types have different target
4302 * namespaces but have the SAME NAME; this can happen if
4303 * schemata are imported
4304 * 2. those complex types contain attributes with an equal name
4305 * 3. those attributes are in no namespace
4306 * We will compute a new context string.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004307 */
4308 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004309 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004310 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004311
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004312 if (val != 0) {
4313 xmlSchemaPCustomErr(ctxt,
4314 XML_SCHEMAP_INTERNAL,
4315 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004316 "Internal error: xmlSchemaAddAttribute, "
4317 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004318 "could not be added to the hash.", name);
4319 xmlFree(ret);
4320 return (NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004321 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004322 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004323 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004324 if (ctxt->assemble != NULL)
4325 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004326 return (ret);
4327}
4328
4329/**
4330 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004331 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004332 * @schema: the schema being built
4333 * @name: the item name
4334 *
4335 * Add an XML schema Attrribute Group declaration
4336 *
4337 * Returns the new struture or NULL in case of error
4338 */
4339static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004340xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004341 xmlSchemaPtr schema, const xmlChar * name,
4342 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004343{
4344 xmlSchemaAttributeGroupPtr ret = NULL;
4345 int val;
4346
4347 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4348 return (NULL);
4349
4350 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004351 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004352 if (schema->attrgrpDecl == NULL)
4353 return (NULL);
4354
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004355 ret =
4356 (xmlSchemaAttributeGroupPtr)
4357 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004358 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004359 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004360 return (NULL);
4361 }
4362 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004363 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004364 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004365 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004366 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004367 xmlSchemaPCustomErr(ctxt,
4368 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4369 NULL, NULL, node,
4370 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004371 xmlFree(ret);
4372 return (NULL);
4373 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004374 if (ctxt->assemble != NULL)
4375 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004376 return (ret);
4377}
4378
4379/**
4380 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004381 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004382 * @schema: the schema being built
4383 * @name: the type name
4384 * @namespace: the type namespace
4385 *
4386 * Add an XML schema Element declaration
4387 * *WARNING* this interface is highly subject to change
4388 *
4389 * Returns the new struture or NULL in case of error
4390 */
4391static xmlSchemaElementPtr
4392xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004393 const xmlChar * name, const xmlChar * namespace,
4394 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004395{
4396 xmlSchemaElementPtr ret = NULL;
4397 int val;
4398
4399 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4400 return (NULL);
4401
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004402#ifdef DEBUG
4403 fprintf(stderr, "Adding element %s\n", name);
4404 if (namespace != NULL)
4405 fprintf(stderr, " target namespace %s\n", namespace);
4406#endif
4407
Daniel Veillard4255d502002-04-16 15:50:10 +00004408 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004409 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004410 if (schema->elemDecl == NULL)
4411 return (NULL);
4412
4413 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4414 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004415 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004416 return (NULL);
4417 }
4418 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004419 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004420 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004421 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004422 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004423 if (topLevel) {
4424 xmlSchemaPCustomErr(ctxt,
4425 XML_SCHEMAP_REDEFINED_ELEMENT,
4426 NULL, NULL, node,
4427 "A global element declaration with the name '%s' does "
4428 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004429 xmlFree(ret);
4430 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004431 } else {
4432 char buf[30];
4433
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004434 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004435 val = xmlHashAddEntry3(schema->elemDecl, name,
4436 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004437 if (val != 0) {
4438 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004439 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004440 NULL, NULL, node,
4441 "Internal error: xmlSchemaAddElement, "
4442 "a dublicate element declaration with the name '%s' "
4443 "could not be added to the hash.", name);
4444 xmlFree(ret);
4445 return (NULL);
4446 }
4447 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004448
Daniel Veillard4255d502002-04-16 15:50:10 +00004449 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004450 if (ctxt->assemble != NULL)
4451 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004452 return (ret);
4453}
4454
4455/**
4456 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004457 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004458 * @schema: the schema being built
4459 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004460 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004461 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004462 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004463 * *WARNING* this interface is highly subject to change
4464 *
4465 * Returns the new struture or NULL in case of error
4466 */
4467static xmlSchemaTypePtr
4468xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004469 const xmlChar * name, const xmlChar * namespace,
4470 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004471{
4472 xmlSchemaTypePtr ret = NULL;
4473 int val;
4474
4475 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4476 return (NULL);
4477
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004478#ifdef DEBUG
4479 fprintf(stderr, "Adding type %s\n", name);
4480 if (namespace != NULL)
4481 fprintf(stderr, " target namespace %s\n", namespace);
4482#endif
4483
Daniel Veillard4255d502002-04-16 15:50:10 +00004484 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004485 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004486 if (schema->typeDecl == NULL)
4487 return (NULL);
4488
4489 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4490 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004491 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004492 return (NULL);
4493 }
4494 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004495 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004496 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004497 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004498 if (val != 0) {
4499 if (ctxt->includes == 0) {
4500 xmlSchemaPCustomErr(ctxt,
4501 XML_SCHEMAP_REDEFINED_TYPE,
4502 NULL, NULL, node,
4503 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004504 xmlFree(ret);
4505 return (NULL);
4506 } else {
4507 xmlSchemaTypePtr prev;
4508
4509 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4510 if (prev == NULL) {
4511 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004512 XML_ERR_INTERNAL_ERROR,
4513 "Internal error: xmlSchemaAddType, on type "
4514 "'%s'.\n",
4515 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004516 xmlFree(ret);
4517 return (NULL);
4518 }
4519 ret->redef = prev->redef;
4520 prev->redef = ret;
4521 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004522 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004523 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004524 ret->minOccurs = 1;
4525 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004526 ret->attributeUses = NULL;
4527 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004528 if (ctxt->assemble != NULL)
4529 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004530 return (ret);
4531}
4532
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004533static xmlSchemaQNameRefPtr
4534xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4535 xmlSchemaTypeType refType,
4536 const xmlChar *refName,
4537 const xmlChar *refNs)
4538{
4539 xmlSchemaQNameRefPtr ret;
4540
4541 ret = (xmlSchemaQNameRefPtr)
4542 xmlMalloc(sizeof(xmlSchemaQNameRef));
4543 if (ret == NULL) {
4544 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4545 NULL);
4546 return (NULL);
4547 }
4548 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4549 ret->name = refName;
4550 ret->targetNamespace = refNs;
4551 ret->item = NULL;
4552 ret->itemType = refType;
4553 /*
4554 * Store the reference item in the schema.
4555 */
4556 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4557 return (ret);
4558}
4559
4560/**
4561 * xmlSchemaAddModelGroup:
4562 * @ctxt: a schema parser context
4563 * @schema: the schema being built
4564 * @type: the "compositor" type of the model group
4565 * @container: the internal component name
4566 * @node: the node in the schema doc
4567 *
4568 * Adds a schema model group
4569 * *WARNING* this interface is highly subject to change
4570 *
4571 * Returns the new struture or NULL in case of error
4572 */
4573static xmlSchemaModelGroupPtr
4574xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4575 xmlSchemaTypeType type, const xmlChar **container,
4576 xmlNodePtr node)
4577{
4578 xmlSchemaModelGroupPtr ret = NULL;
4579 xmlChar buf[30];
4580
4581 if ((ctxt == NULL) || (schema == NULL))
4582 return (NULL);
4583
4584#ifdef DEBUG
4585 fprintf(stderr, "Adding model group component\n");
4586#endif
4587 ret = (xmlSchemaModelGroupPtr)
4588 xmlMalloc(sizeof(xmlSchemaModelGroup));
4589 if (ret == NULL) {
4590 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4591 NULL);
4592 return (NULL);
4593 }
4594 ret->type = type;
4595 ret->annot = NULL;
4596 ret->node = node;
4597 ret->children = NULL;
4598 ret->next = NULL;
4599 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4600 if (container != NULL)
4601 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4602 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
4603 if (container != NULL)
4604 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4605 } else {
4606 if (container != NULL)
4607 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4608 }
4609 if (container != NULL)
4610 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4611 /*
4612 * Add to volatile items.
4613 * TODO: this should be changed someday.
4614 */
4615 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4616 xmlFree(ret);
4617 return (NULL);
4618 }
4619 return (ret);
4620}
4621
4622
4623/**
4624 * xmlSchemaAddParticle:
4625 * @ctxt: a schema parser context
4626 * @schema: the schema being built
4627 * @node: the corresponding node in the schema doc
4628 * @min: the minOccurs
4629 * @max: the maxOccurs
4630 *
4631 * Adds an XML schema particle component.
4632 * *WARNING* this interface is highly subject to change
4633 *
4634 * Returns the new struture or NULL in case of error
4635 */
4636static xmlSchemaParticlePtr
4637xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4638 xmlNodePtr node, int min, int max)
4639{
4640 xmlSchemaParticlePtr ret = NULL;
4641 if ((ctxt == NULL) || (schema == NULL))
4642 return (NULL);
4643
4644#ifdef DEBUG
4645 fprintf(stderr, "Adding particle component\n");
4646#endif
4647 ret = (xmlSchemaParticlePtr)
4648 xmlMalloc(sizeof(xmlSchemaParticle));
4649 if (ret == NULL) {
4650 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4651 NULL);
4652 return (NULL);
4653 }
4654 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4655 ret->annot = NULL;
4656 ret->node = node;
4657 ret->minOccurs = min;
4658 ret->maxOccurs = max;
4659 ret->next = NULL;
4660 ret->children = NULL;
4661
4662 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4663 xmlFree(ret);
4664 return (NULL);
4665 }
4666 return (ret);
4667}
4668
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004669/**
4670 * xmlSchemaAddGroup:
4671 * @ctxt: a schema validation context
4672 * @schema: the schema being built
4673 * @name: the group name
4674 *
4675 * Add an XML schema Group definition
4676 *
4677 * Returns the new struture or NULL in case of error
4678 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004679static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004680xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004681 const xmlChar *name, const xmlChar *namespaceName,
4682 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004683{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004684 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004685 int val;
4686
4687 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4688 return (NULL);
4689
4690 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004691 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004692 if (schema->groupDecl == NULL)
4693 return (NULL);
4694
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004695 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004696 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004697 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004698 return (NULL);
4699 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004700 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004701 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004702 ret->type = XML_SCHEMA_TYPE_GROUP;
4703 ret->node = node;
4704 ret->targetNamespace = namespaceName;
4705 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004706 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004707 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004708 XML_SCHEMAP_REDEFINED_GROUP,
4709 NULL, NULL, node,
4710 "A global model group definition with the name '%s' does already "
4711 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004712 xmlFree(ret);
4713 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004714 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004715 if (ctxt->assemble != NULL)
4716 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004717 return (ret);
4718}
4719
Daniel Veillard3646d642004-06-02 19:19:14 +00004720/**
4721 * xmlSchemaNewWildcardNs:
4722 * @ctxt: a schema validation context
4723 *
4724 * Creates a new wildcard namespace constraint.
4725 *
4726 * Returns the new struture or NULL in case of error
4727 */
4728static xmlSchemaWildcardNsPtr
4729xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4730{
4731 xmlSchemaWildcardNsPtr ret;
4732
4733 ret = (xmlSchemaWildcardNsPtr)
4734 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4735 if (ret == NULL) {
4736 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
4737 return (NULL);
4738 }
4739 ret->value = NULL;
4740 ret->next = NULL;
4741 return (ret);
4742}
4743
4744/**
4745 * xmlSchemaAddWildcard:
4746 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004747 * @schema: a schema
4748 *
4749 * Adds a wildcard.
4750 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004751 *
4752 * Returns the new struture or NULL in case of error
4753 */
4754static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004755xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4756 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004757{
4758 xmlSchemaWildcardPtr ret = NULL;
4759
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004760 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004761 return (NULL);
4762
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004763#ifdef DEBUG
4764 fprintf(stderr, "Adding wildcard component\n");
4765#endif
4766
Daniel Veillard3646d642004-06-02 19:19:14 +00004767 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4768 if (ret == NULL) {
4769 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4770 return (NULL);
4771 }
4772 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004773 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004774 ret->minOccurs = 1;
4775 ret->maxOccurs = 1;
4776
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004777 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4778 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4779 "Failed to add a wildcard component to the list", NULL);
4780 xmlFree(ret);
4781 return (NULL);
4782 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004783 return (ret);
4784}
4785
Daniel Veillard4255d502002-04-16 15:50:10 +00004786/************************************************************************
4787 * *
4788 * Utilities for parsing *
4789 * *
4790 ************************************************************************/
4791
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004792#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004793/**
4794 * xmlGetQNameProp:
4795 * @ctxt: a schema validation context
4796 * @node: a subtree containing XML Schema informations
4797 * @name: the attribute name
4798 * @namespace: the result namespace if any
4799 *
4800 * Extract a QName Attribute value
4801 *
4802 * Returns the NCName or NULL if not found, and also update @namespace
4803 * with the namespace URI
4804 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004805static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004806xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004807 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004808{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004809 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004810 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004811 const xmlChar *ret, *prefix;
4812 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004813 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004814
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004815 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004816 attr = xmlSchemaGetPropNode(node, name);
4817 if (attr == NULL)
4818 return (NULL);
4819 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004820
Daniel Veillard4255d502002-04-16 15:50:10 +00004821 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004822 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004823
Daniel Veillardba0153a2004-04-01 10:42:31 +00004824 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004825 ns = xmlSearchNs(node->doc, node, 0);
4826 if (ns) {
4827 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4828 return (val);
4829 }
4830 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004831 ret = xmlSplitQName3(val, &len);
4832 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004833 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004834 }
4835 ret = xmlDictLookup(ctxt->dict, ret, -1);
4836 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004837
4838 ns = xmlSearchNs(node->doc, node, prefix);
4839 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004840 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4841 NULL, NULL, (xmlNodePtr) attr,
4842 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004843 "The QName value '%s' has no corresponding namespace "
4844 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004845 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004846 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004847 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004848 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004849}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004850#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004851
4852/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004853 * xmlSchemaPValAttrNodeQNameValue:
4854 * @ctxt: a schema parser context
4855 * @schema: the schema context
4856 * @ownerDes: the designation of the parent element
4857 * @ownerItem: the parent as a schema object
4858 * @value: the QName value
4859 * @local: the resulting local part if found, the attribute value otherwise
4860 * @uri: the resulting namespace URI if found
4861 *
4862 * Extracts the local name and the URI of a QName value and validates it.
4863 * This one is intended to be used on attribute values that
4864 * should resolve to schema components.
4865 *
4866 * Returns 0, in case the QName is valid, a positive error code
4867 * if not valid and -1 if an internal error occurs.
4868 */
4869static int
4870xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
4871 xmlSchemaPtr schema,
4872 xmlChar **ownerDes,
4873 xmlSchemaTypePtr ownerItem,
4874 xmlAttrPtr attr,
4875 const xmlChar *value,
4876 const xmlChar **uri,
4877 const xmlChar **prefix,
4878 const xmlChar **local)
4879{
4880 const xmlChar *pref;
4881 xmlNsPtr ns;
4882 int len, ret;
4883
4884 *uri = NULL;
4885 *local = NULL;
4886 if (prefix != 0)
4887 *prefix = NULL;
4888 ret = xmlValidateQName(value, 1);
4889 if (ret > 0) {
4890 xmlSchemaPSimpleTypeErr(ctxt,
4891 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4892 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004893 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4894 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004895 NULL, NULL, NULL);
4896 *local = value;
4897 return (ctxt->err);
4898 } else if (ret < 0)
4899 return (-1);
4900
4901 if (!strchr((char *) value, ':')) {
4902 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4903 if (ns)
4904 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4905 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4906 /*
4907 * This one takes care of included schemas with no
4908 * target namespace.
4909 */
4910 *uri = schema->targetNamespace;
4911 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004912 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004913 return (0);
4914 }
4915 /*
4916 * At this point xmlSplitQName3 has to return a local name.
4917 */
4918 *local = xmlSplitQName3(value, &len);
4919 *local = xmlDictLookup(ctxt->dict, *local, -1);
4920 pref = xmlDictLookup(ctxt->dict, value, len);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004921 if (prefix != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00004922 *prefix = pref;
4923 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4924 if (ns == NULL) {
4925 xmlSchemaPSimpleTypeErr(ctxt,
4926 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4927 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004928 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
4929 "The QName value '%s' has no corresponding namespace "
4930 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004931 return (ctxt->err);
4932 } else {
4933 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4934 }
4935 return (0);
4936}
4937
4938/**
4939 * xmlSchemaPValAttrNodeQName:
4940 * @ctxt: a schema parser context
4941 * @schema: the schema context
4942 * @ownerDes: the designation of the owner element
4943 * @ownerItem: the owner as a schema object
4944 * @attr: the attribute node
4945 * @local: the resulting local part if found, the attribute value otherwise
4946 * @uri: the resulting namespace URI if found
4947 *
4948 * Extracts and validates the QName of an attribute value.
4949 * This one is intended to be used on attribute values that
4950 * should resolve to schema components.
4951 *
4952 * Returns 0, in case the QName is valid, a positive error code
4953 * if not valid and -1 if an internal error occurs.
4954 */
4955static int
4956xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
4957 xmlSchemaPtr schema,
4958 xmlChar **ownerDes,
4959 xmlSchemaTypePtr ownerItem,
4960 xmlAttrPtr attr,
4961 const xmlChar **uri,
4962 const xmlChar **prefix,
4963 const xmlChar **local)
4964{
4965 const xmlChar *value;
4966
4967 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4968 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
4969 ownerDes, ownerItem, attr, value, uri, prefix, local));
4970}
4971
4972/**
4973 * xmlSchemaPValAttrQName:
4974 * @ctxt: a schema parser context
4975 * @schema: the schema context
4976 * @ownerDes: the designation of the parent element
4977 * @ownerItem: the owner as a schema object
4978 * @ownerElem: the parent node of the attribute
4979 * @name: the name of the attribute
4980 * @local: the resulting local part if found, the attribute value otherwise
4981 * @uri: the resulting namespace URI if found
4982 *
4983 * Extracts and validates the QName of an attribute value.
4984 *
4985 * Returns 0, in case the QName is valid, a positive error code
4986 * if not valid and -1 if an internal error occurs.
4987 */
4988static int
4989xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
4990 xmlSchemaPtr schema,
4991 xmlChar **ownerDes,
4992 xmlSchemaTypePtr ownerItem,
4993 xmlNodePtr ownerElem,
4994 const char *name,
4995 const xmlChar **uri,
4996 const xmlChar **prefix,
4997 const xmlChar **local)
4998{
4999 xmlAttrPtr attr;
5000
5001 attr = xmlSchemaGetPropNode(ownerElem, name);
5002 if (attr == NULL) {
5003 *local = NULL;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00005004 if (prefix != NULL)
5005 *prefix = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005006 *uri = NULL;
5007 return (0);
5008 }
5009 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5010 ownerDes, ownerItem, attr, uri, prefix, local));
5011}
5012
5013/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005014 * xmlSchemaPValAttrID:
5015 * @ctxt: a schema parser context
5016 * @schema: the schema context
5017 * @ownerDes: the designation of the parent element
5018 * @ownerItem: the owner as a schema object
5019 * @ownerElem: the parent node of the attribute
5020 * @name: the name of the attribute
5021 *
5022 * Extracts and validates the ID of an attribute value.
5023 *
5024 * Returns 0, in case the ID is valid, a positive error code
5025 * if not valid and -1 if an internal error occurs.
5026 */
5027static int
5028xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5029 xmlChar **ownerDes,
5030 xmlSchemaTypePtr ownerItem,
5031 xmlNodePtr ownerElem,
5032 const xmlChar *name)
5033{
5034 int ret;
5035 xmlChar *value;
5036 xmlAttrPtr attr;
5037
5038 value = xmlGetNoNsProp(ownerElem, name);
5039 if (value == NULL)
5040 return (0);
5041
5042 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5043 if (attr == NULL)
5044 return (-1);
5045
5046 ret = xmlValidateNCName(BAD_CAST value, 1);
5047 if (ret == 0) {
5048 /*
5049 * NOTE: the IDness might have already be declared in the DTD
5050 */
5051 if (attr->atype != XML_ATTRIBUTE_ID) {
5052 xmlIDPtr res;
5053 xmlChar *strip;
5054
5055 /*
5056 * TODO: Use xmlSchemaStrip here; it's not exported at this
5057 * moment.
5058 */
5059 strip = xmlSchemaCollapseString(BAD_CAST value);
5060 if (strip != NULL)
5061 value = strip;
5062 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5063 if (res == NULL) {
5064 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5065 xmlSchemaPSimpleTypeErr(ctxt,
5066 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5067 ownerDes, ownerItem, (xmlNodePtr) attr,
5068 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00005069 NULL, NULL, "The ID '%s' is already defined",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005070 BAD_CAST value, NULL);
5071 } else
5072 attr->atype = XML_ATTRIBUTE_ID;
5073 if (strip != NULL)
5074 xmlFree(strip);
5075 }
5076 } else if (ret > 0) {
5077 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5078 xmlSchemaPSimpleTypeErr(ctxt,
5079 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5080 ownerDes, ownerItem, (xmlNodePtr) attr,
5081 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5082 NULL, BAD_CAST value, NULL, NULL, NULL);
5083 }
5084 xmlFree(value);
5085
5086 return (ret);
5087}
5088
5089/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005090 * xmlGetMaxOccurs:
5091 * @ctxt: a schema validation context
5092 * @node: a subtree containing XML Schema informations
5093 *
5094 * Get the maxOccurs property
5095 *
5096 * Returns the default if not found, or the value
5097 */
5098static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005099xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5100 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005101{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005102 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005103 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005104 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005105
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005106 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5107 if (attr == NULL)
5108 return (def);
5109 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005110
5111 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005112 if (max != UNBOUNDED) {
5113 xmlSchemaPSimpleTypeErr(ctxt,
5114 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5115 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5116 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5117 val, NULL, NULL, NULL);
5118 return (def);
5119 } else
5120 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005121 }
5122
5123 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005124 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005125 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005126 if (*cur == 0) {
5127 xmlSchemaPSimpleTypeErr(ctxt,
5128 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5129 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5130 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5131 val, NULL, NULL, NULL);
5132 return (def);
5133 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005134 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005135 ret = ret * 10 + (*cur - '0');
5136 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005137 }
William M. Brack76e95df2003-10-18 16:20:14 +00005138 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005139 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005140 /*
5141 * TODO: Restrict the maximal value to Integer.
5142 */
5143 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
5144 xmlSchemaPSimpleTypeErr(ctxt,
5145 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5146 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5147 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5148 val, NULL, NULL, NULL);
5149 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005150 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005151 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005152}
5153
5154/**
5155 * xmlGetMinOccurs:
5156 * @ctxt: a schema validation context
5157 * @node: a subtree containing XML Schema informations
5158 *
5159 * Get the minOccurs property
5160 *
5161 * Returns the default if not found, or the value
5162 */
5163static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005164xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5165 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005166{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005167 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005168 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005169 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005170
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005171 attr = xmlSchemaGetPropNode(node, "minOccurs");
5172 if (attr == NULL)
5173 return (def);
5174 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005175 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005176 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005177 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005178 if (*cur == 0) {
5179 xmlSchemaPSimpleTypeErr(ctxt,
5180 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5181 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5182 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5183 val, NULL, NULL, NULL);
5184 return (def);
5185 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005186 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005187 ret = ret * 10 + (*cur - '0');
5188 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005189 }
William M. Brack76e95df2003-10-18 16:20:14 +00005190 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005191 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005192 /*
5193 * TODO: Restrict the maximal value to Integer.
5194 */
5195 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
5196 xmlSchemaPSimpleTypeErr(ctxt,
5197 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5198 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5199 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5200 val, NULL, NULL, NULL);
5201 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005202 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005203 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005204}
5205
5206/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005207 * xmlSchemaPGetBoolNodeValue:
5208 * @ctxt: a schema validation context
5209 * @ownerDes: owner designation
5210 * @ownerItem: the owner as a schema item
5211 * @node: the node holding the value
5212 *
5213 * Converts a boolean string value into 1 or 0.
5214 *
5215 * Returns 0 or 1.
5216 */
5217static int
5218xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5219 xmlChar **ownerDes,
5220 xmlSchemaTypePtr ownerItem,
5221 xmlNodePtr node)
5222{
5223 xmlChar *value = NULL;
5224 int res = 0;
5225
5226 value = xmlNodeGetContent(node);
5227 /*
5228 * 3.2.2.1 Lexical representation
5229 * An instance of a datatype that is defined as ·boolean·
5230 * can have the following legal literals {true, false, 1, 0}.
5231 */
5232 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5233 res = 1;
5234 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5235 res = 0;
5236 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5237 res = 1;
5238 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
5239 res = 0;
5240 else {
5241 xmlSchemaPSimpleTypeErr(ctxt,
5242 XML_SCHEMAP_INVALID_BOOLEAN,
5243 ownerDes, ownerItem, node,
5244 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5245 "(1 | 0 | true | false)", BAD_CAST value,
5246 NULL, NULL, NULL);
5247 }
5248 if (value != NULL)
5249 xmlFree(value);
5250 return (res);
5251}
5252
5253/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005254 * xmlGetBooleanProp:
5255 * @ctxt: a schema validation context
5256 * @node: a subtree containing XML Schema informations
5257 * @name: the attribute name
5258 * @def: the default value
5259 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005260 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005261 *
5262 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005263 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005264 */
5265static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00005266xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5267 xmlChar **ownerDes,
5268 xmlSchemaTypePtr ownerItem,
5269 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005270 const char *name, int def)
5271{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005272 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005273
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005274 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005275 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005276 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005277 /*
5278 * 3.2.2.1 Lexical representation
5279 * An instance of a datatype that is defined as ·boolean·
5280 * can have the following legal literals {true, false, 1, 0}.
5281 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005282 if (xmlStrEqual(val, BAD_CAST "true"))
5283 def = 1;
5284 else if (xmlStrEqual(val, BAD_CAST "false"))
5285 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005286 else if (xmlStrEqual(val, BAD_CAST "1"))
5287 def = 1;
5288 else if (xmlStrEqual(val, BAD_CAST "0"))
5289 def = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005290 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005291 xmlSchemaPSimpleTypeErr(ctxt,
5292 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005293 ownerDes, ownerItem,
5294 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
William M. Brack2f2a6632004-08-20 23:09:47 +00005295 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5296 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005297 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005298 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005299}
5300
5301/************************************************************************
5302 * *
5303 * Shema extraction from an Infoset *
5304 * *
5305 ************************************************************************/
5306static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5307 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005308 xmlNodePtr node,
5309 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005310static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5311 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005312 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005313 xmlNodePtr node,
5314 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005315static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5316 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005317 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005318 xmlNodePtr node,
5319 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005320static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5321 ctxt,
5322 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005323 xmlNodePtr node,
5324 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005325static xmlSchemaAttributeGroupPtr
5326xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005327 xmlSchemaPtr schema, xmlNodePtr node,
5328 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005329static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5330 xmlSchemaPtr schema,
5331 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005332static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005333xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5334 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005335
5336/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005337 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005338 *
5339 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005340 * @ownerDes: the designation of the parent element
5341 * @ownerItem: the schema object owner if existent
5342 * @attr: the schema attribute node being validated
5343 * @value: the value
5344 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005345 *
5346 * Validates a value against the given built-in type.
5347 * This one is intended to be used internally for validation
5348 * of schema attribute values during parsing of the schema.
5349 *
5350 * Returns 0 if the value is valid, a positive error code
5351 * number otherwise and -1 in case of an internal or API error.
5352 */
5353static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00005354xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
5355 xmlChar **ownerDes,
5356 xmlSchemaTypePtr ownerItem,
5357 xmlAttrPtr attr,
5358 const xmlChar *value,
5359 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005360{
Daniel Veillard01fa6152004-06-29 17:04:39 +00005361
Daniel Veillardc0826a72004-08-10 14:17:33 +00005362 int ret = 0;
5363
5364 /*
5365 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5366 * one is really meant to be used internally, so better not.
5367 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005368 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005369 return (-1);
5370 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5371 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005372 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005373 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005374 "type '%s' is not a built-in type.\n",
5375 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005376 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005377 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005378 switch (type->builtInType) {
5379 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005380 case XML_SCHEMAS_QNAME:
5381 case XML_SCHEMAS_ANYURI:
5382 case XML_SCHEMAS_TOKEN:
5383 case XML_SCHEMAS_LANGUAGE:
5384 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
5385 break;
5386
5387 /*
5388 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005389 ret = xmlValidateNCName(value, 1);
5390 break;
5391 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00005392 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005393 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005394 "Internal error: xmlSchemaPvalueAttrNode, use "
5395 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
5396 "for extracting QName valueues instead.\n",
5397 NULL, NULL);
5398 return (-1);
5399 case XML_SCHEMAS_ANYURI:
5400 if (value != NULL) {
5401 xmlURIPtr uri = xmlParseURI((const char *) value);
5402 if (uri == NULL)
5403 ret = 1;
5404 else
5405 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005406 }
5407 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005408 case XML_SCHEMAS_TOKEN: {
5409 const xmlChar *cur = value;
5410
5411 if (IS_BLANK_CH(*cur)) {
5412 ret = 1;
5413 } else while (*cur != 0) {
5414 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
5415 ret = 1;
5416 break;
5417 } else if (*cur == ' ') {
5418 cur++;
5419 if ((*cur == 0) || (*cur == ' ')) {
5420 ret = 1;
5421 break;
5422 }
5423 } else {
5424 cur++;
5425 }
5426 }
5427 }
5428 break;
5429 case XML_SCHEMAS_LANGUAGE:
5430 if (xmlCheckLanguageID(value) != 1)
5431 ret = 1;
5432 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005433 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005434 default: {
5435 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005436 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005437 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005438 "valueidation using the type '%s' is not implemented "
5439 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00005440 type->name, NULL);
5441 return (-1);
5442 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005443 }
5444 /*
5445 * TODO: Should we use the S4S error codes instead?
5446 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005447 if (ret < 0) {
5448 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
5449 XML_SCHEMAP_INTERNAL,
5450 "Internal error: xmlSchemaPValAttrNodeValue, "
5451 "failed to validate a schema attribute value.\n",
5452 NULL, NULL);
5453 return (-1);
5454 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005455 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
5456 xmlSchemaPSimpleTypeErr(ctxt,
5457 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
5458 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005459 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005460 NULL, NULL, NULL);
5461 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
5462 } else {
5463 xmlSchemaPSimpleTypeErr(ctxt,
5464 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
5465 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005466 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005467 NULL, NULL, NULL);
5468 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
5469 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005470 }
5471 return (ret);
5472}
5473
5474/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005475 * xmlSchemaPValAttrNode:
5476 *
5477 * @ctxt: a schema parser context
5478 * @ownerDes: the designation of the parent element
5479 * @ownerItem: the schema object owner if existent
5480 * @attr: the schema attribute node being validated
5481 * @type: the built-in type to be validated against
5482 * @value: the resulting value if any
5483 *
5484 * Extracts and validates a value against the given built-in type.
5485 * This one is intended to be used internally for validation
5486 * of schema attribute values during parsing of the schema.
5487 *
5488 * Returns 0 if the value is valid, a positive error code
5489 * number otherwise and -1 in case of an internal or API error.
5490 */
5491static int
5492xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5493 xmlChar **ownerDes,
5494 xmlSchemaTypePtr ownerItem,
5495 xmlAttrPtr attr,
5496 xmlSchemaTypePtr type,
5497 const xmlChar **value)
5498{
5499 const xmlChar *val;
5500
5501 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
5502 return (-1);
5503
5504 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5505 if (value != NULL)
5506 *value = val;
5507
5508 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
5509 val, type));
5510}
5511
5512/**
5513 * xmlSchemaPValAttr:
5514 *
5515 * @ctxt: a schema parser context
5516 * @node: the element node of the attribute
5517 * @ownerDes: the designation of the parent element
5518 * @ownerItem: the schema object owner if existent
5519 * @ownerElem: the owner element node
5520 * @name: the name of the schema attribute node
5521 * @type: the built-in type to be validated against
5522 * @value: the resulting value if any
5523 *
5524 * Extracts and validates a value against the given built-in type.
5525 * This one is intended to be used internally for validation
5526 * of schema attribute values during parsing of the schema.
5527 *
5528 * Returns 0 if the value is valid, a positive error code
5529 * number otherwise and -1 in case of an internal or API error.
5530 */
5531static int
5532xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
5533 xmlChar **ownerDes,
5534 xmlSchemaTypePtr ownerItem,
5535 xmlNodePtr ownerElem,
5536 const char *name,
5537 xmlSchemaTypePtr type,
5538 const xmlChar **value)
5539{
5540 xmlAttrPtr attr;
5541
5542 if ((ctxt == NULL) || (type == NULL)) {
5543 if (value != NULL)
5544 *value = NULL;
5545 return (-1);
5546 }
5547 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5548 if (value != NULL)
5549 *value = NULL;
5550 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005551 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005552 "Internal error: xmlSchemaPValAttr, the given "
5553 "type '%s' is not a built-in type.\n",
5554 type->name, NULL);
5555 return (-1);
5556 }
5557 attr = xmlSchemaGetPropNode(ownerElem, name);
5558 if (attr == NULL) {
5559 if (value != NULL)
5560 *value = NULL;
5561 return (0);
5562 }
5563 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
5564 type, value));
5565}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005566
5567static int
5568xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5569 xmlSchemaPtr schema,
5570 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005571 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005572 const xmlChar *namespaceName)
5573{
5574 if (xmlStrEqual(schema->targetNamespace, namespaceName))
5575 return (1);
5576 if (pctxt->localImports != NULL) {
5577 int i;
5578 for (i = 0; i < pctxt->nbLocalImports; i++)
5579 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5580 return (1);
5581 }
5582 if (namespaceName == NULL)
5583 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005584 NULL, (xmlSchemaTypePtr) item, node,
5585 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005586 "namespace are not valid, since not indicated by an import "
5587 "statement", NULL);
5588 else
5589 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005590 NULL, (xmlSchemaTypePtr) item, node,
5591 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005592 "namespace '%s' are not valid, since not indicated by an import "
5593 "statement", namespaceName);
5594 return (0);
5595}
5596
Daniel Veillardc0826a72004-08-10 14:17:33 +00005597/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005598 * xmlSchemaParseAttrDecls:
5599 * @ctxt: a schema validation context
5600 * @schema: the schema being built
5601 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005602 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005603 *
5604 * parse a XML schema attrDecls declaration corresponding to
5605 * <!ENTITY % attrDecls
5606 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5607 */
5608static xmlNodePtr
5609xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5610 xmlNodePtr child, xmlSchemaTypePtr type)
5611{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005612 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005613
Daniel Veillard4255d502002-04-16 15:50:10 +00005614 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005615 (IS_SCHEMA(child, "attributeGroup"))) {
5616 attr = NULL;
5617 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005618 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005619 } else if (IS_SCHEMA(child, "attributeGroup")) {
5620 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005621 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005622 }
5623 if (attr != NULL) {
5624 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005625 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5626 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5627 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005628 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005629 lastattr = attr;
5630 } else {
5631 lastattr->next = attr;
5632 lastattr = attr;
5633 }
5634 }
5635 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005636 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005637 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005638}
5639
5640/**
5641 * xmlSchemaParseAnnotation:
5642 * @ctxt: a schema validation context
5643 * @schema: the schema being built
5644 * @node: a subtree containing XML Schema informations
5645 *
5646 * parse a XML schema Attrribute declaration
5647 * *WARNING* this interface is highly subject to change
5648 *
William M. Bracke7091952004-05-11 15:09:58 +00005649 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005650 * 1 in case of success.
5651 */
5652static xmlSchemaAnnotPtr
5653xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5654 xmlNodePtr node)
5655{
5656 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005657 xmlNodePtr child = NULL;
5658 xmlAttrPtr attr;
5659 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005660
Daniel Veillardc0826a72004-08-10 14:17:33 +00005661 /*
5662 * INFO: S4S completed.
5663 */
5664 /*
5665 * id = ID
5666 * {any attributes with non-schema namespace . . .}>
5667 * Content: (appinfo | documentation)*
5668 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005669 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5670 return (NULL);
5671 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005672 attr = node->properties;
5673 while (attr != NULL) {
5674 if (((attr->ns == NULL) &&
5675 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
5676 ((attr->ns != NULL) &&
5677 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
5678
5679 xmlSchemaPIllegalAttrErr(ctxt,
5680 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5681 NULL, NULL, attr);
5682 }
5683 attr = attr->next;
5684 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005685 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005686 /*
5687 * And now for the children...
5688 */
5689 child = node->children;
5690 while (child != NULL) {
5691 if (IS_SCHEMA(child, "appinfo")) {
5692 /* TODO: make available the content of "appinfo". */
5693 /*
5694 * source = anyURI
5695 * {any attributes with non-schema namespace . . .}>
5696 * Content: ({any})*
5697 */
5698 attr = child->properties;
5699 while (attr != NULL) {
5700 if (((attr->ns == NULL) &&
5701 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
5702 ((attr->ns != NULL) &&
5703 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005704
Daniel Veillardc0826a72004-08-10 14:17:33 +00005705 xmlSchemaPIllegalAttrErr(ctxt,
5706 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5707 NULL, NULL, attr);
5708 }
5709 attr = attr->next;
5710 }
5711 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5712 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
5713 child = child->next;
5714 } else if (IS_SCHEMA(child, "documentation")) {
5715 /* TODO: make available the content of "documentation". */
5716 /*
5717 * source = anyURI
5718 * {any attributes with non-schema namespace . . .}>
5719 * Content: ({any})*
5720 */
5721 attr = child->properties;
5722 while (attr != NULL) {
5723 if (attr->ns == NULL) {
5724 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
5725 xmlSchemaPIllegalAttrErr(ctxt,
5726 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5727 NULL, NULL, attr);
5728 }
5729 } else {
5730 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5731 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5732 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
5733
5734 xmlSchemaPIllegalAttrErr(ctxt,
5735 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5736 NULL, NULL, attr);
5737 }
5738 }
5739 attr = attr->next;
5740 }
5741 /*
5742 * Attribute "xml:lang".
5743 */
5744 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5745 if (attr != NULL)
5746 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
5747 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
5748 child = child->next;
5749 } else {
5750 if (!barked)
5751 xmlSchemaPContentErr(ctxt,
5752 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5753 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5754 barked = 1;
5755 child = child->next;
5756 }
5757 }
5758
Daniel Veillard4255d502002-04-16 15:50:10 +00005759 return (ret);
5760}
5761
5762/**
5763 * xmlSchemaParseFacet:
5764 * @ctxt: a schema validation context
5765 * @schema: the schema being built
5766 * @node: a subtree containing XML Schema informations
5767 *
5768 * parse a XML schema Facet declaration
5769 * *WARNING* this interface is highly subject to change
5770 *
5771 * Returns the new type structure or NULL in case of error
5772 */
5773static xmlSchemaFacetPtr
5774xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005775 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005776{
5777 xmlSchemaFacetPtr facet;
5778 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005779 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005780
5781 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5782 return (NULL);
5783
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005784 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005785 if (facet == NULL) {
5786 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5787 return (NULL);
5788 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005789 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005790 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005791 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005792 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5793 "Facet %s has no value\n", node->name, NULL);
5794 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005795 return (NULL);
5796 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005797 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005798 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005799 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005800 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005801 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005802 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005803 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005804 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005805 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005806 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005807 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005808 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005809 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005810 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005811 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005812 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005813 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005814 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005815 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005816 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005817 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005818 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5819 } else if (IS_SCHEMA(node, "minLength")) {
5820 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5821 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005822 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5823 "Unknown facet type %s\n", node->name, NULL);
5824 xmlSchemaFreeFacet(facet);
5825 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005826 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005827 xmlSchemaPValAttrID(ctxt, NULL,
5828 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005829 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005830 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5831 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5832 const xmlChar *fixed;
5833
5834 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5835 if (fixed != NULL) {
5836 if (xmlStrEqual(fixed, BAD_CAST "true"))
5837 facet->fixed = 1;
5838 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005839 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005840 child = node->children;
5841
5842 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005843 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5844 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005845 }
5846 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005847 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5848 "Facet %s has unexpected child content\n",
5849 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005850 }
5851 return (facet);
5852}
5853
5854/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005855 * xmlSchemaParseWildcardNs:
5856 * @ctxt: a schema parser context
5857 * @wildc: the wildcard, already created
5858 * @node: a subtree containing XML Schema informations
5859 *
5860 * Parses the attribute "processContents" and "namespace"
5861 * of a xsd:anyAttribute and xsd:any.
5862 * *WARNING* this interface is highly subject to change
5863 *
5864 * Returns 0 if everything goes fine, a positive error code
5865 * if something is not valid and -1 if an internal error occurs.
5866 */
5867static int
5868xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5869 xmlSchemaPtr schema,
5870 xmlSchemaWildcardPtr wildc,
5871 xmlNodePtr node)
5872{
5873 const xmlChar *pc, *ns, *dictnsItem;
5874 int ret = 0;
5875 xmlChar *nsItem;
5876 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5877 xmlAttrPtr attr;
5878
5879 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5880 if ((pc == NULL)
5881 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5882 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5883 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5884 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5885 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5886 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5887 } else {
5888 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005889 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005890 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00005891 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005892 NULL, NULL, NULL);
5893 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005894 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005895 }
5896 /*
5897 * Build the namespace constraints.
5898 */
5899 attr = xmlSchemaGetPropNode(node, "namespace");
5900 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00005901 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005902 wildc->any = 1;
5903 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5904 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5905 if (wildc->negNsSet == NULL) {
5906 return (-1);
5907 }
5908 wildc->negNsSet->value = schema->targetNamespace;
5909 } else {
5910 const xmlChar *end, *cur;
5911
5912 cur = ns;
5913 do {
5914 while (IS_BLANK_CH(*cur))
5915 cur++;
5916 end = cur;
5917 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5918 end++;
5919 if (end == cur)
5920 break;
5921 nsItem = xmlStrndup(cur, end - cur);
5922 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5923 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
5924 xmlSchemaPSimpleTypeErr(ctxt,
5925 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
5926 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005927 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005928 "((##any | ##other) | List of (anyURI | "
5929 "(##targetNamespace | ##local)))",
5930 nsItem, NULL, NULL, NULL);
5931 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5932 } else {
5933 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5934 dictnsItem = schema->targetNamespace;
5935 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5936 dictnsItem = NULL;
5937 } else {
5938 /*
5939 * Validate the item (anyURI).
5940 */
5941 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
5942 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5943 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5944 }
5945 /*
5946 * Avoid dublicate namespaces.
5947 */
5948 tmp = wildc->nsSet;
5949 while (tmp != NULL) {
5950 if (dictnsItem == tmp->value)
5951 break;
5952 tmp = tmp->next;
5953 }
5954 if (tmp == NULL) {
5955 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5956 if (tmp == NULL) {
5957 xmlFree(nsItem);
5958 return (-1);
5959 }
5960 tmp->value = dictnsItem;
5961 tmp->next = NULL;
5962 if (wildc->nsSet == NULL)
5963 wildc->nsSet = tmp;
5964 else
5965 lastNs->next = tmp;
5966 lastNs = tmp;
5967 }
5968
5969 }
5970 xmlFree(nsItem);
5971 cur = end;
5972 } while (*cur != 0);
5973 }
5974 return (ret);
5975}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005976
5977static int
5978xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005979 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005980 xmlNodePtr node,
5981 int minOccurs,
5982 int maxOccurs) {
5983
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005984 if ((maxOccurs == 0) && ( minOccurs == 0))
5985 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005986 if (maxOccurs != UNBOUNDED) {
5987 /*
5988 * TODO: Maby we should better not create the particle,
5989 * if min/max is invalid, since it could confuse the build of the
5990 * content model.
5991 */
5992 /*
5993 * 3.9.6 Schema Component Constraint: Particle Correct
5994 *
5995 */
5996 if (maxOccurs < 1) {
5997 /*
5998 * 2.2 {max occurs} must be greater than or equal to 1.
5999 */
6000 xmlSchemaPCustomAttrErr(ctxt,
6001 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006002 NULL, NULL,
6003 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006004 "The value must be greater than or equal to 1");
6005 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6006 } else if (minOccurs > maxOccurs) {
6007 /*
6008 * 2.1 {min occurs} must not be greater than {max occurs}.
6009 */
6010 xmlSchemaPCustomAttrErr(ctxt,
6011 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006012 NULL, NULL,
6013 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006014 "The value must not be greater than the value of 'maxOccurs'");
6015 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6016 }
6017 }
6018 return (0);
6019}
6020
Daniel Veillardc0826a72004-08-10 14:17:33 +00006021/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006022 * xmlSchemaParseAny:
6023 * @ctxt: a schema validation context
6024 * @schema: the schema being built
6025 * @node: a subtree containing XML Schema informations
6026 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006027 * Parsea a XML schema <any> element. A particle and wildcard
6028 * will be created (except if minOccurs==maxOccurs==0, in this case
6029 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006030 * *WARNING* this interface is highly subject to change
6031 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006032 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006033 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006034static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006035xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6036 xmlNodePtr node)
6037{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006038 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006039 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006040 xmlSchemaWildcardPtr wild;
6041 int min, max;
6042 xmlAttrPtr attr;
6043 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006044
6045 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6046 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006047 /*
6048 * Check for illegal attributes.
6049 */
6050 attr = node->properties;
6051 while (attr != NULL) {
6052 if (attr->ns == NULL) {
6053 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6054 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6055 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6056 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6057 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6058 xmlSchemaPIllegalAttrErr(ctxt,
6059 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6060 NULL, NULL, attr);
6061 }
6062 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6063 xmlSchemaPIllegalAttrErr(ctxt,
6064 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6065 NULL, NULL, attr);
6066 }
6067 attr = attr->next;
6068 }
6069 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6070 /*
6071 * minOccurs/maxOccurs.
6072 */
6073 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006074 "(nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006075 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6076 "nonNegativeInteger");
6077 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6078 /*
6079 * Create & parse the wildcard.
6080 */
6081 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6082 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006083 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006084 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006085 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006086 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006087 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006088 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006089 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006090 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006091 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006092 }
6093 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006094 xmlSchemaPContentErr(ctxt,
6095 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6096 NULL, NULL, node, child,
6097 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006098 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006099 /*
6100 * No component if minOccurs==maxOccurs==0.
6101 */
6102 if ((min == 0) && (max == 0)) {
6103 /* Don't free the wildcard, since it's already on the list. */
6104 return (NULL);
6105 }
6106 /*
6107 * Create the particle.
6108 */
6109 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6110 if (particle == NULL)
6111 return (NULL);
6112 particle->annot = annot;
6113 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006114
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006115 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006116}
6117
6118/**
6119 * xmlSchemaParseNotation:
6120 * @ctxt: a schema validation context
6121 * @schema: the schema being built
6122 * @node: a subtree containing XML Schema informations
6123 *
6124 * parse a XML schema Notation declaration
6125 *
6126 * Returns the new structure or NULL in case of error
6127 */
6128static xmlSchemaNotationPtr
6129xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006130 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006131{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006132 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006133 xmlSchemaNotationPtr ret;
6134 xmlNodePtr child = NULL;
6135
6136 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6137 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006138 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006139 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006140 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6141 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006142 return (NULL);
6143 }
6144 ret = xmlSchemaAddNotation(ctxt, schema, name);
6145 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006146 return (NULL);
6147 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006148 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006149
6150 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6151 node, BAD_CAST "id");
6152
6153 if (IS_SCHEMA(child, "annotation")) {
6154 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6155 child = child->next;
6156 }
6157
Daniel Veillard4255d502002-04-16 15:50:10 +00006158 child = node->children;
6159 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006160 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6161 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006162 }
6163 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006164 xmlSchemaPContentErr(ctxt,
6165 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6166 NULL, NULL, node, child,
6167 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006168 }
6169
6170 return (ret);
6171}
6172
6173/**
6174 * xmlSchemaParseAnyAttribute:
6175 * @ctxt: a schema validation context
6176 * @schema: the schema being built
6177 * @node: a subtree containing XML Schema informations
6178 *
6179 * parse a XML schema AnyAttrribute declaration
6180 * *WARNING* this interface is highly subject to change
6181 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006182 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006183 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006184static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006185xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6186 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006187{
Daniel Veillard3646d642004-06-02 19:19:14 +00006188 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006189 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006190 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006191
6192 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6193 return (NULL);
6194
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006195 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6196 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006197 if (ret == NULL) {
6198 return (NULL);
6199 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006200 /*
6201 * Check for illegal attributes.
6202 */
6203 attr = node->properties;
6204 while (attr != NULL) {
6205 if (attr->ns == NULL) {
6206 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6207 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6208 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6209 xmlSchemaPIllegalAttrErr(ctxt,
6210 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6211 NULL, NULL, attr);
6212 }
6213 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6214 xmlSchemaPIllegalAttrErr(ctxt,
6215 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6216 NULL, NULL, attr);
6217 }
6218 attr = attr->next;
6219 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006220 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6221 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006222 /*
6223 * Parse the namespace list.
6224 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006225 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006226 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006227 /*
6228 * And now for the children...
6229 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006230 child = node->children;
6231 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006232 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6233 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006234 }
6235 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006236 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006237 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6238 NULL, NULL, node, child,
6239 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006240 }
6241
6242 return (ret);
6243}
6244
6245
6246/**
6247 * xmlSchemaParseAttribute:
6248 * @ctxt: a schema validation context
6249 * @schema: the schema being built
6250 * @node: a subtree containing XML Schema informations
6251 *
6252 * parse a XML schema Attrribute declaration
6253 * *WARNING* this interface is highly subject to change
6254 *
William M. Bracke7091952004-05-11 15:09:58 +00006255 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006256 */
6257static xmlSchemaAttributePtr
6258xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006259 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006260{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006261 const xmlChar *name, *attrValue;
6262 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006263 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006264 xmlNodePtr child = NULL;
6265 xmlAttrPtr attr, nameAttr;
6266 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006267
6268 /*
6269 * Note that the w3c spec assumes the schema to be validated with schema
6270 * for schemas beforehand.
6271 *
6272 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006273 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006274
6275 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6276 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006277 attr = xmlSchemaGetPropNode(node, "ref");
6278 nameAttr = xmlSchemaGetPropNode(node, "name");
6279
6280 if ((attr == NULL) && (nameAttr == NULL)) {
6281 /*
6282 * 3.2.3 : 3.1
6283 * One of ref or name must be present, but not both
6284 */
6285 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6286 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
6287 "One of the attributes 'ref' or 'name' must be present");
6288 return (NULL);
6289 }
6290 if ((topLevel) || (attr == NULL)) {
6291 if (nameAttr == NULL) {
6292 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6293 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
6294 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006295 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006296 }
6297 } else
6298 isRef = 1;
6299
6300 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006301 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006302 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
6303
6304 /*
6305 * Parse as attribute reference.
6306 */
6307 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6308 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6309 &refPrefix, &ref) != 0) {
6310 return (NULL);
6311 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006312 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006313 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006314 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006315 if (ret == NULL) {
6316 if (repName != NULL)
6317 xmlFree(repName);
6318 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006319 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006320 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6321 ret->node = node;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006322 ret->refNs = refNs;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006323 ret->refPrefix = refPrefix;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006324 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006325 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6326 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006327 /*
6328 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6329 */
6330 if (nameAttr != NULL)
6331 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6332 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6333 "ref", "name");
6334 /*
6335 * Check for illegal attributes.
6336 */
6337 attr = node->properties;
6338 while (attr != NULL) {
6339 if (attr->ns == NULL) {
6340 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6341 xmlStrEqual(attr->name, BAD_CAST "form")) {
6342 /*
6343 * 3.2.3 : 3.2
6344 * If ref is present, then all of <simpleType>,
6345 * form and type must be absent.
6346 */
6347 xmlSchemaPIllegalAttrErr(ctxt,
6348 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
6349 (xmlSchemaTypePtr) ret, attr);
6350 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6351 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6352 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6353 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6354 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6355 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
6356 xmlSchemaPIllegalAttrErr(ctxt,
6357 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6358 &repName, (xmlSchemaTypePtr) ret, attr);
6359 }
6360 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6361 xmlSchemaPIllegalAttrErr(ctxt,
6362 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6363 &repName, (xmlSchemaTypePtr) ret, attr);
6364 }
6365 attr = attr->next;
6366 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006367 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006368 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006369
6370 /*
6371 * Parse as attribute declaration.
6372 */
6373 if (xmlSchemaPValAttrNode(ctxt,
6374 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
6375 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6376 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006377 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006378 /*
6379 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6380 */
6381 /*
6382 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6383 */
6384 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
6385 xmlSchemaPSimpleTypeErr(ctxt,
6386 XML_SCHEMAP_NO_XMLNS,
6387 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006388 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006389 "The value must not match 'xmlns'",
6390 NULL, NULL);
6391 if (repName != NULL)
6392 xmlFree(repName);
6393 return (NULL);
6394 }
6395 /*
6396 * Evaluate the target namespace
6397 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006398 if (topLevel) {
6399 ns = schema->targetNamespace;
6400 } else {
6401 attr = xmlSchemaGetPropNode(node, "form");
6402 if (attr != NULL) {
6403 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6404 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6405 ns = schema->targetNamespace;
6406 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6407 xmlSchemaPSimpleTypeErr(ctxt,
6408 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6409 &repName, NULL, (xmlNodePtr) attr,
6410 NULL, "(qualified | unqualified)",
6411 attrValue, NULL, NULL, NULL);
6412 }
6413 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
6414 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006415 }
6416 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006417 if (ret == NULL) {
6418 if (repName != NULL)
6419 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006420 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006421 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006422 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006423 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006424 if (topLevel)
6425 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
6426 /*
6427 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6428 */
6429 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
6430 xmlSchemaPCustomErr(ctxt,
6431 XML_SCHEMAP_NO_XSI,
6432 &repName, (xmlSchemaTypePtr) ret, node,
6433 "The target namespace must not match '%s'",
6434 xmlSchemaInstanceNs);
6435 }
6436 /*
6437 * Check for illegal attributes.
6438 */
6439 attr = node->properties;
6440 while (attr != NULL) {
6441 if (attr->ns == NULL) {
6442 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6443 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6444 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6445 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6446 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
6447 if ((topLevel) ||
6448 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6449 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
6450 xmlSchemaPIllegalAttrErr(ctxt,
6451 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6452 &repName, (xmlSchemaTypePtr) ret, attr);
6453 }
6454 }
6455 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6456 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6457 &repName, (xmlSchemaTypePtr) ret, attr);
6458 }
6459 attr = attr->next;
6460 }
6461 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
6462 node, "type", &ret->typeNs, NULL, &ret->typeName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006463 }
6464 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6465 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006466 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006467 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006468 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006469 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6470 if (ret->defValue != NULL)
6471 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
6472 /*
6473 * Attribute "default".
6474 */
6475 attr = xmlSchemaGetPropNode(node, "default");
6476 if (attr != NULL) {
6477 /*
6478 * 3.2.3 : 1
6479 * default and fixed must not both be present.
6480 */
6481 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6482 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6483 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6484 } else
6485 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6486 }
6487 if (topLevel == 0) {
6488 /*
6489 * Attribute "use".
6490 */
6491 attr = xmlSchemaGetPropNode(node, "use");
6492 if (attr != NULL) {
6493 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6494 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6495 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6496 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6497 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6498 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6499 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6500 else
6501 xmlSchemaPSimpleTypeErr(ctxt,
6502 XML_SCHEMAP_INVALID_ATTR_USE,
6503 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006504 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006505 attrValue, NULL, NULL, NULL);
6506 } else
6507 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6508 /*
6509 * 3.2.3 : 2
6510 * If default and use are both present, use must have
6511 * the actual value optional.
6512 */
6513 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6514 (ret->defValue != NULL) &&
6515 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
6516 xmlSchemaPSimpleTypeErr(ctxt,
6517 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6518 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006519 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006520 "The value must be 'optional' if the attribute "
6521 "'default' is present as well", NULL, NULL);
6522 }
6523 }
6524 /*
6525 * And now for the children...
6526 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006527 child = node->children;
6528 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006529 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6530 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006531 }
6532 if (isRef) {
6533 if (child != NULL) {
6534 if (IS_SCHEMA(child, "simpleType"))
6535 /*
6536 * 3.2.3 : 3.2
6537 * If ref is present, then all of <simpleType>,
6538 * form and type must be absent.
6539 */
6540 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6541 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6542 "(annotation?)");
6543 else
6544 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6545 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6546 "(annotation?)");
6547 }
6548 } else {
6549 if (IS_SCHEMA(child, "simpleType")) {
6550 if (ret->typeName != NULL) {
6551 /*
6552 * 3.2.3 : 4
6553 * type and <simpleType> must not both be present.
6554 */
6555 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6556 &repName, (xmlSchemaTypePtr) ret, node, child,
6557 "The attribute 'type' and the <simpleType> child "
6558 "are mutually exclusive", NULL);
6559 } else
6560 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6561 child = child->next;
6562 }
6563 if (child != NULL)
6564 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6565 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6566 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006567 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006568 /*
6569 * Cleanup.
6570 */
6571 if (repName != NULL)
6572 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006573 return (ret);
6574}
6575
6576/**
6577 * xmlSchemaParseAttributeGroup:
6578 * @ctxt: a schema validation context
6579 * @schema: the schema being built
6580 * @node: a subtree containing XML Schema informations
6581 *
6582 * parse a XML schema Attribute Group declaration
6583 * *WARNING* this interface is highly subject to change
6584 *
6585 * Returns the attribute group or NULL in case of error.
6586 */
6587static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006588xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006589 xmlSchemaPtr schema, xmlNodePtr node,
6590 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006591{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006592 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006593 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006594 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006595 const xmlChar *oldcontainer;
6596 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006597
6598 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6599 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006600
6601 nameAttr = xmlSchemaGetPropNode(node, "name");
6602 attr = xmlSchemaGetPropNode(node, "ref");
6603 if ((topLevel) || (attr == NULL)) {
6604 /*
6605 * Parse as an attribute group definition.
6606 * Note that those are allowed at top level only.
6607 */
6608 if (nameAttr == NULL) {
6609 xmlSchemaPMissingAttrErr(ctxt,
6610 XML_SCHEMAP_S4S_ATTR_MISSING,
6611 NULL, NULL, node, "name", NULL);
6612 return (NULL);
6613 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006614 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
6615 * (xmlNodePtr) nameAttr);
6616 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006617 /*
6618 * The name is crucial, exit if invalid.
6619 */
6620 if (xmlSchemaPValAttrNode(ctxt,
6621 NULL, NULL, nameAttr,
6622 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6623 return (NULL);
6624 }
6625 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6626 if (ret == NULL)
6627 return (NULL);
6628 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6629 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6630 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006631 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006632 } else {
6633 char buf[50];
6634 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6635
6636 /*
6637 * Parse as an attribute group definition reference.
6638 */
6639 if (attr == NULL) {
6640 xmlSchemaPMissingAttrErr(ctxt,
6641 XML_SCHEMAP_S4S_ATTR_MISSING,
6642 NULL, NULL, node, "ref", NULL);
6643 }
6644 xmlSchemaPValAttrNodeQName(ctxt, schema,
6645 NULL, NULL, attr, &refNs, &refPrefix, &ref);
6646
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006647 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006648 name = (const xmlChar *) buf;
6649 if (name == NULL) {
6650 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6651 "attribute group definition reference", node);
6652 return (NULL);
6653 }
6654 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6655 if (ret == NULL)
6656 return (NULL);
6657 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6658 ret->ref = ref;
6659 ret->refNs = refNs;
6660 /* TODO: Is @refPrefix currently used? */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006661 ret->refPrefix = refPrefix;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006662 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006663 xmlSchemaCheckReference(ctxt, schema, node,
6664 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006665 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006666 /*
6667 * Check for illegal attributes.
6668 */
6669 attr = node->properties;
6670 while (attr != NULL) {
6671 if (attr->ns == NULL) {
6672 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6673 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
6674 (!xmlStrEqual(attr->name, BAD_CAST "id")))
6675 {
6676 xmlSchemaPIllegalAttrErr(ctxt,
6677 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6678 NULL, NULL, attr);
6679 }
6680 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6681 xmlSchemaPIllegalAttrErr(ctxt,
6682 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6683 NULL, NULL, attr);
6684 }
6685 attr = attr->next;
6686 }
6687 /* TODO: Validate "id" ? */
6688 /*
6689 * And now for the children...
6690 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006691 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006692 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006693 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006694 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006695 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6696 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006697 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006698 if (topLevel) {
6699 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
6700 if (IS_SCHEMA(child, "anyAttribute")) {
6701 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6702 child = child->next;
6703 }
6704 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006705 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006706 xmlSchemaPContentErr(ctxt,
6707 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6708 NULL, NULL, node, child, NULL,
6709 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006710 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006711 ctxt->container = oldcontainer;
6712 return (ret);
6713}
6714
6715/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006716 * xmlSchemaPValAttrFormDefault:
6717 * @value: the value
6718 * @flags: the flags to be modified
6719 * @flagQualified: the specific flag for "qualified"
6720 *
6721 * Returns 0 if the value is valid, 1 otherwise.
6722 */
6723static int
6724xmlSchemaPValAttrFormDefault(const xmlChar *value,
6725 int *flags,
6726 int flagQualified)
6727{
6728 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6729 if ((*flags & flagQualified) == 0)
6730 *flags |= flagQualified;
6731 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
6732 return (1);
6733
6734 return (0);
6735}
6736
6737/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006738 * xmlSchemaPValAttrBlockFinal:
6739 * @value: the value
6740 * @flags: the flags to be modified
6741 * @flagAll: the specific flag for "#all"
6742 * @flagExtension: the specific flag for "extension"
6743 * @flagRestriction: the specific flag for "restriction"
6744 * @flagSubstitution: the specific flag for "substitution"
6745 * @flagList: the specific flag for "list"
6746 * @flagUnion: the specific flag for "union"
6747 *
6748 * Validates the value of the attribute "final" and "block". The value
6749 * is converted into the specified flag values and returned in @flags.
6750 *
6751 * Returns 0 if the value is valid, 1 otherwise.
6752 */
6753
6754static int
6755xmlSchemaPValAttrBlockFinal(const xmlChar *value,
6756 int *flags,
6757 int flagAll,
6758 int flagExtension,
6759 int flagRestriction,
6760 int flagSubstitution,
6761 int flagList,
6762 int flagUnion)
6763{
6764 int ret = 0;
6765
6766 /*
6767 * TODO: This does not check for dublicate entries.
6768 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006769 if ((flags == NULL) || (value == NULL))
6770 return (-1);
6771 if (value[0] == 0)
6772 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006773 if (xmlStrEqual(value, BAD_CAST "#all")) {
6774 if (flagAll != -1)
6775 *flags |= flagAll;
6776 else {
6777 if (flagExtension != -1)
6778 *flags |= flagExtension;
6779 if (flagRestriction != -1)
6780 *flags |= flagRestriction;
6781 if (flagSubstitution != -1)
6782 *flags |= flagSubstitution;
6783 if (flagList != -1)
6784 *flags |= flagList;
6785 if (flagUnion != -1)
6786 *flags |= flagUnion;
6787 }
6788 } else {
6789 const xmlChar *end, *cur = value;
6790 xmlChar *item;
6791
6792 do {
6793 while (IS_BLANK_CH(*cur))
6794 cur++;
6795 end = cur;
6796 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6797 end++;
6798 if (end == cur)
6799 break;
6800 item = xmlStrndup(cur, end - cur);
6801 if (xmlStrEqual(item, BAD_CAST "extension")) {
6802 if (flagExtension != -1) {
6803 if ((*flags & flagExtension) == 0)
6804 *flags |= flagExtension;
6805 } else
6806 ret = 1;
6807 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6808 if (flagRestriction != -1) {
6809 if ((*flags & flagRestriction) == 0)
6810 *flags |= flagRestriction;
6811 } else
6812 ret = 1;
6813 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6814 if (flagSubstitution != -1) {
6815 if ((*flags & flagSubstitution) == 0)
6816 *flags |= flagSubstitution;
6817 } else
6818 ret = 1;
6819 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6820 if (flagList != -1) {
6821 if ((*flags & flagList) == 0)
6822 *flags |= flagList;
6823 } else
6824 ret = 1;
6825 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6826 if (flagUnion != -1) {
6827 if ((*flags & flagUnion) == 0)
6828 *flags |= flagUnion;
6829 } else
6830 ret = 1;
6831 } else
6832 ret = 1;
6833 if (item != NULL)
6834 xmlFree(item);
6835 cur = end;
6836 } while ((ret == 0) && (*cur != 0));
6837 }
6838
6839 return (ret);
6840}
6841
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006842static int
6843xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006844 xmlSchemaIDCPtr idc,
6845 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006846 xmlAttrPtr attr,
6847 int isField)
6848{
6849 xmlNodePtr node;
6850
6851 /*
6852 * c-selector-xpath:
6853 * Schema Component Constraint: Selector Value OK
6854 *
6855 * TODO: 1 The {selector} must be a valid XPath expression, as defined
6856 * in [XPath].
6857 */
6858 if (selector == NULL) {
6859 xmlSchemaPErr(ctxt, idc->node,
6860 XML_SCHEMAP_INTERNAL,
6861 "Internal error: xmlSchemaCheckCSelectorXPath, "
6862 "the selector is not specified.\n", NULL, NULL);
6863 return (-1);
6864 }
6865 if (attr == NULL)
6866 node = idc->node;
6867 else
6868 node = (xmlNodePtr) attr;
6869 if (selector->xpath == NULL) {
6870 xmlSchemaPCustomErr(ctxt,
6871 /* TODO: Adjust error code. */
6872 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6873 NULL, NULL, node,
6874 "The XPath expression of the selector is not valid", NULL);
6875 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6876 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006877 const xmlChar **nsArray = NULL;
6878 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006879 /*
6880 * Compile the XPath expression.
6881 */
6882 /*
6883 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006884 * TODO: Call xmlPatterncompile with different options for selector/
6885 * field.
6886 */
6887 nsList = xmlGetNsList(attr->doc, attr->parent);
6888 /*
6889 * Build an array of prefixes and namespaces.
6890 */
6891 if (nsList != NULL) {
6892 int i, count = 0;
6893 xmlNsPtr ns;
6894
6895 for (i = 0; nsList[i] != NULL; i++)
6896 count++;
6897
6898 nsArray = (const xmlChar **) xmlMalloc(
6899 (count * 2 + 1) * sizeof(const xmlChar *));
6900 if (nsArray == NULL) {
6901 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6902 NULL);
6903 return (-1);
6904 }
6905 for (i = 0; i < count; i++) {
6906 ns = nsList[i];
6907 nsArray[2 * i] = nsList[i]->href;
6908 nsArray[2 * i + 1] = nsList[i]->prefix;
6909 }
6910 nsArray[count * 2] = NULL;
6911 xmlFree(nsList);
6912 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006913 /*
6914 * TODO: Differentiate between "selector" and "field".
6915 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006916 if (isField)
6917 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006918 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006919 else
6920 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006921 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006922 if (nsArray != NULL)
6923 xmlFree((xmlChar **) nsArray);
6924
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006925 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006926 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006927 /* TODO: Adjust error code? */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006928 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6929 NULL, NULL, node,
6930 "The XPath expression '%s' could not be "
6931 "compiled", selector->xpath);
6932 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006933 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006934 }
6935 return (0);
6936}
6937
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006938#define ADD_ANNOTATION(annot) \
6939 xmlSchemaAnnotPtr cur = item->annot; \
6940 if (item->annot == NULL) { \
6941 item->annot = annot; \
6942 return (annot); \
6943 } \
6944 cur = item->annot; \
6945 if (cur->next != NULL) { \
6946 cur = cur->next; \
6947 } \
6948 cur->next = annot;
6949
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006950/**
6951 * xmlSchemaAssignAnnotation:
6952 * @item: the schema component
6953 * @annot: the annotation
6954 *
6955 * Adds the annotation to the given schema component.
6956 *
6957 * Returns the given annotaion.
6958 */
6959static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006960xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
6961 xmlSchemaAnnotPtr annot)
6962{
6963 if ((annItem == NULL) || (annot == NULL))
6964 return (NULL);
6965 switch (annItem->type) {
6966 case XML_SCHEMA_TYPE_ELEMENT: {
6967 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
6968 ADD_ANNOTATION(annot)
6969 }
6970 break;
6971 case XML_SCHEMA_TYPE_ATTRIBUTE: {
6972 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
6973 ADD_ANNOTATION(annot)
6974 }
6975 break;
6976 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
6977 case XML_SCHEMA_TYPE_ANY: {
6978 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
6979 ADD_ANNOTATION(annot)
6980 }
6981 break;
6982 case XML_SCHEMA_TYPE_PARTICLE:
6983 case XML_SCHEMA_TYPE_IDC_KEY:
6984 case XML_SCHEMA_TYPE_IDC_KEYREF:
6985 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
6986 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
6987 ADD_ANNOTATION(annot)
6988 }
6989 break;
6990 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
6991 xmlSchemaAttributeGroupPtr item =
6992 (xmlSchemaAttributeGroupPtr) annItem;
6993 ADD_ANNOTATION(annot)
6994 }
6995 break;
6996 case XML_SCHEMA_TYPE_NOTATION: {
6997 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
6998 ADD_ANNOTATION(annot)
6999 }
7000 break;
7001 case XML_SCHEMA_FACET_MININCLUSIVE:
7002 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7003 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7004 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7005 case XML_SCHEMA_FACET_TOTALDIGITS:
7006 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7007 case XML_SCHEMA_FACET_PATTERN:
7008 case XML_SCHEMA_FACET_ENUMERATION:
7009 case XML_SCHEMA_FACET_WHITESPACE:
7010 case XML_SCHEMA_FACET_LENGTH:
7011 case XML_SCHEMA_FACET_MAXLENGTH:
7012 case XML_SCHEMA_FACET_MINLENGTH: {
7013 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7014 ADD_ANNOTATION(annot)
7015 }
7016 break;
7017 case XML_SCHEMA_TYPE_SIMPLE:
7018 case XML_SCHEMA_TYPE_COMPLEX: {
7019 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7020 ADD_ANNOTATION(annot)
7021 }
7022 break;
7023 case XML_SCHEMA_TYPE_GROUP: {
7024 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7025 ADD_ANNOTATION(annot)
7026 }
7027 break;
7028 case XML_SCHEMA_TYPE_SEQUENCE:
7029 case XML_SCHEMA_TYPE_CHOICE:
7030 case XML_SCHEMA_TYPE_ALL: {
7031 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7032 ADD_ANNOTATION(annot)
7033 }
7034 break;
7035 default:
7036 xmlSchemaPCustomErr(NULL,
7037 XML_SCHEMAP_INTERNAL,
7038 NULL, NULL, NULL,
7039 "Internal error: xmlSchemaAddAnnotation, "
7040 "The item is not a annotated schema component", NULL);
7041 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007042 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007043 return (annot);
7044}
7045
7046/**
7047 * xmlSchemaParseIDCSelectorAndField:
7048 * @ctxt: a schema validation context
7049 * @schema: the schema being built
7050 * @node: a subtree containing XML Schema informations
7051 *
7052 * Parses a XML Schema identity-contraint definition's
7053 * <selector> and <field> elements.
7054 *
7055 * Returns the parsed identity-constraint definition.
7056 */
7057static xmlSchemaIDCSelectPtr
7058xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
7059 xmlSchemaPtr schema,
7060 xmlSchemaIDCPtr idc,
7061 xmlNodePtr node,
7062 int isField)
7063{
7064 xmlSchemaIDCSelectPtr item;
7065 xmlNodePtr child = NULL;
7066 xmlAttrPtr attr;
7067
7068 /*
7069 * Check for illegal attributes.
7070 */
7071 attr = node->properties;
7072 while (attr != NULL) {
7073 if (attr->ns == NULL) {
7074 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7075 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
7076 xmlSchemaPIllegalAttrErr(ctxt,
7077 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7078 NULL, NULL, attr);
7079 }
7080 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7081 xmlSchemaPIllegalAttrErr(ctxt,
7082 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7083 NULL, NULL, attr);
7084 }
7085 attr = attr->next;
7086 }
7087 /*
7088 * Create the item.
7089 */
7090 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7091 if (item == NULL) {
7092 xmlSchemaPErrMemory(ctxt,
7093 "allocating a 'selector' of an identity-constraint definition",
7094 NULL);
7095 return (NULL);
7096 }
7097 memset(item, 0, sizeof(xmlSchemaIDCSelect));
7098 /*
7099 * Attribute "xpath" (mandatory).
7100 */
7101 attr = xmlSchemaGetPropNode(node, "xpath");
7102 if (attr == NULL) {
7103 xmlSchemaPMissingAttrErr(ctxt,
7104 XML_SCHEMAP_S4S_ATTR_MISSING,
7105 NULL, NULL, node,
7106 "name", NULL);
7107 } else {
7108 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7109 /*
7110 * URGENT TODO: "field"s have an other syntax than "selector"s.
7111 */
7112
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007113 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7114 isField) == -1) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007115 xmlSchemaPErr(ctxt,
7116 (xmlNodePtr) attr,
7117 XML_SCHEMAP_INTERNAL,
7118 "Internal error: xmlSchemaParseIDCSelectorAndField, "
7119 "validating the XPath expression of a IDC selector.\n",
7120 NULL, NULL);
7121 }
7122
7123 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007124 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007125 /*
7126 * And now for the children...
7127 */
7128 child = node->children;
7129 if (IS_SCHEMA(child, "annotation")) {
7130 /*
7131 * Add the annotation to the parent IDC.
7132 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007133 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007134 xmlSchemaParseAnnotation(ctxt, schema, child));
7135 child = child->next;
7136 }
7137 if (child != NULL) {
7138 xmlSchemaPContentErr(ctxt,
7139 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7140 NULL, NULL, node, child,
7141 NULL, "(annotation?)");
7142 }
7143
7144 return (item);
7145}
7146
7147/**
7148 * xmlSchemaParseIDC:
7149 * @ctxt: a schema validation context
7150 * @schema: the schema being built
7151 * @node: a subtree containing XML Schema informations
7152 *
7153 * Parses a XML Schema identity-contraint definition.
7154 *
7155 * Returns the parsed identity-constraint definition.
7156 */
7157static xmlSchemaIDCPtr
7158xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
7159 xmlSchemaPtr schema,
7160 xmlNodePtr node,
7161 xmlSchemaTypeType idcCategory,
7162 const xmlChar *targetNamespace)
7163{
7164 xmlSchemaIDCPtr item = NULL;
7165 xmlNodePtr child = NULL;
7166 xmlAttrPtr attr;
7167 const xmlChar *name = NULL;
7168 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7169 int resAdd;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00007170
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007171 /*
7172 * Check for illegal attributes.
7173 */
7174 attr = node->properties;
7175 while (attr != NULL) {
7176 if (attr->ns == NULL) {
7177 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7178 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7179 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7180 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
7181 xmlSchemaPIllegalAttrErr(ctxt,
7182 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7183 NULL, NULL, attr);
7184 }
7185 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7186 xmlSchemaPIllegalAttrErr(ctxt,
7187 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7188 NULL, NULL, attr);
7189 }
7190 attr = attr->next;
7191 }
7192 /*
7193 * Attribute "name" (mandatory).
7194 */
7195 attr = xmlSchemaGetPropNode(node, "name");
7196 if (attr == NULL) {
7197 xmlSchemaPMissingAttrErr(ctxt,
7198 XML_SCHEMAP_S4S_ATTR_MISSING,
7199 NULL, NULL, node,
7200 "name", NULL);
7201 return (NULL);
7202 } else if (xmlSchemaPValAttrNode(ctxt,
7203 NULL, NULL, attr,
7204 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7205 return (NULL);
7206 }
7207 /*
7208 * Create the component.
7209 */
7210 if (schema->idcDef == NULL)
7211 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
7212 if (schema->idcDef == NULL)
7213 return (NULL);
7214
7215 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7216 if (item == NULL) {
7217 xmlSchemaPErrMemory(ctxt,
7218 "allocating an identity-constraint definition", NULL);
7219 return (NULL);
7220 }
7221 /*
7222 * Add the IDC to the list of IDCs on the schema component.
7223 */
7224 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
7225 if (resAdd != 0) {
7226 xmlSchemaPCustomErrExt(ctxt,
7227 XML_SCHEMAP_REDEFINED_TYPE,
7228 NULL, NULL, node,
7229 "An identity-constraint definition with the name '%s' "
7230 "and targetNamespace '%s' does already exist",
7231 name, targetNamespace, NULL);
7232 xmlFree(item);
7233 return (NULL);
7234 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007235 memset(item, 0, sizeof(xmlSchemaIDC));
7236 item->name = name;
7237 item->type = idcCategory;
7238 item->node = node;
7239 /*
7240 * The target namespace of the parent element declaration.
7241 */
7242 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007243 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7244 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007245 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7246 /*
7247 * Attribute "refer" (mandatory).
7248 */
7249 attr = xmlSchemaGetPropNode(node, "refer");
7250 if (attr == NULL) {
7251 xmlSchemaPMissingAttrErr(ctxt,
7252 XML_SCHEMAP_S4S_ATTR_MISSING,
7253 NULL, NULL, node,
7254 "refer", NULL);
7255 } else {
7256 /*
7257 * Create a reference item.
7258 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007259 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
7260 NULL, NULL);
7261 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007262 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007263 xmlSchemaPValAttrNodeQName(ctxt, schema,
7264 NULL, NULL, attr,
7265 &(item->ref->targetNamespace), 0,
7266 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007267 xmlSchemaCheckReference(ctxt, schema, node,
7268 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007269 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007270 }
7271 }
7272 /*
7273 * And now for the children...
7274 */
7275 child = node->children;
7276 if (IS_SCHEMA(child, "annotation")) {
7277 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7278 child = child->next;
7279 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007280 if (child == NULL) {
7281 xmlSchemaPContentErr(ctxt,
7282 XML_SCHEMAP_S4S_ELEM_MISSING,
7283 NULL, NULL, node, child,
7284 "A child element is missing",
7285 "(annotation?, (selector, field+))");
7286 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007287 /*
7288 * Child element <selector>.
7289 */
7290 if (IS_SCHEMA(child, "selector")) {
7291 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
7292 item, child, 0);
7293 child = child->next;
7294 /*
7295 * Child elements <field>.
7296 */
7297 if (IS_SCHEMA(child, "field")) {
7298 do {
7299 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
7300 item, child, 1);
7301 if (field != NULL) {
7302 field->index = item->nbFields;
7303 item->nbFields++;
7304 if (lastField != NULL)
7305 lastField->next = field;
7306 else
7307 item->fields = field;
7308 lastField = field;
7309 }
7310 child = child->next;
7311 } while (IS_SCHEMA(child, "field"));
7312 } else {
7313 xmlSchemaPContentErr(ctxt,
7314 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7315 NULL, NULL, node, child,
7316 NULL, "(annotation?, (selector, field+))");
7317 }
7318 }
7319 if (child != NULL) {
7320 xmlSchemaPContentErr(ctxt,
7321 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7322 NULL, NULL, node, child,
7323 NULL, "(annotation?, (selector, field+))");
7324 }
7325
7326 return (item);
7327}
7328
Daniel Veillardc0826a72004-08-10 14:17:33 +00007329/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007330 * xmlSchemaParseElement:
7331 * @ctxt: a schema validation context
7332 * @schema: the schema being built
7333 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007334 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007335 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007336 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007337 * *WARNING* this interface is highly subject to change
7338 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007339 * Returns the element declaration or a particle; NULL in case
7340 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007341 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007342static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007343xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007344 xmlNodePtr node, int topLevel)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007345{
7346 xmlSchemaElementPtr decl = NULL;
7347 xmlSchemaParticlePtr particle = NULL;
7348 xmlSchemaAnnotPtr annot = NULL;
7349 xmlNodePtr child = NULL;
7350 xmlAttrPtr attr, nameAttr;
7351 int min, max, isRef = 0;
7352 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007353
7354 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7355 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007356
Daniel Veillard4255d502002-04-16 15:50:10 +00007357 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007358 return (NULL);
7359 /*
7360 * If we get a "ref" attribute on a local <element> we will assume it's
7361 * a reference - even if there's a "name" attribute; this seems to be more
7362 * robust.
7363 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007364 nameAttr = xmlSchemaGetPropNode(node, "name");
7365 attr = xmlSchemaGetPropNode(node, "ref");
7366 if ((topLevel) || (attr == NULL)) {
7367 if (nameAttr == NULL) {
7368 xmlSchemaPMissingAttrErr(ctxt,
7369 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007370 NULL, NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007371 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007372 }
7373 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007374 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007375
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007376 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7377 child = node->children;
7378 if (IS_SCHEMA(child, "annotation")) {
7379 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7380 child = child->next;
7381 }
7382 /*
7383 * Skip particle part if a global declaration.
7384 */
7385 if (topLevel)
7386 goto declaration_part;
7387 /*
7388 * The particle part ==================================================
7389 */
7390 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7391 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
7392 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
7393 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7394 if (particle == NULL)
7395 goto return_null;
7396
7397 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7398
7399 if (isRef) {
7400 const xmlChar *refNs = NULL, *ref = NULL;
7401 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007402 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007403 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007404 */
7405 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007406 NULL, NULL, attr, &refNs, NULL, &ref);
7407 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007408 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007409 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007410 */
7411 if (nameAttr != NULL) {
7412 xmlSchemaPMutualExclAttrErr(ctxt,
7413 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007414 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007415 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007416 /*
7417 * Check for illegal attributes.
7418 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007419 attr = node->properties;
7420 while (attr != NULL) {
7421 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007422 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7423 xmlStrEqual(attr->name, BAD_CAST "name") ||
7424 xmlStrEqual(attr->name, BAD_CAST "id") ||
7425 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7426 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7427 {
7428 attr = attr->next;
7429 continue;
7430 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007431 /* SPEC (3.3.3 : 2.2) */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007432 xmlSchemaPCustomAttrErr(ctxt,
7433 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007434 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007435 "Only the attributes 'minOccurs', 'maxOccurs' and "
7436 "'id' are allowed in addition to 'ref'");
7437 break;
7438 }
7439 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7440 xmlSchemaPIllegalAttrErr(ctxt,
7441 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007442 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007443 }
7444 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007445 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007446 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007447 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007448 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007449 if (child != NULL) {
7450 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7451 NULL, NULL, node, child, NULL, "(annotation?)");
7452 }
7453 if ((min == 0) && (max == 0))
7454 goto return_null;
7455 /*
7456 * Create the reference item.
7457 */
7458 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7459 ref, refNs);
7460 if (refer == NULL)
7461 goto return_null;
7462 particle->children = (xmlSchemaTreeItemPtr) refer;
7463 particle->annot = annot;
7464 /*
7465 * Add to assembled items; the reference need to be resolved.
7466 */
7467 if (ctxt->assemble != NULL)
7468 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7469
7470 return ((xmlSchemaBasicItemPtr) particle);
7471 }
7472 /*
7473 * The declaration part ===============================================
7474 */
7475declaration_part:
7476 {
7477 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7478 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7479
7480 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007481 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007482 goto return_null;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007483 /*
7484 * Evaluate the target namespace.
7485 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007486 if (topLevel) {
7487 ns = schema->targetNamespace;
7488 } else {
7489 attr = xmlSchemaGetPropNode(node, "form");
7490 if (attr != NULL) {
7491 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7492 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007493 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007494 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
7495 xmlSchemaPSimpleTypeErr(ctxt,
7496 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007497 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007498 NULL, "(qualified | unqualified)",
7499 attrValue, NULL, NULL, NULL);
7500 }
7501 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7502 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00007503 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007504 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
7505 if (decl == NULL) {
7506 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007507 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007508 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7509 decl->node = node;
7510 decl->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007511 /*
7512 * Check for illegal attributes.
7513 */
William M. Bracke7091952004-05-11 15:09:58 +00007514 attr = node->properties;
7515 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007516 if (attr->ns == NULL) {
7517 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7518 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
7519 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7520 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7521 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7522 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007523 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7524 {
7525 if (topLevel == 0) {
7526 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007527 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007528 (!xmlStrEqual(attr->name, BAD_CAST "form")))
7529 {
7530 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
7531 /*
7532 * 3.3.6 : 3 If there is a non-·absent· {substitution
7533 * group affiliation}, then {scope} must be global.
7534 * TODO: This one is redundant, since the S4S does
7535 * prohibit this attribute on local declarations already;
7536 * so why an explicit error code? Weird spec.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007537 * TODO: Think about hanling this equal to the other attributes.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007538 */
7539 xmlSchemaPIllegalAttrErr(ctxt,
7540 XML_SCHEMAP_E_PROPS_CORRECT_3,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007541 NULL, (xmlSchemaTypePtr) decl, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007542 } else {
7543 xmlSchemaPIllegalAttrErr(ctxt,
7544 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007545 NULL, (xmlSchemaTypePtr) decl, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007546 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007547 }
7548 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7549 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
7550 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7551
7552 xmlSchemaPIllegalAttrErr(ctxt,
7553 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007554 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007555 }
7556 }
7557 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7558
7559 xmlSchemaPIllegalAttrErr(ctxt,
7560 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007561 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007562 }
7563 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007564 }
William M. Bracke7091952004-05-11 15:09:58 +00007565 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007566 * Extract/validate attributes.
7567 */
7568 if (topLevel) {
7569 /*
7570 * Process top attributes of global element declarations here.
7571 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007572 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7573 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
7574 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7575 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7576 &(decl->substGroupNs), NULL, &(decl->substGroup));
7577 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007578 node, "abstract", 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007579 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007580 /*
7581 * Attribute "final".
7582 */
7583 attr = xmlSchemaGetPropNode(node, "final");
7584 if (attr == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007585 decl->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007586 } else {
7587 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007588 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007589 -1,
7590 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7591 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
7592 xmlSchemaPSimpleTypeErr(ctxt,
7593 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007594 NULL, (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007595 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007596 attrValue, NULL, NULL, NULL);
7597 }
7598 }
7599 }
7600 /*
7601 * Attribute "block".
7602 */
7603 attr = xmlSchemaGetPropNode(node, "block");
7604 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007605 /*
7606 * Apply default "block" values.
7607 */
7608 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7609 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7610 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7611 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7612 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7613 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007614 } else {
7615 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007616 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007617 -1,
7618 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
7619 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
7620 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7621 xmlSchemaPSimpleTypeErr(ctxt,
7622 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007623 NULL, (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007624 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00007625 "restriction | substitution))", attrValue,
7626 NULL, NULL, NULL);
7627 }
7628 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007629 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007630 node, "nillable", 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007631 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007632
Daniel Veillardc0826a72004-08-10 14:17:33 +00007633 xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007634 NULL, (xmlSchemaTypePtr) decl, node,
7635 "type", &(decl->namedTypeNs), NULL, &(decl->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00007636
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007637 decl->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007638 attr = xmlSchemaGetPropNode(node, "fixed");
7639 if (attr != NULL) {
7640 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007641 if (decl->value != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007642 /*
7643 * 3.3.3 : 1
7644 * default and fixed must not both be present.
7645 */
7646 xmlSchemaPMutualExclAttrErr(ctxt,
7647 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007648 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007649 "default", "fixed");
7650 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007651 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7652 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007653 }
William M. Bracke7091952004-05-11 15:09:58 +00007654 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007655 /*
7656 * And now for the children...
7657 */
7658 oldcontainer = ctxt->container;
7659 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007660 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007661 /*
7662 * 3.3.3 : 3
7663 * "type" and either <simpleType> or <complexType> are mutually
7664 * exclusive
7665 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007666 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007667 xmlSchemaPContentErr(ctxt,
7668 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007669 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007670 "The attribute 'type' and the <complexType> child are "
7671 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007672 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007673 decl->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007674 child = child->next;
7675 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007676 /*
7677 * 3.3.3 : 3
7678 * "type" and either <simpleType> or <complexType> are
7679 * mutually exclusive
7680 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007681 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007682 xmlSchemaPContentErr(ctxt,
7683 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007684 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007685 "The attribute 'type' and the <simpleType> child are "
7686 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007687 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007688 decl->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007689 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007690 }
William M. Bracke7091952004-05-11 15:09:58 +00007691 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007692 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007693 if (IS_SCHEMA(child, "unique")) {
7694 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007695 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007696 } else if (IS_SCHEMA(child, "key")) {
7697 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007698 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007699 } else if (IS_SCHEMA(child, "keyref")) {
7700 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007701 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007702 }
7703 if (lastIDC != NULL)
7704 lastIDC->next = curIDC;
7705 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007706 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007707 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007708 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007709 }
7710 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007711 xmlSchemaPContentErr(ctxt,
7712 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007713 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007714 NULL, "(annotation?, ((simpleType | complexType)?, "
7715 "(unique | key | keyref)*))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007716 }
7717 ctxt->container = oldcontainer;
7718 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007719 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007720 /*
7721 * NOTE: Element Declaration Representation OK 4. will be checked at a
7722 * different layer.
7723 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007724 FREE_AND_NULL(des)
7725 if (topLevel)
7726 return ((xmlSchemaBasicItemPtr) decl);
7727 else {
7728 particle->children = (xmlSchemaTreeItemPtr) decl;
7729 return ((xmlSchemaBasicItemPtr) particle);
7730 }
7731
7732return_null:
7733 FREE_AND_NULL(des)
7734 if (annot != NULL)
7735 xmlSchemaFreeAnnot(annot);
7736 if (particle != NULL)
7737 xmlSchemaFreeParticle(particle);
7738 if (decl != NULL)
7739 xmlSchemaFreeElement(decl);
7740 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007741}
7742
7743/**
7744 * xmlSchemaParseUnion:
7745 * @ctxt: a schema validation context
7746 * @schema: the schema being built
7747 * @node: a subtree containing XML Schema informations
7748 *
7749 * parse a XML schema Union definition
7750 * *WARNING* this interface is highly subject to change
7751 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007752 * Returns -1 in case of internal error, 0 in case of success and a positive
7753 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007754 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007755static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007756xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007757 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007758{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007759 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007760 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007761 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007762 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007763
7764 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007765 return (-1);
7766 /* Not a component, don't create it. */
7767 type = ctxt->ctxtType;
7768 /*
7769 * Mark the simple type as being of variety "union".
7770 */
7771 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
William M. Brack2f2a6632004-08-20 23:09:47 +00007772 /*
7773 * Check for illegal attributes.
7774 */
7775 attr = node->properties;
7776 while (attr != NULL) {
7777 if (attr->ns == NULL) {
7778 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7779 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
7780 xmlSchemaPIllegalAttrErr(ctxt,
7781 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007782 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007783 }
7784 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7785 xmlSchemaPIllegalAttrErr(ctxt,
7786 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007787 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007788 }
7789 attr = attr->next;
7790 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007791 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007792 /*
7793 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007794 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007795 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007796 attr = xmlSchemaGetPropNode(node, "memberTypes");
7797 if (attr != NULL) {
7798 const xmlChar *end;
7799 xmlChar *tmp;
7800 const xmlChar *localName, *nsName;
7801 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7802 xmlSchemaQNameRefPtr ref;
7803
7804 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7805 type->ref = cur;
7806 do {
7807 while (IS_BLANK_CH(*cur))
7808 cur++;
7809 end = cur;
7810 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7811 end++;
7812 if (end == cur)
7813 break;
7814 tmp = xmlStrndup(cur, end - cur);
7815 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7816 NULL, attr, BAD_CAST tmp, &nsName, NULL, &localName) == 0) {
7817 /*
7818 * Create the member type link.
7819 */
7820 link = (xmlSchemaTypeLinkPtr)
7821 xmlMalloc(sizeof(xmlSchemaTypeLink));
7822 if (link == NULL) {
7823 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7824 "allocating a type link", NULL);
7825 return (-1);
7826 }
7827 link->type = NULL;
7828 link->next = NULL;
7829 if (lastLink == NULL)
7830 type->memberTypes = link;
7831 else
7832 lastLink->next = link;
7833 lastLink = link;
7834 /*
7835 * Create a reference item.
7836 */
7837 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
7838 localName, nsName);
7839 if (ref == NULL) {
7840 FREE_AND_NULL(tmp)
7841 return (-1);
7842 }
7843 /*
7844 * Assign the reference to the link, it will be resolved
7845 * later during fixup of the union simple type.
7846 */
7847 link->type = (xmlSchemaTypePtr) ref;
7848 }
7849 FREE_AND_NULL(tmp)
7850 cur = end;
7851 } while (*cur != 0);
7852
7853 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007854 /*
7855 * And now for the children...
7856 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007857 child = node->children;
7858 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007859 /*
7860 * Add the annotation to the simple type ancestor.
7861 */
7862 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7863 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007864 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007865 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007866 if (IS_SCHEMA(child, "simpleType")) {
7867 xmlSchemaTypePtr subtype, last = NULL;
7868
7869 /*
7870 * Anchor the member types in the "subtypes" field of the
7871 * simple type.
7872 */
7873 while (IS_SCHEMA(child, "simpleType")) {
7874 subtype = (xmlSchemaTypePtr)
7875 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7876 if (subtype != NULL) {
7877 if (last == NULL) {
7878 type->subtypes = subtype;
7879 last = subtype;
7880 } else {
7881 last->next = subtype;
7882 last = subtype;
7883 }
7884 last->next = NULL;
7885 }
7886 child = child->next;
7887 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007888 }
7889 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007890 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007891 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7892 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
7893 }
7894 if ((attr == NULL) && (type->subtypes == NULL)) {
7895 /*
7896 * src-union-memberTypes-or-simpleTypes
7897 * Either the memberTypes [attribute] of the <union> element must
7898 * be non-empty or there must be at least one simpleType [child].
7899 */
7900 xmlSchemaPCustomErr(ctxt,
7901 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
7902 NULL, NULL, node,
7903 "Either the attribute 'memberTypes' or "
7904 "at least one <simpleType> child must be present", NULL);
7905 }
7906 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007907}
7908
7909/**
7910 * xmlSchemaParseList:
7911 * @ctxt: a schema validation context
7912 * @schema: the schema being built
7913 * @node: a subtree containing XML Schema informations
7914 *
7915 * parse a XML schema List definition
7916 * *WARNING* this interface is highly subject to change
7917 *
William M. Bracke7091952004-05-11 15:09:58 +00007918 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007919 * 1 in case of success.
7920 */
7921static xmlSchemaTypePtr
7922xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007923 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007924{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007925 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007926 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007927 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007928
7929 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7930 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007931 /* Not a component, don't create it. */
7932 type = ctxt->ctxtType;
7933 /*
7934 * Mark the type as being of variety "list".
7935 */
7936 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
William M. Brack2f2a6632004-08-20 23:09:47 +00007937 /*
7938 * Check for illegal attributes.
7939 */
7940 attr = node->properties;
7941 while (attr != NULL) {
7942 if (attr->ns == NULL) {
7943 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7944 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
7945 xmlSchemaPIllegalAttrErr(ctxt,
7946 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007947 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007948 }
7949 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7950 xmlSchemaPIllegalAttrErr(ctxt,
7951 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007952 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007953 }
7954 attr = attr->next;
7955 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007956
7957 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7958
William M. Brack2f2a6632004-08-20 23:09:47 +00007959 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007960 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
7961 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00007962 */
7963 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007964 node, "itemType", &(type->refNs), NULL, &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00007965 /*
7966 * And now for the children...
7967 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007968 child = node->children;
7969 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007970 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7971 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007972 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007973 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007974 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007975 /*
7976 * src-list-itemType-or-simpleType
7977 * Either the itemType [attribute] or the <simpleType> [child] of
7978 * the <list> element must be present, but not both.
7979 */
7980 if (type->ref != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007981 xmlSchemaPCustomErr(ctxt,
7982 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007983 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00007984 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007985 "are mutually exclusive", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00007986 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007987 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007988 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007989 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007990 } else if (type->ref == NULL) {
7991 xmlSchemaPCustomErr(ctxt,
7992 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
7993 NULL, NULL, node,
7994 "Either the attribute 'itemType' or the <simpleType> child "
7995 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007996 }
7997 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007998 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007999 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8000 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008001 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008002 if ((type->ref == NULL) &&
8003 (type->subtypes == NULL) &&
8004 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
8005 xmlSchemaPCustomErr(ctxt,
8006 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
8007 NULL, NULL, node,
8008 "Either the attribute 'itemType' or the <simpleType> child "
8009 "must be present", NULL);
8010 }
8011 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008012}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008013
Daniel Veillard4255d502002-04-16 15:50:10 +00008014/**
8015 * xmlSchemaParseSimpleType:
8016 * @ctxt: a schema validation context
8017 * @schema: the schema being built
8018 * @node: a subtree containing XML Schema informations
8019 *
8020 * parse a XML schema Simple Type definition
8021 * *WARNING* this interface is highly subject to change
8022 *
William M. Bracke7091952004-05-11 15:09:58 +00008023 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008024 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008025 */
8026static xmlSchemaTypePtr
8027xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008028 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008029{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008030 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008031 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008032 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008033 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008034
8035 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8036 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008037
Daniel Veillardc0826a72004-08-10 14:17:33 +00008038 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008039 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008040 if (attr == NULL) {
8041 xmlSchemaPMissingAttrErr(ctxt,
8042 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008043 NULL, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008044 "name", NULL);
8045 return (NULL);
8046 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008047 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008048 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008049 return (NULL);
8050 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008051 }
8052
8053 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008054 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008055
Daniel Veillard01fa6152004-06-29 17:04:39 +00008056 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008057 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008058 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008059 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008060 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008061 if (type == NULL)
8062 return (NULL);
8063 type->node = node;
8064 type->type = XML_SCHEMA_TYPE_SIMPLE;
8065 /*
8066 * Check for illegal attributes.
8067 */
8068 attr = node->properties;
8069 while (attr != NULL) {
8070 if (attr->ns == NULL) {
8071 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
8072 xmlSchemaPIllegalAttrErr(ctxt,
8073 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008074 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008075 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008076 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8077 xmlSchemaPIllegalAttrErr(ctxt,
8078 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008079 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008080 }
8081 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008082 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008083 } else {
8084 /*
8085 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008086 *
8087 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008088 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008089 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008090 if (type == NULL)
8091 return (NULL);
8092 type->node = node;
8093 type->type = XML_SCHEMA_TYPE_SIMPLE;
8094 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8095 /*
8096 * Check for illegal attributes.
8097 */
8098 attr = node->properties;
8099 while (attr != NULL) {
8100 if (attr->ns == NULL) {
8101 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8102 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008103 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008104 xmlSchemaPIllegalAttrErr(ctxt,
8105 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008106 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008107 }
8108 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8109 xmlSchemaPIllegalAttrErr(ctxt,
8110 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008111 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008112 }
8113 attr = attr->next;
8114 }
8115 /*
8116 * Attribute "final".
8117 */
8118 attr = xmlSchemaGetPropNode(node, "final");
8119 if (attr == NULL) {
8120 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
8121 } else {
8122 attrValue = xmlSchemaGetProp(ctxt, node, "final");
8123 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8124 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
8125 XML_SCHEMAS_TYPE_FINAL_LIST,
8126 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8127
8128 xmlSchemaPSimpleTypeErr(ctxt,
8129 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008130 NULL, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00008131 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008132 attrValue, NULL, NULL, NULL);
8133 }
8134 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008135 }
8136 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008137 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008138 /*
8139 * And now for the children...
8140 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008141 oldCtxtType = ctxt->ctxtType;
8142 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008143 ctxt->ctxtType = type;
8144 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008145 child = node->children;
8146 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008147 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8148 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008149 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008150 if (child == NULL) {
8151 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8152 NULL, type, node, child, NULL,
8153 "(annotation?, (restriction | list | union))");
8154 } else if (IS_SCHEMA(child, "restriction")) {
8155 xmlSchemaParseRestriction(ctxt, schema, child,
8156 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008157 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008158 } else if (IS_SCHEMA(child, "list")) {
8159 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008160 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008161 } else if (IS_SCHEMA(child, "union")) {
8162 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008163 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008164 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008165 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008166 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008167 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008168 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008169 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008170 ctxt->parentItem = oldParentItem;
8171 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008172
Daniel Veillard4255d502002-04-16 15:50:10 +00008173 return (type);
8174}
8175
Daniel Veillard4255d502002-04-16 15:50:10 +00008176/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008177 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008178 * @ctxt: a schema validation context
8179 * @schema: the schema being built
8180 * @node: a subtree containing XML Schema informations
8181 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008182 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008183 * *WARNING* this interface is highly subject to change
8184 *
William M. Bracke7091952004-05-11 15:09:58 +00008185 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008186 * 1 in case of success.
8187 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008188static xmlSchemaTreeItemPtr
8189xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8190 xmlSchemaPtr schema,
8191 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008192{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008193 xmlSchemaParticlePtr item;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008194 xmlNodePtr child = NULL;
8195 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008196 const xmlChar *ref = NULL, *refNs = NULL;
8197 int min, max;
8198
8199 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8200 return (NULL);
8201
8202 attr = xmlSchemaGetPropNode(node, "ref");
8203 if (attr == NULL) {
8204 xmlSchemaPMissingAttrErr(ctxt,
8205 XML_SCHEMAP_S4S_ATTR_MISSING,
8206 NULL, NULL, node,
8207 "ref", NULL);
8208 return (NULL);
8209 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
8210 attr, &refNs, NULL, &ref) != 0) {
8211 return (NULL);
8212 }
8213 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8214 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8215 "(nonNegativeInteger | unbounded)");
8216 /*
8217 * Check for illegal attributes.
8218 */
8219 attr = node->properties;
8220 while (attr != NULL) {
8221 if (attr->ns == NULL) {
8222 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
8223 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8224 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8225 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
8226 xmlSchemaPIllegalAttrErr(ctxt,
8227 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8228 NULL, NULL, attr);
8229 }
8230 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8231 xmlSchemaPIllegalAttrErr(ctxt,
8232 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8233 NULL, NULL, attr);
8234 }
8235 attr = attr->next;
8236 }
8237 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8238 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8239 if (item == NULL)
8240 return (NULL);
8241 /*
8242 * Create a reference item as the term; it will be substituted for
8243 * the model group after the reference has been resolved.
8244 */
8245 item->children = (xmlSchemaTreeItemPtr)
8246 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8247 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8248 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8249 /*
8250 * And now for the children...
8251 */
8252 child = node->children;
8253 /* TODO: Is annotation even allowed for a model group reference? */
8254 if (IS_SCHEMA(child, "annotation")) {
8255 /*
8256 * TODO: What to do exactly with the annotation?
8257 */
8258 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8259 child = child->next;
8260 }
8261 if (child != NULL) {
8262 xmlSchemaPContentErr(ctxt,
8263 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8264 NULL, NULL, node, child, NULL,
8265 "(annotation?)");
8266 }
8267 /*
8268 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8269 */
8270 if ((min == 0) && (max == 0))
8271 return (NULL);
8272 if (ctxt->assemble != NULL)
8273 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8274 return ((xmlSchemaTreeItemPtr) item);
8275}
8276
8277/**
8278 * xmlSchemaParseModelGroupDefinition:
8279 * @ctxt: a schema validation context
8280 * @schema: the schema being built
8281 * @node: a subtree containing XML Schema informations
8282 *
8283 * Parses a XML schema model group definition.
8284 * *WARNING* this interface is highly subject to change
8285 *
8286 * Returns -1 in case of error, 0 if the declaration is improper and
8287 * 1 in case of success.
8288 */
8289static xmlSchemaModelGroupDefPtr
8290xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8291 xmlSchemaPtr schema,
8292 xmlNodePtr node)
8293{
8294 xmlSchemaModelGroupDefPtr item;
8295 xmlNodePtr child = NULL;
8296 xmlAttrPtr attr;
8297 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008298
8299 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008300 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008301
8302 attr = xmlSchemaGetPropNode(node, "name");
8303 if (attr == NULL) {
8304 xmlSchemaPMissingAttrErr(ctxt,
8305 XML_SCHEMAP_S4S_ATTR_MISSING,
8306 NULL, NULL, node,
8307 "name", NULL);
8308 return (NULL);
8309 } else if (xmlSchemaPValAttrNode(ctxt,
8310 NULL, NULL, attr,
8311 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8312 return (NULL);
8313 }
8314 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8315 if (item == NULL)
8316 return (NULL);
8317 /*
8318 * Check for illegal attributes.
8319 */
8320 attr = node->properties;
8321 while (attr != NULL) {
8322 if (attr->ns == NULL) {
8323 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8324 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
8325 xmlSchemaPIllegalAttrErr(ctxt,
8326 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8327 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008328 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008329 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8330 xmlSchemaPIllegalAttrErr(ctxt,
8331 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8332 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008333 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008334 attr = attr->next;
8335 }
8336 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8337 /*
8338 * And now for the children...
8339 */
8340 child = node->children;
8341 if (IS_SCHEMA(child, "annotation")) {
8342 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8343 child = child->next;
8344 }
8345 if (IS_SCHEMA(child, "all")) {
8346 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8347 XML_SCHEMA_TYPE_ALL, 0);
8348 child = child->next;
8349 } else if (IS_SCHEMA(child, "choice")) {
8350 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8351 XML_SCHEMA_TYPE_CHOICE, 0);
8352 child = child->next;
8353 } else if (IS_SCHEMA(child, "sequence")) {
8354 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8355 XML_SCHEMA_TYPE_SEQUENCE, 0);
8356 child = child->next;
8357 }
8358 if (child != NULL) {
8359 xmlSchemaPContentErr(ctxt,
8360 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8361 NULL, NULL, node, child, NULL,
8362 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008363 }
8364
8365 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008366}
8367
8368/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008369 * xmlSchemaCleanupDoc:
8370 * @ctxt: a schema validation context
8371 * @node: the root of the document.
8372 *
8373 * removes unwanted nodes in a schemas document tree
8374 */
8375static void
8376xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8377{
8378 xmlNodePtr delete, cur;
8379
8380 if ((ctxt == NULL) || (root == NULL)) return;
8381
8382 /*
8383 * Remove all the blank text nodes
8384 */
8385 delete = NULL;
8386 cur = root;
8387 while (cur != NULL) {
8388 if (delete != NULL) {
8389 xmlUnlinkNode(delete);
8390 xmlFreeNode(delete);
8391 delete = NULL;
8392 }
8393 if (cur->type == XML_TEXT_NODE) {
8394 if (IS_BLANK_NODE(cur)) {
8395 if (xmlNodeGetSpacePreserve(cur) != 1) {
8396 delete = cur;
8397 }
8398 }
8399 } else if ((cur->type != XML_ELEMENT_NODE) &&
8400 (cur->type != XML_CDATA_SECTION_NODE)) {
8401 delete = cur;
8402 goto skip_children;
8403 }
8404
8405 /*
8406 * Skip to next node
8407 */
8408 if (cur->children != NULL) {
8409 if ((cur->children->type != XML_ENTITY_DECL) &&
8410 (cur->children->type != XML_ENTITY_REF_NODE) &&
8411 (cur->children->type != XML_ENTITY_NODE)) {
8412 cur = cur->children;
8413 continue;
8414 }
8415 }
8416 skip_children:
8417 if (cur->next != NULL) {
8418 cur = cur->next;
8419 continue;
8420 }
8421
8422 do {
8423 cur = cur->parent;
8424 if (cur == NULL)
8425 break;
8426 if (cur == root) {
8427 cur = NULL;
8428 break;
8429 }
8430 if (cur->next != NULL) {
8431 cur = cur->next;
8432 break;
8433 }
8434 } while (cur != NULL);
8435 }
8436 if (delete != NULL) {
8437 xmlUnlinkNode(delete);
8438 xmlFreeNode(delete);
8439 delete = NULL;
8440 }
8441}
8442
William M. Brack2f2a6632004-08-20 23:09:47 +00008443
8444/**
8445 * xmlSchemaImportSchema
8446 *
8447 * @ctxt: a schema validation context
8448 * @schemaLocation: an URI defining where to find the imported schema
8449 *
8450 * import a XML schema
8451 * *WARNING* this interface is highly subject to change
8452 *
8453 * Returns -1 in case of error and 1 in case of success.
8454 */
8455#if 0
8456static xmlSchemaImportPtr
8457xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8458 const xmlChar *schemaLocation)
8459{
8460 xmlSchemaImportPtr import;
8461 xmlSchemaParserCtxtPtr newctxt;
8462
8463 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8464 if (newctxt == NULL) {
8465 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8466 NULL);
8467 return (NULL);
8468 }
8469 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8470 /* Keep the same dictionnary for parsing, really */
8471 xmlDictReference(ctxt->dict);
8472 newctxt->dict = ctxt->dict;
8473 newctxt->includes = 0;
8474 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8475
8476 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8477 ctxt->userData);
8478
8479 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8480 if (import == NULL) {
8481 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8482 NULL);
8483 xmlSchemaFreeParserCtxt(newctxt);
8484 return (NULL);
8485 }
8486
8487 memset(import, 0, sizeof(xmlSchemaImport));
8488 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8489 import->schema = xmlSchemaParse(newctxt);
8490
8491 if (import->schema == NULL) {
8492 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008493 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008494 "Failed to import schema from location \"%s\".\n",
8495 schemaLocation, NULL);
8496
8497 xmlSchemaFreeParserCtxt(newctxt);
8498 /* The schemaLocation is held by the dictionary.
8499 if (import->schemaLocation != NULL)
8500 xmlFree((xmlChar *)import->schemaLocation);
8501 */
8502 xmlFree(import);
8503 return NULL;
8504 }
8505
8506 xmlSchemaFreeParserCtxt(newctxt);
8507 return import;
8508}
8509#endif
8510
8511static void
8512xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8513{
8514 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8515 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8516
8517 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8518 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8519
8520 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8521 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8522 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8523 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8524 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8525 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8526 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8527 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8528
8529 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8530 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8531 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8532 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8533 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8534 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8535}
8536
8537static void
8538xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
8539 xmlSchemaPtr schema,
8540 xmlNodePtr node)
8541{
8542 xmlAttrPtr attr;
8543 const xmlChar *val;
8544
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008545 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8546 if (schema->version == NULL)
8547 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8548 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8549 else
8550 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8551 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8552
William M. Brack2f2a6632004-08-20 23:09:47 +00008553 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
8554 if (attr != NULL) {
8555 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8556 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
8557 XML_SCHEMAS_QUALIF_ELEM) != 0) {
8558 xmlSchemaPSimpleTypeErr(ctxt,
8559 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
8560 NULL, NULL, (xmlNodePtr) attr, NULL,
8561 "(qualified | unqualified)", val, NULL, NULL, NULL);
8562 }
8563 }
8564
8565 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
8566 if (attr != NULL) {
8567 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8568 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
8569 XML_SCHEMAS_QUALIF_ATTR) != 0) {
8570 xmlSchemaPSimpleTypeErr(ctxt,
8571 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
8572 NULL, NULL, (xmlNodePtr) attr, NULL,
8573 "(qualified | unqualified)", val, NULL, NULL, NULL);
8574 }
8575 }
8576
8577 attr = xmlSchemaGetPropNode(node, "finalDefault");
8578 if (attr != NULL) {
8579 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8580 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8581 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8582 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8583 -1,
8584 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8585 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8586 xmlSchemaPSimpleTypeErr(ctxt,
8587 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8588 NULL, NULL, (xmlNodePtr) attr, NULL,
8589 "(#all | List of (extension | restriction | list | union))",
8590 val, NULL, NULL, NULL);
8591 }
8592 }
8593
8594 attr = xmlSchemaGetPropNode(node, "blockDefault");
8595 if (attr != NULL) {
8596 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8597 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8598 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8599 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8600 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8601 xmlSchemaPSimpleTypeErr(ctxt,
8602 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8603 NULL, NULL, (xmlNodePtr) attr, NULL,
8604 "(#all | List of (extension | restriction | substitution))",
8605 val, NULL, NULL, NULL);
8606 }
8607 }
8608}
8609
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008610/**
8611 * xmlSchemaParseSchemaTopLevel:
8612 * @ctxt: a schema validation context
8613 * @schema: the schemas
8614 * @nodes: the list of top level nodes
8615 *
8616 * Returns the internal XML Schema structure built from the resource or
8617 * NULL in case of error
8618 */
8619static void
8620xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8621 xmlSchemaPtr schema, xmlNodePtr nodes)
8622{
8623 xmlNodePtr child;
8624 xmlSchemaAnnotPtr annot;
8625
8626 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8627 return;
8628
8629 child = nodes;
8630 while ((IS_SCHEMA(child, "include")) ||
8631 (IS_SCHEMA(child, "import")) ||
8632 (IS_SCHEMA(child, "redefine")) ||
8633 (IS_SCHEMA(child, "annotation"))) {
8634 if (IS_SCHEMA(child, "annotation")) {
8635 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8636 if (schema->annot == NULL)
8637 schema->annot = annot;
8638 else
8639 xmlSchemaFreeAnnot(annot);
8640 } else if (IS_SCHEMA(child, "import")) {
8641 xmlSchemaParseImport(ctxt, schema, child);
8642 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008643 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008644 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008645 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008646 } else if (IS_SCHEMA(child, "redefine")) {
8647 TODO
8648 }
8649 child = child->next;
8650 }
8651 while (child != NULL) {
8652 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008653 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008654 child = child->next;
8655 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008656 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008657 child = child->next;
8658 } else if (IS_SCHEMA(child, "element")) {
8659 xmlSchemaParseElement(ctxt, schema, child, 1);
8660 child = child->next;
8661 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008662 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008663 child = child->next;
8664 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008665 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008666 child = child->next;
8667 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008668 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008669 child = child->next;
8670 } else if (IS_SCHEMA(child, "notation")) {
8671 xmlSchemaParseNotation(ctxt, schema, child);
8672 child = child->next;
8673 } else {
8674 xmlSchemaPErr2(ctxt, NULL, child,
8675 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008676 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008677 child->name, NULL);
8678 child = child->next;
8679 }
8680 while (IS_SCHEMA(child, "annotation")) {
8681 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8682 if (schema->annot == NULL)
8683 schema->annot = annot;
8684 else
8685 xmlSchemaFreeAnnot(annot);
8686 child = child->next;
8687 }
8688 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008689 ctxt->parentItem = NULL;
8690 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008691}
8692
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008693static xmlSchemaImportPtr
8694xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
8695 xmlHashTablePtr *imports,
8696 const xmlChar *nsName)
8697{
8698 xmlSchemaImportPtr ret;
8699
8700 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008701 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008702 if (*imports == NULL) {
8703 xmlSchemaPCustomErr(ctxt,
8704 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8705 NULL, NULL, (xmlNodePtr) ctxt->doc,
8706 "Internal error: failed to build the import table",
8707 NULL);
8708 return (NULL);
8709 }
8710 }
8711 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8712 if (ret == NULL) {
8713 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8714 return (NULL);
8715 }
8716 memset(ret, 0, sizeof(xmlSchemaImport));
8717 if (nsName == NULL)
8718 nsName = XML_SCHEMAS_NO_NAMESPACE;
8719 xmlHashAddEntry(*imports, nsName, ret);
8720
8721 return (ret);
8722}
8723
8724static int
8725xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008726 xmlSchemaPtr schema,
8727 xmlNodePtr node,
8728 const xmlChar *nsName,
8729 const xmlChar *location,
8730 xmlDocPtr *doc,
8731 const xmlChar **targetNamespace,
8732 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008733{
8734 xmlParserCtxtPtr parserCtxt;
8735 xmlSchemaImportPtr import;
8736 const xmlChar *ns;
8737 xmlNodePtr root;
8738
8739 /*
8740 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8741 * <xsi:noNamespaceSchemaLocation>.
8742 */
8743 *doc = NULL;
8744 /*
8745 * Given that the schemaLocation [attribute] is only a hint, it is open
8746 * to applications to ignore all but the first <import> for a given
8747 * namespace, regardless of the ·actual value· of schemaLocation, but
8748 * such a strategy risks missing useful information when new
8749 * schemaLocations are offered.
8750 *
8751 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8752 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8753 * valid or not.
8754 * We will follow XSV here.
8755 */
8756 if (location == NULL) {
8757 /*
8758 * Schema Document Location Strategy:
8759 *
8760 * 3 Based on the namespace name, identify an existing schema document,
8761 * either as a resource which is an XML document or a <schema> element
8762 * information item, in some local schema repository;
8763 *
8764 * 5 Attempt to resolve the namespace name to locate such a resource.
8765 *
8766 * NOTE: Those stategies are not supported, so we will skip.
8767 */
8768 return (0);
8769 }
8770 if (nsName == NULL)
8771 ns = XML_SCHEMAS_NO_NAMESPACE;
8772 else
8773 ns = nsName;
8774
8775 import = xmlHashLookup(schema->schemasImports, ns);
8776 if (import != NULL) {
8777 /*
8778 * There was a valid resource for the specified namespace already
8779 * defined, so skip.
8780 * TODO: This might be changed someday to allow import of
8781 * components from multiple documents for a single target namespace.
8782 */
8783 return (0);
8784 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008785
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008786 /*
8787 * Schema Document Location Strategy:
8788 *
8789 * 2 Based on the location URI, identify an existing schema document,
8790 * either as a resource which is an XML document or a <schema> element
8791 * information item, in some local schema repository;
8792 *
8793 * 4 Attempt to resolve the location URI, to locate a resource on the
8794 * web which is or contains or references a <schema> element;
8795 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8796 *
8797 */
8798 if ((absolute == 0) && (node != NULL)) {
8799 xmlChar *base, *URI;
8800
8801 base = xmlNodeGetBase(node->doc, node);
8802 if (base == NULL) {
8803 URI = xmlBuildURI(location, node->doc->URL);
8804 } else {
8805 URI = xmlBuildURI(location, base);
8806 xmlFree(base);
8807 }
8808 if (URI != NULL) {
8809 location = xmlDictLookup(ctxt->dict, URI, -1);
8810 xmlFree(URI);
8811 }
8812 }
8813 parserCtxt = xmlNewParserCtxt();
8814 if (parserCtxt == NULL) {
8815 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8816 "allocating a parser context", NULL);
8817 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008818 }
8819
8820 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
8821 xmlDictFree(parserCtxt->dict);
8822 parserCtxt->dict = ctxt->dict;
8823 xmlDictReference(parserCtxt->dict);
8824 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008825
8826 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
8827 NULL, SCHEMAS_PARSE_OPTIONS);
8828
8829 /*
8830 * 2.1 The referent is (a fragment of) a resource which is an
8831 * XML document (see clause 1.1), which in turn corresponds to
8832 * a <schema> element information item in a well-formed information
8833 * set, which in turn corresponds to a valid schema.
8834 * TODO: What to do with the "fragment" stuff?
8835 *
8836 * 2.2 The referent is a <schema> element information item in
8837 * a well-formed information set, which in turn corresponds
8838 * to a valid schema.
8839 * NOTE: 2.2 won't apply, since only XML documents will be processed
8840 * here.
8841 */
8842 if (*doc == NULL) {
8843 xmlErrorPtr lerr;
8844 /*
8845 * It is *not* an error for the application schema reference
8846 * strategy to fail.
8847 *
8848 * If the doc is NULL and the parser error is an IO error we
8849 * will assume that the resource could not be located or accessed.
8850 *
8851 * TODO: Try to find specific error codes to react only on
8852 * localisation failures.
8853 *
8854 * TODO, FIXME: Check the spec: is a namespace added to the imported
8855 * namespaces, even if the schemaLocation did not provide
8856 * a resource? I guess so, since omitting the "schemaLocation"
8857 * attribute, imports a namespace as well.
8858 */
8859 lerr = xmlGetLastError();
8860 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
8861 xmlFreeParserCtxt(parserCtxt);
8862 return(0);
8863 }
8864
8865 xmlSchemaPCustomErr(ctxt,
8866 XML_SCHEMAP_SRC_IMPORT_2_1,
8867 NULL, NULL, node,
8868 "Failed to parse the resource '%s' for import",
8869 location);
8870 xmlFreeParserCtxt(parserCtxt);
8871 return(XML_SCHEMAP_SRC_IMPORT_2_1);
8872 }
8873 xmlFreeParserCtxt(parserCtxt);
8874
8875 root = xmlDocGetRootElement(*doc);
8876 if (root == NULL) {
8877 xmlSchemaPCustomErr(ctxt,
8878 XML_SCHEMAP_SRC_IMPORT_2_1,
8879 NULL, NULL, node,
8880 "The XML document '%s' to be imported has no document "
8881 "element", location);
8882 xmlFreeDoc(*doc);
8883 *doc = NULL;
8884 return (XML_SCHEMAP_SRC_IMPORT_2_1);
8885 }
8886
8887 xmlSchemaCleanupDoc(ctxt, root);
8888
8889 if (!IS_SCHEMA(root, "schema")) {
8890 xmlSchemaPCustomErr(ctxt,
8891 XML_SCHEMAP_SRC_IMPORT_2_1,
8892 NULL, NULL, node,
8893 "The XML document '%s' to be imported is not a XML schema document",
8894 location);
8895 xmlFreeDoc(*doc);
8896 *doc = NULL;
8897 return (XML_SCHEMAP_SRC_IMPORT_2_1);
8898 }
8899 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
8900 /*
8901 * Schema Representation Constraint: Import Constraints and Semantics
8902 */
8903 if (nsName == NULL) {
8904 if (*targetNamespace != NULL) {
8905 xmlSchemaPCustomErr(ctxt,
8906 XML_SCHEMAP_SRC_IMPORT_3_2,
8907 NULL, NULL, node,
8908 "The XML schema to be imported is not expected "
8909 "to have a target namespace; this differs from "
8910 "its target namespace of '%s'", *targetNamespace);
8911 xmlFreeDoc(*doc);
8912 *doc = NULL;
8913 return (XML_SCHEMAP_SRC_IMPORT_3_2);
8914 }
8915 } else {
8916 if (*targetNamespace == NULL) {
8917 xmlSchemaPCustomErr(ctxt,
8918 XML_SCHEMAP_SRC_IMPORT_3_1,
8919 NULL, NULL, node,
8920 "The XML schema to be imported is expected to have a target "
8921 "namespace of '%s'", nsName);
8922 xmlFreeDoc(*doc);
8923 *doc = NULL;
8924 return (XML_SCHEMAP_SRC_IMPORT_3_1);
8925 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
8926 xmlSchemaPCustomErrExt(ctxt,
8927 XML_SCHEMAP_SRC_IMPORT_3_1,
8928 NULL, NULL, node,
8929 "The XML schema to be imported is expected to have a "
8930 "target namespace of '%s'; this differs from "
8931 "its target namespace of '%s'",
8932 nsName, *targetNamespace, NULL);
8933 xmlFreeDoc(*doc);
8934 *doc = NULL;
8935 return (XML_SCHEMAP_SRC_IMPORT_3_1);
8936 }
8937 }
8938
8939 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
8940 if (import == NULL) {
8941 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
8942 NULL, NULL, NULL,
8943 "Internal error: xmlSchemaAcquireSchemaDoc, "
8944 "failed to build import table", NULL);
8945 xmlFreeDoc(*doc);
8946 *doc = NULL;
8947 return (-1);
8948 }
8949 import->schemaLocation = location;
8950 import->doc = *doc;
8951 return (0);
8952}
William M. Brack2f2a6632004-08-20 23:09:47 +00008953
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008954static void
8955xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
8956 xmlSchemaPtr schema,
8957 const xmlChar *targetNamespace,
8958 xmlNodePtr node)
8959{
8960 const xmlChar *oldURL, **oldLocImps, *oldTNS;
8961 int oldFlags, oldNumLocImps, oldSizeLocImps;
8962
8963 /*
8964 * Save and reset the context & schema.
8965 */
8966 oldURL = pctxt->URL;
8967 /* TODO: Is using the doc->URL here correct? */
8968 pctxt->URL = node->doc->URL;
8969 oldLocImps = pctxt->localImports;
8970 pctxt->localImports = NULL;
8971 oldNumLocImps = pctxt->nbLocalImports;
8972 pctxt->nbLocalImports = 0;
8973 oldSizeLocImps = pctxt->sizeLocalImports;
8974 pctxt->sizeLocalImports = 0;
8975 oldFlags = schema->flags;
8976 xmlSchemaClearSchemaDefaults(schema);
8977 oldTNS = schema->targetNamespace;
8978 schema->targetNamespace = targetNamespace;
8979 /*
8980 * Parse the schema.
8981 */
8982 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
8983 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
8984 /*
8985 * Restore the context & schema.
8986 */
8987 schema->flags = oldFlags;
8988 schema->targetNamespace = oldTNS;
8989 if (pctxt->localImports != NULL)
8990 xmlFree((xmlChar *) pctxt->localImports);
8991 pctxt->localImports = oldLocImps;
8992 pctxt->nbLocalImports = oldNumLocImps;
8993 pctxt->sizeLocalImports = oldSizeLocImps;
8994 pctxt->URL = oldURL;
8995}
8996
William M. Brack2f2a6632004-08-20 23:09:47 +00008997/**
8998 * xmlSchemaParseImport:
8999 * @ctxt: a schema validation context
9000 * @schema: the schema being built
9001 * @node: a subtree containing XML Schema informations
9002 *
9003 * parse a XML schema Import definition
9004 * *WARNING* this interface is highly subject to change
9005 *
9006 * Returns 0 in case of success, a positive error code if
9007 * not valid and -1 in case of an internal error.
9008 */
9009static int
9010xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9011 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009012{
9013 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009014 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009015 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009016 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009017 xmlAttrPtr attr;
9018 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009019 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009020
9021 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9022 return (-1);
9023
9024 /*
9025 * Check for illegal attributes.
9026 */
9027 attr = node->properties;
9028 while (attr != NULL) {
9029 if (attr->ns == NULL) {
9030 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9031 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9032 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
9033 xmlSchemaPIllegalAttrErr(ctxt,
9034 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9035 NULL, NULL, attr);
9036 }
9037 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9038 xmlSchemaPIllegalAttrErr(ctxt,
9039 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9040 NULL, NULL, attr);
9041 }
9042 attr = attr->next;
9043 }
9044 /*
9045 * Extract and validate attributes.
9046 */
9047 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9048 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009049 &namespaceName) != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009050 xmlSchemaPSimpleTypeErr(ctxt,
9051 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9052 NULL, NULL, node,
9053 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009054 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009055 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9056 }
9057
9058 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9059 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
9060 &schemaLocation) != 0) {
9061 xmlSchemaPSimpleTypeErr(ctxt,
9062 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9063 NULL, NULL, node,
9064 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009065 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009066 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
9067 }
9068 /*
9069 * And now for the children...
9070 */
9071 child = node->children;
9072 if (IS_SCHEMA(child, "annotation")) {
9073 /*
9074 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009075 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009076 */
9077 child = child->next;
9078 }
9079 if (child != NULL) {
9080 xmlSchemaPContentErr(ctxt,
9081 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9082 NULL, NULL, node, child, NULL,
9083 "(annotation?)");
9084 }
9085 /*
9086 * Apply additional constraints.
9087 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009088 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009089 /*
9090 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9091 * must not match the ·actual value· of the enclosing <schema>'s
9092 * targetNamespace [attribute].
9093 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009094 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009095 xmlSchemaPCustomErr(ctxt,
9096 XML_SCHEMAP_SRC_IMPORT_1_1,
9097 NULL, NULL, node,
9098 "The value of the attribute 'namespace' must not match "
9099 "the target namespace '%s' of the importing schema",
9100 schema->targetNamespace);
9101 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9102 }
9103 } else {
9104 /*
9105 * 1.2 If the namespace [attribute] is not present, then the enclosing
9106 * <schema> must have a targetNamespace [attribute].
9107 */
9108 if (schema->targetNamespace == NULL) {
9109 xmlSchemaPCustomErr(ctxt,
9110 XML_SCHEMAP_SRC_IMPORT_1_2,
9111 NULL, NULL, node,
9112 "The attribute 'namespace' must be existent if "
9113 "the importing schema has no target namespace",
9114 NULL);
9115 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9116 }
9117 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009118 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009119 * Add the namespace to the list of locally imported namespace.
9120 */
9121 if (ctxt->localImports == NULL) {
9122 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
9123 sizeof(const xmlChar*));
9124 ctxt->sizeLocalImports = 10;
9125 ctxt->nbLocalImports = 0;
9126 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9127 ctxt->sizeLocalImports *= 2;
9128 ctxt->localImports = (const xmlChar **) xmlRealloc(
9129 (xmlChar **) ctxt->localImports,
9130 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9131 }
9132 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9133 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009134 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009135 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009136 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009137 schemaLocation, &doc, &targetNamespace, 0);
9138 if (ret != 0) {
9139 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009140 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009141 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009142 } else if (doc != NULL) {
9143 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9144 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009145 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009146
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009147 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009148}
9149
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009150/**
9151 * xmlSchemaParseInclude:
9152 * @ctxt: a schema validation context
9153 * @schema: the schema being built
9154 * @node: a subtree containing XML Schema informations
9155 *
9156 * parse a XML schema Include definition
9157 *
William M. Bracke7091952004-05-11 15:09:58 +00009158 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009159 * 1 in case of success.
9160 */
9161static int
9162xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9163 xmlNodePtr node)
9164{
9165 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009166 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009167 xmlDocPtr doc = NULL;
9168 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009169 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009170 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009171 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009172 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009173
9174
9175 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9176 return (-1);
9177
9178 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009179 * Check for illegal attributes.
9180 */
9181 attr = node->properties;
9182 while (attr != NULL) {
9183 if (attr->ns == NULL) {
9184 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9185 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
9186 xmlSchemaPIllegalAttrErr(ctxt,
9187 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9188 NULL, NULL, attr);
9189 }
9190 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9191 xmlSchemaPIllegalAttrErr(ctxt,
9192 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9193 NULL, NULL, attr);
9194 }
9195 attr = attr->next;
9196 }
9197 /*
9198 * Extract and validate attributes.
9199 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009200 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009201 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009202 * Preliminary step, extract the URI-Reference for the include and
9203 * make an URI from the base.
9204 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009205 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9206 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009207 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009208 xmlChar *uri = NULL;
9209
9210 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9211 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009212 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009213 base = xmlNodeGetBase(node->doc, node);
9214 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009215 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009216 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009217 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009218 xmlFree(base);
9219 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009220 if (uri == NULL) {
9221 xmlSchemaPErr(ctxt,
9222 node,
9223 XML_SCHEMAP_INTERNAL,
9224 "Internal error: xmlSchemaParseInclude, "
9225 "could not build an URI from the schemaLocation.\n",
9226 NULL, NULL);
9227 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009228 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009229 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9230 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009231 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009232 xmlSchemaPMissingAttrErr(ctxt,
9233 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9234 NULL, NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009235 goto exit_invalid;
9236 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009237 /*
9238 * And now for the children...
9239 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009240 child = node->children;
9241 while (IS_SCHEMA(child, "annotation")) {
9242 /*
9243 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009244 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009245 */
9246 child = child->next;
9247 }
9248 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009249 xmlSchemaPContentErr(ctxt,
9250 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9251 NULL, NULL, node, child, NULL,
9252 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009253 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009254 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009255 * Report self-inclusion.
9256 */
9257 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9258 xmlSchemaPCustomErr(ctxt,
9259 XML_SCHEMAP_SRC_INCLUDE,
9260 NULL, NULL, node,
9261 "The schema document '%s' cannot include itself.",
9262 schemaLocation);
9263 return (XML_SCHEMAP_SRC_INCLUDE);
9264 }
9265 /*
9266 * Check if this one was already processed to avoid incorrect
9267 * duplicate component errors and infinite circular inclusion.
9268 */
9269 include = schema->includes;
9270 while (include != NULL) {
9271 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9272 targetNamespace = include->origTargetNamespace;
9273 if (targetNamespace == NULL) {
9274 /*
9275 * Chameleon include: skip only if it was build for
9276 * the targetNamespace of the including schema.
9277 */
9278 if (xmlStrEqual(schema->targetNamespace,
9279 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009280 goto check_targetNamespace;
9281 }
9282 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009283 goto check_targetNamespace;
9284 }
9285 }
9286 include = include->next;
9287 }
9288 /*
9289 * First step is to parse the input document into an DOM/Infoset
9290 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009291 */
9292 parserCtxt = xmlNewParserCtxt();
9293 if (parserCtxt == NULL) {
9294 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9295 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009296 goto exit_failure;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009297 }
9298
9299 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9300 xmlDictFree(parserCtxt->dict);
9301 parserCtxt->dict = ctxt->dict;
9302 xmlDictReference(parserCtxt->dict);
9303 }
9304
9305 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
9306 NULL, SCHEMAS_PARSE_OPTIONS);
9307 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009308 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009309 /*
9310 * TODO: It is not an error for the ·actual value· of the
9311 * schemaLocation [attribute] to fail to resolve it all, in which
9312 * case no corresponding inclusion is performed.
9313 * So do we need a warning report here?
9314 */
9315 xmlSchemaPCustomErr(ctxt,
9316 XML_SCHEMAP_FAILED_LOAD,
9317 NULL, NULL, node,
9318 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009319 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009320 }
9321
9322 /*
9323 * Then extract the root of the schema
9324 */
9325 root = xmlDocGetRootElement(doc);
9326 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009327 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009328 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009329 NULL, NULL, node,
9330 "The included document '%s' has no document "
9331 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009332 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009333 }
9334
9335 /*
9336 * Remove all the blank text nodes
9337 */
9338 xmlSchemaCleanupDoc(ctxt, root);
9339
9340 /*
9341 * Check the schemas top level element
9342 */
9343 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009344 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009345 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009346 NULL, NULL, node,
9347 "The document '%s' to be included is not a schema document",
9348 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009349 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009350 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009351
William M. Brack2f2a6632004-08-20 23:09:47 +00009352 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009353 /*
9354 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9355 * value· is identical to the ·actual value· of the targetNamespace
9356 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9357 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009358check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009359 if (targetNamespace != NULL) {
9360 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009361 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009362 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009363 NULL, NULL, node,
9364 "The target namespace of the included schema "
9365 "'%s' has to be absent, since the including schema "
9366 "has no target namespace",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009367 schemaLocation);
9368 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009369 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9370 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009371 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009372 NULL, NULL, node,
9373 "The target namespace '%s' of the included schema '%s' "
9374 "differs from '%s' of the including schema",
9375 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009376 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009377 }
9378 } else if (schema->targetNamespace != NULL) {
9379 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
9380 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
9381 } else
9382 wasConvertingNs = 1;
9383 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009384
9385 if (include != NULL)
9386 goto exit;
9387
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009388 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009389 * URGENT TODO: If the schema is a chameleon-include then copy the
9390 * components into the including schema and modify the targetNamespace
9391 * of those components, do nothing otherwise.
9392 * NOTE: This is currently worked-around by compiling the chameleon
9393 * for every destinct including targetNamespace; thus not performant at
9394 * the moment.
9395 * TODO: Check when the namespace in wildcards for chameleons needs
9396 * to be converted: before we built wildcard intersections or after.
9397 */
9398 /*
9399 * Register the include.
9400 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009401 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9402 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009403 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9404 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009405 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009406 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009407 include->next = schema->includes;
9408 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009409 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009410 * TODO: Use the resolved URI for the this location, since it might
9411 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009412 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009413 include->schemaLocation = schemaLocation;
9414 include->doc = doc;
9415 /*
9416 * In case of chameleons, the original target namespace will differ
9417 * from the resulting namespace.
9418 */
9419 include->origTargetNamespace = targetNamespace;
9420 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009421#ifdef DEBUG_INCLUDES
9422 if (targetNamespace != schema->targetNamespace)
9423 xmlGenericError(xmlGenericErrorContext,
9424 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9425 " into TNS '%s'\n", schemaLocation,
9426 targetNamespace, schema->targetNamespace);
9427 else
9428 xmlGenericError(xmlGenericErrorContext,
9429 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9430 targetNamespace);
9431#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009432 /*
9433 * Compile the included schema.
9434 */
9435 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9436
9437exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009438 /*
9439 * Remove the converting flag.
9440 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009441 if ((wasConvertingNs == 0) &&
9442 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009443 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009444 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009445
9446exit_invalid:
9447 if (doc != NULL) {
9448 if (include != NULL)
9449 include->doc = NULL;
9450 xmlFreeDoc(doc);
9451 }
9452 return (ctxt->err);
9453
9454exit_failure:
9455 if (doc != NULL) {
9456 if (include != NULL)
9457 include->doc = NULL;
9458 xmlFreeDoc(doc);
9459 }
9460 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009461}
9462
9463/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009464 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009465 * @ctxt: a schema validation context
9466 * @schema: the schema being built
9467 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009468 * @type: the "compositor" type
9469 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009470 *
9471 * parse a XML schema Sequence definition
9472 * *WARNING* this interface is highly subject to change
9473 *
William M. Bracke7091952004-05-11 15:09:58 +00009474 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009475 * 1 in case of success.
9476 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009477static xmlSchemaTreeItemPtr
9478xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9479 xmlNodePtr node, xmlSchemaTypeType type,
9480 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009481{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009482 xmlSchemaModelGroupPtr item;
9483 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009484 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009485 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009486 const xmlChar *oldcontainer, *container;
9487 int min, max;
Daniel Veillard4255d502002-04-16 15:50:10 +00009488
9489 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009490 return (NULL);
9491 /*
9492 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009493 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009494 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9495 if (item == NULL)
9496 return (NULL);
9497
9498 if (withParticle) {
9499 if (type == XML_SCHEMA_TYPE_ALL) {
9500 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
9501 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
9502 } else {
9503 /* choice + sequence */
9504 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
9505 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9506 "(nonNegativeInteger | unbounded)");
9507 }
9508 /*
9509 * Create a particle
9510 */
9511 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9512 if (particle == NULL)
9513 return (NULL);
9514 particle->children = (xmlSchemaTreeItemPtr) item;
9515 /*
9516 * Check for illegal attributes.
9517 */
9518 attr = node->properties;
9519 while (attr != NULL) {
9520 if (attr->ns == NULL) {
9521 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9522 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9523 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
9524 xmlSchemaPIllegalAttrErr(ctxt,
9525 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9526 NULL, NULL, attr);
9527 }
9528 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009529 xmlSchemaPIllegalAttrErr(ctxt,
9530 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009531 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009532 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009533 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009534 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009535 } else {
9536 /*
9537 * Check for illegal attributes.
9538 */
9539 attr = node->properties;
9540 while (attr != NULL) {
9541 if (attr->ns == NULL) {
9542 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9543 xmlSchemaPIllegalAttrErr(ctxt,
9544 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9545 NULL, NULL, attr);
9546 }
9547 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9548 xmlSchemaPIllegalAttrErr(ctxt,
9549 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9550 NULL, NULL, attr);
9551 }
9552 attr = attr->next;
9553 }
9554
William M. Brack2f2a6632004-08-20 23:09:47 +00009555 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009556
William M. Brack2f2a6632004-08-20 23:09:47 +00009557 /*
9558 * Extract and validate attributes.
9559 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009560 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009561 /*
9562 * And now for the children...
9563 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009564 child = node->children;
9565 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009566 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009567 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009568 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009569 oldcontainer = ctxt->container;
9570 ctxt->container = container;
9571 if (type == XML_SCHEMA_TYPE_ALL) {
9572 xmlSchemaParticlePtr part, last = NULL;
9573
9574 while (IS_SCHEMA(child, "element")) {
9575 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9576 schema, child, 0);
9577 if (part != NULL) {
9578 if (part->minOccurs > 1)
9579 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
9580 NULL, NULL, child,
9581 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9582 if (part->maxOccurs > 1)
9583 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
9584 NULL, NULL, child,
9585 "Invalid value for maxOccurs (must be 0 or 1)",
9586 NULL);
9587 if (last == NULL)
9588 item->children = (xmlSchemaTreeItemPtr) part;
9589 else
9590 last->next = (xmlSchemaTreeItemPtr) part;
9591 last = part;
9592 }
9593 child = child->next;
9594 }
9595 if (child != NULL) {
9596 xmlSchemaPContentErr(ctxt,
9597 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9598 NULL, NULL, node, child, NULL,
9599 "(annotation?, (annotation?, element*)");
9600 }
9601 } else {
9602 /* choice + sequence */
9603 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9604
9605 while ((IS_SCHEMA(child, "element")) ||
9606 (IS_SCHEMA(child, "group")) ||
9607 (IS_SCHEMA(child, "any")) ||
9608 (IS_SCHEMA(child, "choice")) ||
9609 (IS_SCHEMA(child, "sequence"))) {
9610
9611 if (IS_SCHEMA(child, "element")) {
9612 part = (xmlSchemaTreeItemPtr)
9613 xmlSchemaParseElement(ctxt, schema, child, 0);
9614 } else if (IS_SCHEMA(child, "group")) {
9615 part =
9616 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9617 } else if (IS_SCHEMA(child, "any")) {
9618 part = (xmlSchemaTreeItemPtr)
9619 xmlSchemaParseAny(ctxt, schema, child);
9620 } else if (IS_SCHEMA(child, "choice")) {
9621 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9622 XML_SCHEMA_TYPE_CHOICE, 1);
9623 } else if (IS_SCHEMA(child, "sequence")) {
9624 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9625 XML_SCHEMA_TYPE_SEQUENCE, 1);
9626 }
9627 if (part != NULL) {
9628 if (last == NULL)
9629 item->children = part;
9630 else
9631 last->next = part;
9632 last = part;
9633 }
9634 child = child->next;
9635 }
9636 if (child != NULL) {
9637 xmlSchemaPContentErr(ctxt,
9638 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9639 NULL, NULL, node, child, NULL,
9640 "(annotation?, (element | group | choice | sequence | any)*)");
9641 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009642 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009643 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009644 if (withParticle)
9645 return ((xmlSchemaTreeItemPtr) particle);
9646 else
9647 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009648}
9649
9650/**
9651 * xmlSchemaParseRestriction:
9652 * @ctxt: a schema validation context
9653 * @schema: the schema being built
9654 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009655 *
9656 * parse a XML schema Restriction definition
9657 * *WARNING* this interface is highly subject to change
9658 *
9659 * Returns the type definition or NULL in case of error
9660 */
9661static xmlSchemaTypePtr
9662xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009663 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009664{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009665 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009666 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009667 char buf[30];
9668 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009669 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009670
9671 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9672 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009673 /* Not a component, don't create it. */
9674 type = ctxt->ctxtType;
9675 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
9676
9677 /*
9678 * TODO: Is the container needed at all? the anonymous
9679 * items inside should generate unique names already.
9680 */
9681 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
9682 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009683 /*
9684 * Check for illegal attributes.
9685 */
9686 attr = node->properties;
9687 while (attr != NULL) {
9688 if (attr->ns == NULL) {
9689 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9690 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
9691 xmlSchemaPIllegalAttrErr(ctxt,
9692 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009693 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009694 }
9695 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9696 xmlSchemaPIllegalAttrErr(ctxt,
9697 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009698 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009699 }
9700 attr = attr->next;
9701 }
9702 /*
9703 * Extract and validate attributes.
9704 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009705 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009706 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009707 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009708 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009709 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009710 NULL, NULL, node, "base",
9711 &(type->baseNs), NULL,
9712 &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009713 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009714 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009715 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009716 XML_SCHEMAP_S4S_ATTR_MISSING,
William M. Brack2f2a6632004-08-20 23:09:47 +00009717 NULL, type, node, "base", NULL);
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009718 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009719 /*
9720 * And now for the children...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009721 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009722 child = node->children;
9723 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009724 /*
9725 * Add the annotation to the simple type ancestor.
9726 */
9727 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9728 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009729 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009730 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009731 oldcontainer = ctxt->container;
9732 ctxt->container = container;
9733 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9734 /*
9735 * Corresponds to <simpleType><restriction><simpleType>.
9736 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009737 if (IS_SCHEMA(child, "simpleType")) {
9738 if (type->base != NULL) {
9739 /*
9740 * src-restriction-base-or-simpleType
9741 * Either the base [attribute] or the simpleType [child] of the
9742 * <restriction> element must be present, but not both.
9743 */
9744 xmlSchemaPContentErr(ctxt,
9745 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009746 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009747 "The attribute 'base' and the <simpleType> child are "
9748 "mutually exclusive", NULL);
9749 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009750 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009751 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009752 }
9753 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009754 } else if (type->base == NULL) {
9755 xmlSchemaPContentErr(ctxt,
9756 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9757 NULL, NULL, node, child,
9758 "Either the attribute 'base' or a <simpleType> child "
9759 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009760 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009761 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9762 /*
9763 * Corresponds to <complexType><complexContent><restriction>...
9764 * followed by:
9765 *
9766 * Model groups <all>, <choice> and <sequence>.
9767 */
9768 if (IS_SCHEMA(child, "all")) {
9769 type->subtypes = (xmlSchemaTypePtr)
9770 xmlSchemaParseModelGroup(ctxt, schema, child,
9771 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009772 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009773 } else if (IS_SCHEMA(child, "choice")) {
9774 type->subtypes = (xmlSchemaTypePtr)
9775 xmlSchemaParseModelGroup(ctxt,
9776 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9777 child = child->next;
9778 } else if (IS_SCHEMA(child, "sequence")) {
9779 type->subtypes = (xmlSchemaTypePtr)
9780 xmlSchemaParseModelGroup(ctxt, schema, child,
9781 XML_SCHEMA_TYPE_SEQUENCE, 1);
9782 child = child->next;
9783 /*
9784 * Model group reference <group>.
9785 */
9786 } else if (IS_SCHEMA(child, "group")) {
9787 type->subtypes = (xmlSchemaTypePtr)
9788 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9789 child = child->next;
9790 }
9791 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
9792 xmlSchemaTypePtr contType, baseType = NULL;
9793 /*
9794 * Corresponds to <complexType><simpleContent><restriction>...
9795 *
9796 * SPEC (content type):
9797 * "1 If the type definition ·resolved· to by the ·actual value· of
9798 * the base [attribute] is a complex type definition whose own
9799 * {content type} is a simple type definition and the <restriction>
9800 * alternative is chosen, then starting from either" ...
9801 *
9802 * "1.1 the simple type definition corresponding to the <simpleType>
9803 * among the [children] of <restriction> if there is one;"
9804 */
9805 if (IS_SCHEMA(child, "simpleType")) {
9806
9807 baseType = (xmlSchemaTypePtr)
9808 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9809 if (baseType == NULL)
9810 return (NULL);
9811 child = child->next;
9812 }
9813 /*
9814 * SPEC
9815 * "... a simple type definition which restricts the simple type
9816 * definition identified in clause 1.1 or clause 1.2 with a set
9817 * of facet components"
9818 *
9819 * Create the anonymous simple type, which will be the content type
9820 * of the complex type.
9821 * Note that we will use the same node as for the <restriction> to
9822 * have it somehow anchored in the schema doc.
9823 */
9824 snprintf(buf, 29, "#scST%d", ctxt->counter++ + 1);
9825 contType = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf,
9826 container, node);
9827 if (contType == NULL)
9828 return (NULL);
9829 contType->node = node;
9830 contType->type = XML_SCHEMA_TYPE_SIMPLE;
9831 contType->baseType = baseType;
9832 type->contentTypeDef = contType;
William M. Brack2f2a6632004-08-20 23:09:47 +00009833 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009834
9835 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
9836 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
9837 xmlSchemaFacetPtr facet, lastfacet = NULL;
9838 xmlSchemaTypePtr facetHolder;
9839
9840 if (parentType == XML_SCHEMA_TYPE_SIMPLE)
9841 facetHolder = type;
9842 else
9843 facetHolder = type->contentTypeDef;
9844 /*
9845 * Corresponds to <complexType><simpleContent><restriction>...
9846 * <simpleType><restriction>...
9847 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009848
Daniel Veillard01fa6152004-06-29 17:04:39 +00009849 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009850 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009851 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009852 /*
9853 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9854 * Simple Type Definition Schema Representation Constraint:
9855 * *Single Facet Value*
9856 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009857 while ((IS_SCHEMA(child, "minInclusive")) ||
9858 (IS_SCHEMA(child, "minExclusive")) ||
9859 (IS_SCHEMA(child, "maxInclusive")) ||
9860 (IS_SCHEMA(child, "maxExclusive")) ||
9861 (IS_SCHEMA(child, "totalDigits")) ||
9862 (IS_SCHEMA(child, "fractionDigits")) ||
9863 (IS_SCHEMA(child, "pattern")) ||
9864 (IS_SCHEMA(child, "enumeration")) ||
9865 (IS_SCHEMA(child, "whiteSpace")) ||
9866 (IS_SCHEMA(child, "length")) ||
9867 (IS_SCHEMA(child, "maxLength")) ||
9868 (IS_SCHEMA(child, "minLength"))) {
9869 facet = xmlSchemaParseFacet(ctxt, schema, child);
9870 if (facet != NULL) {
9871 if (lastfacet == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009872 facetHolder->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009873 else
9874 lastfacet->next = facet;
9875 lastfacet = facet;
9876 lastfacet->next = NULL;
9877 }
9878 child = child->next;
9879 }
9880 /*
9881 * Create links for derivation and validation.
9882 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009883 if (facetHolder->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009884 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
9885
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009886 facet = facetHolder->facets;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009887 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009888 facetLink = (xmlSchemaFacetLinkPtr)
9889 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +00009890 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009891 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009892 xmlFree(facetLink);
9893 return (NULL);
9894 }
9895 facetLink->facet = facet;
9896 facetLink->next = NULL;
9897 if (lastFacetLink == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009898 facetHolder->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009899 else
9900 lastFacetLink->next = facetLink;
9901 lastFacetLink = facetLink;
9902 facet = facet->next;
9903 } while (facet != NULL);
9904 }
9905 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009906 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
9907 /*
9908 * Attribute uses/declarations.
9909 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009910 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009911 /*
9912 * Attribute wildcard.
9913 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009914 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009915 type->attributeWildcard =
9916 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009917 child = child->next;
9918 }
9919 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009920 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009921 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009922 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009923 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9924 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009925 "annotation?, (group | all | choice | sequence)?, "
9926 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009927 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009928 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009929 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9930 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009931 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
9932 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
9933 "length | minLength | maxLength | enumeration | whiteSpace | "
9934 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
9935 } else {
9936 /* Simple type */
9937 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009938 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9939 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009940 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
9941 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
9942 "length | minLength | maxLength | enumeration | whiteSpace | "
9943 "pattern)*))");
9944 }
9945 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009946 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009947 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009948}
9949
9950/**
9951 * xmlSchemaParseExtension:
9952 * @ctxt: a schema validation context
9953 * @schema: the schema being built
9954 * @node: a subtree containing XML Schema informations
9955 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009956 * Parses an <extension>, which is found inside a
9957 * <simpleContent> or <complexContent>.
9958 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +00009959 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009960 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +00009961 */
9962static xmlSchemaTypePtr
9963xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009964 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009965{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009966 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009967 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009968 char buf[30];
9969 const xmlChar *oldcontainer, *container;
9970 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009971
9972 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9973 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009974 /* Not a component, don't create it. */
9975 type = ctxt->ctxtType;
9976 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00009977
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009978 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
9979 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
9980 /*
9981 * Check for illegal attributes.
9982 */
9983 attr = node->properties;
9984 while (attr != NULL) {
9985 if (attr->ns == NULL) {
9986 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9987 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
9988 xmlSchemaPIllegalAttrErr(ctxt,
9989 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9990 NULL, NULL, attr);
9991 }
9992 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9993 xmlSchemaPIllegalAttrErr(ctxt,
9994 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9995 NULL, NULL, attr);
9996 }
9997 attr = attr->next;
9998 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009999
10000 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010001
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010002 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010003 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010004 */
10005 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010006 NULL, NULL, node, "base", &(type->baseNs), NULL,
10007 &(type->base)) == 0) && (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010008 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010009 XML_SCHEMAP_S4S_ATTR_MISSING,
10010 NULL, NULL, node, "base", NULL);
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010011 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010012 /*
10013 * And now for the children...
10014 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010015 child = node->children;
10016 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010017 /*
10018 * Add the annotation to the type ancestor.
10019 */
10020 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10021 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010022 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010023 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010024 oldcontainer = ctxt->container;
10025 ctxt->container = container;
10026 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10027 /*
10028 * Corresponds to <complexType><complexContent><extension>... and:
10029 *
10030 * Model groups <all>, <choice>, <sequence> and <group>.
10031 */
10032 if (IS_SCHEMA(child, "all")) {
10033 type->subtypes = (xmlSchemaTypePtr)
10034 xmlSchemaParseModelGroup(ctxt, schema,
10035 child, XML_SCHEMA_TYPE_ALL, 1);
10036 child = child->next;
10037 } else if (IS_SCHEMA(child, "choice")) {
10038 type->subtypes = (xmlSchemaTypePtr)
10039 xmlSchemaParseModelGroup(ctxt, schema,
10040 child, XML_SCHEMA_TYPE_CHOICE, 1);
10041 child = child->next;
10042 } else if (IS_SCHEMA(child, "sequence")) {
10043 type->subtypes = (xmlSchemaTypePtr)
10044 xmlSchemaParseModelGroup(ctxt, schema,
10045 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10046 child = child->next;
10047 } else if (IS_SCHEMA(child, "group")) {
10048 type->subtypes = (xmlSchemaTypePtr)
10049 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10050 child = child->next;
10051 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010052 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010053 if (child != NULL) {
10054 /*
10055 * Attribute uses/declarations.
10056 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010057 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010058 /*
10059 * Attribute wildcard.
10060 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010061 if (IS_SCHEMA(child, "anyAttribute")) {
10062 ctxt->ctxtType->attributeWildcard =
10063 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10064 child = child->next;
10065 }
10066 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010067 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010068 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10069 /* Complex content extension. */
10070 xmlSchemaPContentErr(ctxt,
10071 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10072 NULL, NULL, node, child, NULL,
10073 "(annotation?, ((group | all | choice | sequence)?, "
10074 "((attribute | attributeGroup)*, anyAttribute?)))");
10075 } else {
10076 /* Simple content extension. */
10077 xmlSchemaPContentErr(ctxt,
10078 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10079 NULL, NULL, node, child, NULL,
10080 "(annotation?, ((attribute | attributeGroup)*, "
10081 "anyAttribute?))");
10082 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010083 }
10084 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010085 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010086}
10087
10088/**
10089 * xmlSchemaParseSimpleContent:
10090 * @ctxt: a schema validation context
10091 * @schema: the schema being built
10092 * @node: a subtree containing XML Schema informations
10093 *
10094 * parse a XML schema SimpleContent definition
10095 * *WARNING* this interface is highly subject to change
10096 *
10097 * Returns the type definition or NULL in case of error
10098 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010099static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010100xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10101 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010102{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010103 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010104 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010105 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010106
10107 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010108 return (-1);
10109 /* Not a component, don't create it. */
10110 type = ctxt->ctxtType;
10111 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10112 /*
10113 * Check for illegal attributes.
10114 */
10115 attr = node->properties;
10116 while (attr != NULL) {
10117 if (attr->ns == NULL) {
10118 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
10119 xmlSchemaPIllegalAttrErr(ctxt,
10120 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10121 NULL, NULL, attr);
10122 }
10123 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10124 xmlSchemaPIllegalAttrErr(ctxt,
10125 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10126 NULL, NULL, attr);
10127 }
10128 attr = attr->next;
10129 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010130
10131 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010132
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010133 /*
10134 * And now for the children...
10135 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010136 child = node->children;
10137 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010138 /*
10139 * Add the annotation to the complex type ancestor.
10140 */
10141 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10142 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010143 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010144 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010145 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010146 xmlSchemaParseRestriction(ctxt, schema, child,
10147 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010148 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010149 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010150 xmlSchemaParseExtension(ctxt, schema, child,
10151 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010152 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010153 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010154 if (child != NULL) {
10155 xmlSchemaPContentErr(ctxt,
10156 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10157 NULL, NULL, node, child, NULL,
10158 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010159 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010160 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010161}
10162
10163/**
10164 * xmlSchemaParseComplexContent:
10165 * @ctxt: a schema validation context
10166 * @schema: the schema being built
10167 * @node: a subtree containing XML Schema informations
10168 *
10169 * parse a XML schema ComplexContent definition
10170 * *WARNING* this interface is highly subject to change
10171 *
10172 * Returns the type definition or NULL in case of error
10173 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010174static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010175xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10176 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010177{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010178 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010179 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010180 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010181
10182 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010183 return (-1);
10184 /* Not a component, don't create it. */
10185 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010186 /*
10187 * Check for illegal attributes.
10188 */
10189 attr = node->properties;
10190 while (attr != NULL) {
10191 if (attr->ns == NULL) {
10192 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10193 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
10194 {
10195 xmlSchemaPIllegalAttrErr(ctxt,
10196 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10197 NULL, NULL, attr);
10198 }
10199 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10200 xmlSchemaPIllegalAttrErr(ctxt,
10201 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10202 NULL, NULL, attr);
10203 }
10204 attr = attr->next;
10205 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010206
10207 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10208
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010209 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010210 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010211 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010212 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10213 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10214 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010215 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010216 child = node->children;
10217 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010218 /*
10219 * Add the annotation to the complex type ancestor.
10220 */
10221 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10222 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010223 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010224 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010225 if (IS_SCHEMA(child, "restriction")) {
10226 xmlSchemaParseRestriction(ctxt, schema, child,
10227 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010228 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010229 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010230 xmlSchemaParseExtension(ctxt, schema, child,
10231 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010232 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010233 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010234 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010235 xmlSchemaPContentErr(ctxt,
10236 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10237 NULL, NULL, node, child,
10238 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010239 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010240 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010241}
10242
10243/**
10244 * xmlSchemaParseComplexType:
10245 * @ctxt: a schema validation context
10246 * @schema: the schema being built
10247 * @node: a subtree containing XML Schema informations
10248 *
10249 * parse a XML schema Complex Type definition
10250 * *WARNING* this interface is highly subject to change
10251 *
10252 * Returns the type definition or NULL in case of error
10253 */
10254static xmlSchemaTypePtr
10255xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010256 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010257{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010258 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010259 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010260 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010261 xmlAttrPtr attr;
10262 const xmlChar *attrValue;
10263 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010264 char buf[40];
10265
Daniel Veillard4255d502002-04-16 15:50:10 +000010266
10267 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10268 return (NULL);
10269
Daniel Veillard01fa6152004-06-29 17:04:39 +000010270 ctxtType = ctxt->ctxtType;
10271
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010272 if (topLevel) {
10273 attr = xmlSchemaGetPropNode(node, "name");
10274 if (attr == NULL) {
10275 xmlSchemaPMissingAttrErr(ctxt,
10276 XML_SCHEMAP_S4S_ATTR_MISSING,
10277 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
10278 "name", NULL);
10279 return (NULL);
10280 } else if (xmlSchemaPValAttrNode(ctxt,
10281 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
10282 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10283 return (NULL);
10284 }
10285 }
10286
10287 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010288 /*
10289 * Parse as local complex type definition.
10290 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010291 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010292 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10293 if (type == NULL)
10294 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010295 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010296 type->node = node;
10297 type->type = XML_SCHEMA_TYPE_COMPLEX;
10298 /*
10299 * TODO: We need the target namespace.
10300 */
10301 } else {
10302 /*
10303 * Parse as global complex type definition.
10304 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010305 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010306 if (type == NULL)
10307 return (NULL);
10308 type->node = node;
10309 type->type = XML_SCHEMA_TYPE_COMPLEX;
10310 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
10311 /*
10312 * Set defaults.
10313 */
10314 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010315 }
10316 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010317 /*
10318 * Handle attributes.
10319 */
10320 attr = node->properties;
10321 while (attr != NULL) {
10322 if (attr->ns == NULL) {
10323 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10324 /*
10325 * Attribute "id".
10326 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010327 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10328 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010329 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10330 /*
10331 * Attribute "mixed".
10332 */
10333 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10334 (xmlNodePtr) attr))
10335 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10336 } else if (topLevel) {
10337 /*
10338 * Attributes of global complex type definitions.
10339 */
10340 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10341 /* Pass. */
10342 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10343 /*
10344 * Attribute "abstract".
10345 */
10346 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10347 (xmlNodePtr) attr))
10348 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10349 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10350 /*
10351 * Attribute "final".
10352 */
10353 attrValue = xmlSchemaGetNodeContent(ctxt,
10354 (xmlNodePtr) attr);
10355 if (xmlSchemaPValAttrBlockFinal(attrValue,
10356 &(type->flags),
10357 -1,
10358 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10359 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10360 -1, -1, -1) != 0)
10361 {
10362 xmlSchemaPSimpleTypeErr(ctxt,
10363 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10364 &des, type, (xmlNodePtr) attr,
10365 NULL,
10366 "(#all | List of (extension | restriction))",
10367 attrValue, NULL, NULL, NULL);
10368 }
10369 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10370 /*
10371 * Attribute "block".
10372 */
10373 attrValue = xmlSchemaGetNodeContent(ctxt,
10374 (xmlNodePtr) attr);
10375 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
10376 -1,
10377 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
10378 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
10379 -1, -1, -1) != 0) {
10380 xmlSchemaPSimpleTypeErr(ctxt,
10381 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10382 &des, type, (xmlNodePtr) attr,
10383 NULL,
10384 "(#all | List of (extension | restriction)) ",
10385 attrValue, NULL, NULL, NULL);
10386 }
10387 } else {
10388 xmlSchemaPIllegalAttrErr(ctxt,
10389 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10390 &des, type, attr);
10391 }
10392 } else {
10393 xmlSchemaPIllegalAttrErr(ctxt,
10394 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10395 &des, type, attr);
10396 }
10397 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10398 xmlSchemaPIllegalAttrErr(ctxt,
10399 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10400 &des, type, attr);
10401 }
10402 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010403 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010404 if (xmlSchemaGetPropNode(node, "block") == NULL) {
10405 /*
10406 * Apply default "block" values.
10407 */
10408 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10409 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10410 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10411 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10412 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010413 /*
10414 * And now for the children...
10415 */
10416 oldcontainer = ctxt->container;
10417 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010418 child = node->children;
10419 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010420 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10421 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010422 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010423 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010424 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010425 /*
10426 * 3.4.3 : 2.2
10427 * Specifying mixed='true' when the <simpleContent>
10428 * alternative is chosen has no effect
10429 */
William M. Bracke7091952004-05-11 15:09:58 +000010430 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10431 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010432 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010433 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010434 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010435 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10436 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010437 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010438 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010439 /*
10440 * SPEC
10441 * "...the third alternative (neither <simpleContent> nor
10442 * <complexContent>) is chosen. This case is understood as shorthand
10443 * for complex content restricting the ·ur-type definition·, and the
10444 * details of the mappings should be modified as necessary.
10445 */
10446 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10447 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010448 /*
10449 * Parse model groups.
10450 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010451 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010452 type->subtypes = (xmlSchemaTypePtr)
10453 xmlSchemaParseModelGroup(ctxt, schema, child,
10454 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010455 child = child->next;
10456 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010457 type->subtypes = (xmlSchemaTypePtr)
10458 xmlSchemaParseModelGroup(ctxt, schema, child,
10459 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010460 child = child->next;
10461 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010462 type->subtypes = (xmlSchemaTypePtr)
10463 xmlSchemaParseModelGroup(ctxt, schema, child,
10464 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010465 child = child->next;
10466 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010467 type->subtypes = (xmlSchemaTypePtr)
10468 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010469 child = child->next;
10470 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010471 /*
10472 * Parse attribute decls/refs.
10473 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010474 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010475 /*
10476 * Parse attribute wildcard.
10477 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010478 if (IS_SCHEMA(child, "anyAttribute")) {
10479 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10480 child = child->next;
10481 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010482 }
10483 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010484 xmlSchemaPContentErr(ctxt,
10485 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10486 &des, type, node, child,
10487 NULL, "(annotation?, (simpleContent | complexContent | "
10488 "((group | all | choice | sequence)?, ((attribute | "
10489 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010490 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010491 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010492 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010493 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010494 return (type);
10495}
10496
Daniel Veillard4255d502002-04-16 15:50:10 +000010497/**
10498 * xmlSchemaParseSchema:
10499 * @ctxt: a schema validation context
10500 * @node: a subtree containing XML Schema informations
10501 *
10502 * parse a XML schema definition from a node set
10503 * *WARNING* this interface is highly subject to change
10504 *
10505 * Returns the internal XML Schema structure built from the resource or
10506 * NULL in case of error
10507 */
10508static xmlSchemaPtr
10509xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10510{
10511 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010512 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010513 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010514 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010515
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010516 /*
10517 * This one is called by xmlSchemaParse only and is used if
10518 * the schema to be parsed was specified via the API; i.e. not
10519 * automatically by the validated instance document.
10520 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010521 if ((ctxt == NULL) || (node == NULL))
10522 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010523 nberrors = ctxt->nberrors;
10524 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010525 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010526 xmlSchemaImportPtr import;
10527
Daniel Veillard4255d502002-04-16 15:50:10 +000010528 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010529 if (schema == NULL)
10530 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010531 /*
10532 * Disable build of list of items.
10533 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010534 attr = xmlSchemaGetPropNode(node, "targetNamespace");
10535 if (attr != NULL) {
10536 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
10537 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10538 /*
10539 * TODO: Should we proceed with an invalid target namespace?
10540 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010541 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
10542 } else {
10543 schema->targetNamespace = NULL;
10544 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010545 /*
10546 * Add the current ns name and location to the import table;
10547 * this is needed to have a consistent mechanism, regardless
10548 * if all schemata are constructed dynamically fired by the
10549 * instance or if the schema to be used was specified via
10550 * the API.
10551 */
10552 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10553 schema->targetNamespace);
10554 if (import == NULL) {
10555 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10556 NULL, NULL, (xmlNodePtr) ctxt->doc,
10557 "Internal error: xmlSchemaParseSchema, "
10558 "failed to add an import entry", NULL);
10559 xmlSchemaFree(schema);
10560 schema = NULL;
10561 return (NULL);
10562 }
10563 import->schemaLocation = ctxt->URL;
10564 /*
10565 * NOTE: We won't set the doc here, otherwise it will be freed
10566 * if the import struct is freed.
10567 * import->doc = ctxt->doc;
10568 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010569 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010570 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10571 } else {
10572 xmlDocPtr doc;
10573
10574 doc = node->doc;
10575
10576 if ((doc != NULL) && (doc->URL != NULL)) {
10577 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10578 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010579 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010580 } else {
10581 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10582 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010583 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010584 }
10585 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010586 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010587 if (ctxt->nberrors != 0) {
10588 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010589 xmlSchemaFree(schema);
10590 schema = NULL;
10591 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010592 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010593 if (schema != NULL)
10594 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010595 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010596#ifdef DEBUG
10597 if (schema == NULL)
10598 xmlGenericError(xmlGenericErrorContext,
10599 "xmlSchemaParse() failed\n");
10600#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010601 return (schema);
10602}
10603
10604/************************************************************************
10605 * *
10606 * Validating using Schemas *
10607 * *
10608 ************************************************************************/
10609
10610/************************************************************************
10611 * *
10612 * Reading/Writing Schemas *
10613 * *
10614 ************************************************************************/
10615
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010616#if 0 /* Will be enabled if it is clear what options are needed. */
10617/**
10618 * xmlSchemaParserCtxtSetOptions:
10619 * @ctxt: a schema parser context
10620 * @options: a combination of xmlSchemaParserOption
10621 *
10622 * Sets the options to be used during the parse.
10623 *
10624 * Returns 0 in case of success, -1 in case of an
10625 * API error.
10626 */
10627static int
10628xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10629 int options)
10630
10631{
10632 int i;
10633
10634 if (ctxt == NULL)
10635 return (-1);
10636 /*
10637 * WARNING: Change the start value if adding to the
10638 * xmlSchemaParseOption.
10639 */
10640 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10641 if (options & 1<<i) {
10642 return (-1);
10643 }
10644 }
10645 ctxt->options = options;
10646 return (0);
10647}
10648
10649/**
10650 * xmlSchemaValidCtxtGetOptions:
10651 * @ctxt: a schema parser context
10652 *
10653 * Returns the option combination of the parser context.
10654 */
10655static int
10656xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
10657
10658{
10659 if (ctxt == NULL)
10660 return (-1);
10661 else
10662 return (ctxt->options);
10663}
10664
10665 void *curItems; /* used for dynamic addition of schemata */
10666 int nbCurItems; /* used for dynamic addition of schemata */
10667 int sizeCurItems; /* used for dynamic addition of schemata */
10668
10669#endif
10670
Daniel Veillard4255d502002-04-16 15:50:10 +000010671/**
10672 * xmlSchemaNewParserCtxt:
10673 * @URL: the location of the schema
10674 *
10675 * Create an XML Schemas parse context for that file/resource expected
10676 * to contain an XML Schemas file.
10677 *
10678 * Returns the parser context or NULL in case of error
10679 */
10680xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010681xmlSchemaNewParserCtxt(const char *URL)
10682{
Daniel Veillard4255d502002-04-16 15:50:10 +000010683 xmlSchemaParserCtxtPtr ret;
10684
10685 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010686 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010687
10688 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10689 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010690 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010691 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010692 return (NULL);
10693 }
10694 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010695 ret->dict = xmlDictCreate();
10696 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010697 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010698 return (ret);
10699}
10700
10701/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010702 * xmlSchemaNewParserCtxtUseDict:
10703 * @URL: the location of the schema
10704 * @dict: the dictionary to be used
10705 *
10706 * Create an XML Schemas parse context for that file/resource expected
10707 * to contain an XML Schemas file.
10708 *
10709 * Returns the parser context or NULL in case of error
10710 */
10711static xmlSchemaParserCtxtPtr
10712xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
10713{
10714 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010715 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010716 if (URL == NULL)
10717 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010718 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010719
10720 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10721 if (ret == NULL) {
10722 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10723 NULL);
10724 return (NULL);
10725 }
10726 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10727 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010728 xmlDictReference(dict);
10729 if (URL != NULL)
10730 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010731 ret->includes = 0;
10732 return (ret);
10733}
10734
10735
10736/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010737 * xmlSchemaNewMemParserCtxt:
10738 * @buffer: a pointer to a char array containing the schemas
10739 * @size: the size of the array
10740 *
10741 * Create an XML Schemas parse context for that memory buffer expected
10742 * to contain an XML Schemas file.
10743 *
10744 * Returns the parser context or NULL in case of error
10745 */
10746xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010747xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10748{
Daniel Veillard6045c902002-10-09 21:13:59 +000010749 xmlSchemaParserCtxtPtr ret;
10750
10751 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010752 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010753
10754 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10755 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010756 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010757 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010758 return (NULL);
10759 }
10760 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10761 ret->buffer = buffer;
10762 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010763 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010764 return (ret);
10765}
10766
10767/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010768 * xmlSchemaNewDocParserCtxt:
10769 * @doc: a preparsed document tree
10770 *
10771 * Create an XML Schemas parse context for that document.
10772 * NB. The document may be modified during the parsing process.
10773 *
10774 * Returns the parser context or NULL in case of error
10775 */
10776xmlSchemaParserCtxtPtr
10777xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10778{
10779 xmlSchemaParserCtxtPtr ret;
10780
10781 if (doc == NULL)
10782 return (NULL);
10783
10784 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10785 if (ret == NULL) {
10786 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10787 NULL);
10788 return (NULL);
10789 }
10790 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10791 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010792 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010793 /* The application has responsibility for the document */
10794 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010795
10796 return (ret);
10797}
10798
10799/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010800 * xmlSchemaFreeParserCtxt:
10801 * @ctxt: the schema parser context
10802 *
10803 * Free the resources associated to the schema parser context
10804 */
10805void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010806xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10807{
Daniel Veillard4255d502002-04-16 15:50:10 +000010808 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010809 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010810 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010811 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010812 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010813 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010814 xmlFree(ctxt->assemble);
10815 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010816 if (ctxt->vctxt != NULL) {
10817 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10818 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010819 if (ctxt->localImports != NULL)
10820 xmlFree((xmlChar *) ctxt->localImports);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010821 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010822 xmlFree(ctxt);
10823}
10824
10825/************************************************************************
10826 * *
10827 * Building the content models *
10828 * *
10829 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010830
Daniel Veillard4255d502002-04-16 15:50:10 +000010831/**
10832 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000010833 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010834 * @particle: the particle component
10835 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000010836 *
10837 * Generate the automata sequence needed for that type
10838 */
10839static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010840xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt,
10841 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010842 const xmlChar * name)
10843{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010844 if (particle == NULL) {
10845 xmlSchemaPErr(ctxt, NULL,
10846 XML_SCHEMAP_INTERNAL,
10847 "Internal error: xmlSchemaBuildAContentModel, "
10848 "particle is NULL.\n", NULL, NULL);
10849 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010850 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010851 if (particle->children == NULL) {
10852 xmlSchemaPErr(ctxt, GET_NODE(particle),
10853 XML_SCHEMAP_INTERNAL,
10854 "Internal error: xmlSchemaBuildAContentModel, "
10855 "no term on particle.\n", NULL, NULL);
10856 return;
10857 }
10858
10859 switch (particle->children->type) {
10860 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010861 xmlAutomataStatePtr start, end;
10862 xmlSchemaWildcardPtr wild;
10863 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000010864
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010865 wild = (xmlSchemaWildcardPtr) particle->children;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010866
10867 start = ctxt->state;
10868 end = xmlAutomataNewState(ctxt->am);
10869
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010870 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010871 if (wild->any == 1) {
10872 /*
10873 * We need to add both transitions:
10874 *
10875 * 1. the {"*", "*"} for elements in a namespace.
10876 */
10877 ctxt->state =
10878 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010879 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010880 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10881 /*
10882 * 2. the {"*"} for elements in no namespace.
10883 */
10884 ctxt->state =
10885 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010886 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010887 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10888
10889 } else if (wild->nsSet != NULL) {
10890 ns = wild->nsSet;
10891 do {
10892 ctxt->state = start;
10893 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010894 ctxt->state, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010895 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10896 ns = ns->next;
10897 } while (ns != NULL);
10898
10899 } else if (wild->negNsSet != NULL) {
10900 xmlAutomataStatePtr deadEnd;
10901
10902 deadEnd = xmlAutomataNewState(ctxt->am);
10903 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010904 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010905 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010906 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010907 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10908 }
10909 } else {
10910 int counter;
10911 xmlAutomataStatePtr hop;
10912 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010913 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010914 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010915 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010916
10917 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
10918 hop = xmlAutomataNewState(ctxt->am);
10919 if (wild->any == 1) {
10920 ctxt->state =
10921 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010922 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010923 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10924 ctxt->state =
10925 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010926 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010927 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10928 } else if (wild->nsSet != NULL) {
10929 ns = wild->nsSet;
10930 do {
10931 ctxt->state =
10932 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010933 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010934 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10935 ns = ns->next;
10936 } while (ns != NULL);
10937
10938 } else if (wild->negNsSet != NULL) {
10939 xmlAutomataStatePtr deadEnd;
10940
10941 deadEnd = xmlAutomataNewState(ctxt->am);
10942 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010943 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010944 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010945 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010946 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10947 }
10948 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
10949 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
10950 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010951 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010952 xmlAutomataNewEpsilon(ctxt->am, start, end);
10953 }
10954 ctxt->state = end;
10955 break;
10956 }
10957 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010958 xmlAutomataStatePtr oldstate;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010959 xmlSchemaElementPtr elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +000010960
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010961 elemDecl = (xmlSchemaElementPtr) particle->children;
10962
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010963 oldstate = ctxt->state;
10964
10965 if (particle->maxOccurs >= UNBOUNDED) {
10966 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010967 xmlAutomataStatePtr tmp;
10968 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +000010969
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010970 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010971 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010972 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010973 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010974 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000010975 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010976 xmlAutomataNewTransition2(ctxt->am,
10977 ctxt->state, NULL,
10978 elemDecl->name,
10979 elemDecl->targetNamespace,
10980 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010981 tmp = ctxt->state;
10982 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010983 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010984 ctxt->state =
10985 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010986 counter);
Daniel Veillard32370232002-10-16 14:08:14 +000010987
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010988 } else {
10989 ctxt->state =
10990 xmlAutomataNewTransition2(ctxt->am,
10991 ctxt->state, NULL,
10992 elemDecl->name,
10993 elemDecl->targetNamespace,
10994 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010995 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
10996 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010997 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010998 /* basically an elem* */
10999 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11000 ctxt->state);
11001 }
11002 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011003 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011004 xmlAutomataStatePtr tmp;
11005 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +000011006
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011007 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
11008 oldstate, NULL);
11009 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011010 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011011 particle->minOccurs - 1,
11012 particle->maxOccurs - 1);
11013 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
11014 ctxt->state,
11015 NULL,
11016 elemDecl->name,
11017 elemDecl->targetNamespace,
11018 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011019 tmp = ctxt->state;
11020 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011021 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011022 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011023 NULL, counter);
11024 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011025 /* basically an elem? */
11026 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011027 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011028 }
Daniel Veillardb39bc392002-10-26 19:29:51 +000011029
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011030 } else {
11031 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
11032 ctxt->state,
11033 NULL,
11034 elemDecl->name,
11035 elemDecl->targetNamespace,
11036 (xmlSchemaTypePtr) elemDecl);
11037 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011038 /* basically an elem? */
11039 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011040 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011041 }
11042 }
11043 break;
11044 }
11045 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011046 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011047
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011048 /*
11049 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011050 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011051 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011052 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11053 sub = particle->children->children;
11054 while (sub != NULL) {
11055 xmlSchemaBuildAContentModel(ctxt,
11056 (xmlSchemaParticlePtr) sub, name);
11057 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011058 }
11059 } else {
11060 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011061
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011062 if (particle->maxOccurs >= UNBOUNDED) {
11063 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011064 xmlAutomataStatePtr tmp;
11065 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011066
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011067 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011068 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011069 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011070
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011071 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011072 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011073
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011074 sub = particle->children->children;
11075 while (sub != NULL) {
11076 xmlSchemaBuildAContentModel(ctxt,
11077 (xmlSchemaParticlePtr) sub, name);
11078 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011079 }
11080 tmp = ctxt->state;
11081 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11082 oldstate, counter);
11083 ctxt->state =
11084 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11085 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011086
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011087 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011088 sub = particle->children->children;
11089 while (sub != NULL) {
11090 xmlSchemaBuildAContentModel(ctxt,
11091 (xmlSchemaParticlePtr) sub, name);
11092 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011093 }
11094 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11095 oldstate);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011096 if (particle->minOccurs == 0) {
11097 xmlAutomataNewEpsilon(ctxt->am,
11098 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011099 }
11100 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011101 } else if ((particle->maxOccurs > 1)
11102 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011103 xmlAutomataStatePtr tmp;
11104 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011105
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011106 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011107 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011108 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011109
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011110 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011111 particle->minOccurs - 1,
11112 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011113
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011114 sub = particle->children->children;
11115 while (sub != NULL) {
11116 xmlSchemaBuildAContentModel(ctxt,
11117 (xmlSchemaParticlePtr) sub, name);
11118 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011119 }
11120 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011121 xmlAutomataNewCountedTrans(ctxt->am,
11122 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011123 ctxt->state =
11124 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11125 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011126 if (particle->minOccurs == 0) {
11127 xmlAutomataNewEpsilon(ctxt->am,
11128 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011129 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011130 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011131 sub = particle->children->children;
11132 while (sub != NULL) {
11133 xmlSchemaBuildAContentModel(ctxt,
11134 (xmlSchemaParticlePtr) sub, name);
11135 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011136 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011137 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011138 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11139 ctxt->state);
11140 }
11141 }
11142 }
11143 break;
11144 }
11145 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011146 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011147 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011148
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011149 start = ctxt->state;
11150 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011151
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011152 /*
11153 * iterate over the subtypes and remerge the end with an
11154 * epsilon transition
11155 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011156 if (particle->maxOccurs == 1) {
11157 sub = particle->children->children;
11158 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011159 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011160 xmlSchemaBuildAContentModel(ctxt,
11161 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011162 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011163 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011164 }
11165 } else {
11166 int counter;
11167 xmlAutomataStatePtr hop;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011168 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11169 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011170 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011171 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011172
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011173 /*
11174 * use a counter to keep track of the number of transtions
11175 * which went through the choice.
11176 */
11177 counter =
11178 xmlAutomataNewCounter(ctxt->am, minOccurs,
11179 maxOccurs);
11180 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011181
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011182 sub = particle->children->children;
11183 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011184 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011185 xmlSchemaBuildAContentModel(ctxt,
11186 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011187 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011188 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011189 }
11190 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
11191 counter);
11192 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
11193 counter);
11194 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011195 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011196 xmlAutomataNewEpsilon(ctxt->am, start, end);
11197 }
11198 ctxt->state = end;
11199 break;
11200 }
11201 case XML_SCHEMA_TYPE_ALL:{
11202 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011203 xmlSchemaParticlePtr sub;
11204 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011205 int lax;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011206
11207 sub = (xmlSchemaParticlePtr) particle->children->children;
11208 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011209 break;
11210 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011211 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011212 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011213
11214 elemDecl = (xmlSchemaElementPtr) sub->children;
11215 if (elemDecl == NULL) {
11216 xmlSchemaPErr(ctxt, NULL,
11217 XML_SCHEMAP_INTERNAL,
11218 "Internal error: xmlSchemaBuildAContentModel, "
11219 "<element> particle a NULL term.\n", NULL, NULL);
11220 return;
11221 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011222 /*
11223 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011224 * {particles} of the group must be 0 or 1; this is
11225 * already ensured during the parse of the content of
11226 * <all>.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011227 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011228 if ((sub->minOccurs == 1) &&
11229 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011230 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
11231 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011232 elemDecl->name,
11233 elemDecl->targetNamespace,
11234 1, 1, elemDecl);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011235 } else if ((sub->minOccurs == 0) &&
11236 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011237
11238 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
11239 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011240 elemDecl->name,
11241 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011242 0,
11243 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011244 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011245 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011246 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011247 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011248 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011249 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011250 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011251 break;
11252 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011253 default:
11254 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011255 "Internal error: xmlSchemaBuildAContentModel, found "
11256 "unexpected term of type %d in content model of complex "
11257 "type '%s'.\n",
11258 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011259 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011260 }
11261}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011262
Daniel Veillard4255d502002-04-16 15:50:10 +000011263/**
11264 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011265 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011266 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011267 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011268 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011269 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011270 */
11271static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011272xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011273 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011274 const xmlChar * name)
11275{
Daniel Veillard4255d502002-04-16 15:50:10 +000011276 xmlAutomataStatePtr start;
11277
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011278 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11279 (type->contModel != NULL) ||
11280 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11281 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011282 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011283
11284#ifdef DEBUG_CONTENT
11285 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011286 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011287#endif
11288
Daniel Veillard4255d502002-04-16 15:50:10 +000011289 ctxt->am = xmlNewAutomata();
11290 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011291 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011292 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011293 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011294 }
11295 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011296 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011297 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011298 type->contModel = xmlAutomataCompile(ctxt->am);
11299 if (type->contModel == NULL) {
11300 xmlSchemaPCustomErr(ctxt,
11301 XML_SCHEMAP_INTERNAL,
11302 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011303 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011304 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011305 xmlSchemaPCustomErr(ctxt,
11306 XML_SCHEMAP_NOT_DETERMINISTIC,
11307 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011308 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011309 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011310 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011311#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011312 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011313 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011314 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011315#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011316 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011317 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011318 xmlFreeAutomata(ctxt->am);
11319 ctxt->am = NULL;
11320}
11321
11322/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011323 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011324 * @elem: the schema element context
11325 * @ctxt: the schema parser context
11326 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011327 * Resolves the references of an element declaration
11328 * or particle, which has an element declaration as it's
11329 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011330 */
11331static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011332xmlSchemaElementFixup(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011333 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011334 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011335 const xmlChar * context ATTRIBUTE_UNUSED,
11336 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011337{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011338 if ((ctxt == NULL) || (elem == NULL) ||
11339 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011340 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011341 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011342
11343 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
11344 xmlSchemaTypePtr type;
11345
11346 /* (type definition) ... otherwise the type definition ·resolved·
11347 * to by the ·actual value· of the type [attribute] ...
11348 */
11349 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
11350 elem->namedTypeNs);
11351 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011352 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011353 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011354 NULL, (xmlSchemaTypePtr) elem, elem->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011355 "type", elem->namedType, elem->namedTypeNs,
11356 XML_SCHEMA_TYPE_BASIC, "type definition");
11357 } else
11358 elem->subtypes = type;
11359 }
11360 if (elem->substGroup != NULL) {
11361 xmlSchemaElementPtr substHead;
11362
Daniel Veillardc0826a72004-08-10 14:17:33 +000011363 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011364 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
11365 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011366 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011367 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
11368 elem->substGroupNs);
11369 if (substHead == NULL) {
11370 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011371 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011372 NULL, (xmlSchemaTypePtr) elem, NULL,
11373 "substitutionGroup", elem->substGroup, elem->substGroupNs,
11374 XML_SCHEMA_TYPE_ELEMENT, NULL);
11375 } else {
11376 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
11377 /*
11378 * (type definition)...otherwise the {type definition} of the
11379 * element declaration ·resolved· to by the ·actual value· of
11380 * the substitutionGroup [attribute], if present
11381 */
11382 if (elem->subtypes == NULL)
11383 elem->subtypes = substHead->subtypes;
11384 }
11385 }
11386 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
11387 (elem->substGroup == NULL))
11388 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011389}
11390
11391/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011392 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011393 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011394 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011395 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011396 * Checks and builds the memberTypes of the union simple type.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011397 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011398 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011399static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011400xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11401 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011402{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011403
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011404 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
11405 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011406
Daniel Veillard01fa6152004-06-29 17:04:39 +000011407 /* 1 If the <union> alternative is chosen, then [Definition:]
11408 * define the explicit members as the type definitions ·resolved·
11409 * to by the items in the ·actual value· of the memberTypes [attribute],
11410 * if any, followed by the type definitions corresponding to the
11411 * <simpleType>s among the [children] of <union>, if any.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011412 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011413 /*
11414 * Resolve references.
11415 */
11416 link = type->memberTypes;
11417 lastLink = NULL;
11418 while (link != NULL) {
11419 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011420
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011421 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11422 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11423
11424 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11425 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11426 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
11427 NULL, type, type->node, "memberTypes",
11428 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11429 /*
11430 * Remove the member type link.
11431 */
11432 if (lastLink == NULL)
11433 type->memberTypes = link->next;
11434 else
11435 lastLink->next = link->next;
11436 newLink = link;
11437 link = link->next;
11438 xmlFree(newLink);
11439 } else {
11440 link->type = memberType;
11441 if (IS_NOT_TYPEFIXED(memberType))
11442 xmlSchemaTypeFixup(memberType, ctxt, NULL);
11443
11444 lastLink = link;
11445 link = link->next;
11446 }
11447 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011448 /*
11449 * Add local simple types,
11450 */
11451 memberType = type->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011452 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011453 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11454 if (link == NULL) {
11455 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11456 return (-1);
11457 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011458 if (IS_NOT_TYPEFIXED(memberType))
11459 xmlSchemaTypeFixup(memberType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011460 link->type = memberType;
11461 link->next = NULL;
11462 if (lastLink == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011463 type->memberTypes = link;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011464 else
11465 lastLink->next = link;
11466 lastLink = link;
11467 memberType = memberType->next;
11468 }
11469 /*
11470 * The actual value is then formed by replacing any union type
11471 * definition in the ·explicit members· with the members of their
11472 * {member type definitions}, in order.
11473 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011474 link = type->memberTypes;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011475 while (link != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011476 /* TODO: type-fixup it. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011477 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011478 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011479 if (subLink != NULL) {
11480 link->type = subLink->type;
11481 if (subLink->next != NULL) {
11482 lastLink = link->next;
11483 subLink = subLink->next;
11484 prevLink = link;
11485 while (subLink != NULL) {
11486 newLink = (xmlSchemaTypeLinkPtr)
11487 xmlMalloc(sizeof(xmlSchemaTypeLink));
11488 if (newLink == NULL) {
11489 xmlSchemaPErrMemory(ctxt, "allocating a type link",
11490 NULL);
11491 return (-1);
11492 }
11493 newLink->type = memberType;
11494 prevLink->next = newLink;
11495 prevLink = newLink;
11496 newLink->next = lastLink;
11497
11498 subLink = subLink->next;
11499 }
11500 }
11501 }
11502 }
11503 link = link->next;
11504 }
11505
11506 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011507}
11508
Daniel Veillard4255d502002-04-16 15:50:10 +000011509/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011510 * xmlSchemaIsDerivedFromBuiltInType:
11511 * @ctxt: the schema parser context
11512 * @type: the type definition
11513 * @valType: the value type
11514 *
11515 *
11516 * Returns 1 if the type has the given value type, or
11517 * is derived from such a type.
11518 */
William M. Brack803812b2004-06-03 02:11:24 +000011519static int
Daniel Veillard3646d642004-06-02 19:19:14 +000011520xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
11521 xmlSchemaTypePtr type, int valType)
11522{
11523 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011524 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011525 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011526 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011527 return(1);
11528 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
11529 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
11530 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
11531 ((xmlSchemaAttributePtr) type)->subtypes, valType));
11532 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
11533 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
11534 if (type->baseType != NULL)
11535 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
11536 valType));
11537 } else if ((type->subtypes != NULL) &&
11538 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
11539 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11540 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
11541 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
11542 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
11543 valType));
11544 }
11545
11546 return (0);
11547}
11548
11549/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011550 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011551 * @type: the simpleType definition
11552 *
11553 * Returns the primitive type of the given type or
11554 * NULL in case of error.
11555 */
11556static xmlSchemaTypePtr
11557xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11558{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011559
Daniel Veillard01fa6152004-06-29 17:04:39 +000011560 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011561 /*
11562 * Note that anySimpleType is actually not a primitive type
11563 * but we need that here.
11564 */
11565 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11566 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011567 return (type);
11568 type = type->baseType;
11569 }
11570
11571 return (NULL);
11572}
11573
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011574#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011575/**
11576 * xmlSchemaGetBuiltInTypeAncestor:
11577 * @type: the simpleType definition
11578 *
11579 * Returns the primitive type of the given type or
11580 * NULL in case of error.
11581 */
11582static xmlSchemaTypePtr
11583xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11584{
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011585 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
11586 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))
11587 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011588 while (type != NULL) {
11589 if (type->type == XML_SCHEMA_TYPE_BASIC)
11590 return (type);
11591 type = type->baseType;
11592 }
11593
11594 return (NULL);
11595}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011596#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011597
Daniel Veillard01fa6152004-06-29 17:04:39 +000011598/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011599 * xmlSchemaBuildAttributeUsesOwned:
11600 * @ctxt: the schema parser context
11601 * @type: the complex type definition
11602 * @cur: the attribute declaration list
11603 * @lastUse: the top of the attribute use list
11604 *
11605 * Builds the attribute uses list on the given complex type.
11606 * This one is supposed to be called by
11607 * xmlSchemaBuildAttributeValidation only.
11608 */
11609static int
11610xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
11611 xmlSchemaAttributePtr cur,
11612 xmlSchemaAttributeLinkPtr *uses,
11613 xmlSchemaAttributeLinkPtr *lastUse)
11614{
11615 xmlSchemaAttributeLinkPtr tmp;
11616 while (cur != NULL) {
11617 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
11618 /*
11619 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11620 * to by the ·actual value·s of the ref [attribute] of the
11621 * <attributeGroup> [children], if any."
11622 */
11623 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11624 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
11625 lastUse) == -1) {
11626 return (-1);
11627 }
11628 } else {
11629 /* W3C: "1 The set of attribute uses corresponding to the
11630 * <attribute> [children], if any."
11631 */
11632 tmp = (xmlSchemaAttributeLinkPtr)
11633 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11634 if (tmp == NULL) {
11635 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11636 return (-1);
11637 }
11638 tmp->attr = cur;
11639 tmp->next = NULL;
11640 if (*uses == NULL)
11641 *uses = tmp;
11642 else
11643 (*lastUse)->next = tmp;
11644 *lastUse = tmp;
11645 }
11646 cur = cur->next;
11647 }
11648 return (0);
11649}
11650
Daniel Veillard50355f02004-06-08 17:52:16 +000011651/**
11652 * xmlSchemaCloneWildcardNsConstraints:
11653 * @ctxt: the schema parser context
11654 * @dest: the destination wildcard
11655 * @source: the source wildcard
11656 *
11657 * Clones the namespace constraints of source
11658 * and assignes them to dest.
11659 * Returns -1 on internal error, 0 otherwise.
11660 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011661static int
11662xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11663 xmlSchemaWildcardPtr *dest,
11664 xmlSchemaWildcardPtr source)
11665{
11666 xmlSchemaWildcardNsPtr cur, tmp, last;
11667
11668 if ((source == NULL) || (*dest == NULL))
11669 return(-1);
11670 (*dest)->any = source->any;
11671 cur = source->nsSet;
11672 last = NULL;
11673 while (cur != NULL) {
11674 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11675 if (tmp == NULL)
11676 return(-1);
11677 tmp->value = cur->value;
11678 if (last == NULL)
11679 (*dest)->nsSet = tmp;
11680 else
11681 last->next = tmp;
11682 last = tmp;
11683 cur = cur->next;
11684 }
11685 if ((*dest)->negNsSet != NULL)
11686 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
11687 if (source->negNsSet != NULL) {
11688 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11689 if ((*dest)->negNsSet == NULL)
11690 return(-1);
11691 (*dest)->negNsSet->value = source->negNsSet->value;
11692 } else
11693 (*dest)->negNsSet = NULL;
11694 return(0);
11695}
11696
Daniel Veillard50355f02004-06-08 17:52:16 +000011697/**
11698 * xmlSchemaUnionWildcards:
11699 * @ctxt: the schema parser context
11700 * @completeWild: the first wildcard
11701 * @curWild: the second wildcard
11702 *
11703 * Unions the namespace constraints of the given wildcards.
11704 * @completeWild will hold the resulting union.
11705 * Returns a positive error code on failure, -1 in case of an
11706 * internal error, 0 otherwise.
11707 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011708static int
11709xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
11710 xmlSchemaWildcardPtr completeWild,
11711 xmlSchemaWildcardPtr curWild)
11712{
11713 xmlSchemaWildcardNsPtr cur, curB, tmp;
11714
11715 /*
11716 * 1 If O1 and O2 are the same value, then that value must be the
11717 * value.
11718 */
11719 if ((completeWild->any == curWild->any) &&
11720 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11721 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
11722
11723 if ((completeWild->negNsSet == NULL) ||
11724 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
11725
11726 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011727 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011728
11729 /*
11730 * Check equality of sets.
11731 */
11732 cur = completeWild->nsSet;
11733 while (cur != NULL) {
11734 found = 0;
11735 curB = curWild->nsSet;
11736 while (curB != NULL) {
11737 if (cur->value == curB->value) {
11738 found = 1;
11739 break;
11740 }
11741 curB = curB->next;
11742 }
11743 if (!found)
11744 break;
11745 cur = cur->next;
11746 }
11747 if (found)
11748 return(0);
11749 } else
11750 return(0);
11751 }
11752 }
11753 /*
11754 * 2 If either O1 or O2 is any, then any must be the value
11755 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011756 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011757 if (completeWild->any == 0) {
11758 completeWild->any = 1;
11759 if (completeWild->nsSet != NULL) {
11760 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11761 completeWild->nsSet = NULL;
11762 }
11763 if (completeWild->negNsSet != NULL) {
11764 xmlFree(completeWild->negNsSet);
11765 completeWild->negNsSet = NULL;
11766 }
11767 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011768 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011769 }
11770 /*
11771 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
11772 * then the union of those sets must be the value.
11773 */
11774 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
11775 int found;
11776 xmlSchemaWildcardNsPtr start;
11777
11778 cur = curWild->nsSet;
11779 start = completeWild->nsSet;
11780 while (cur != NULL) {
11781 found = 0;
11782 curB = start;
11783 while (curB != NULL) {
11784 if (cur->value == curB->value) {
11785 found = 1;
11786 break;
11787 }
11788 curB = curB->next;
11789 }
11790 if (!found) {
11791 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11792 if (tmp == NULL)
11793 return (-1);
11794 tmp->value = cur->value;
11795 tmp->next = completeWild->nsSet;
11796 completeWild->nsSet = tmp;
11797 }
11798 cur = cur->next;
11799 }
11800
11801 return(0);
11802 }
11803 /*
11804 * 4 If the two are negations of different values (namespace names
11805 * or ·absent·), then a pair of not and ·absent· must be the value.
11806 */
11807 if ((completeWild->negNsSet != NULL) &&
11808 (curWild->negNsSet != NULL) &&
11809 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11810 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011811
11812 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011813 }
11814 /*
11815 * 5.
11816 */
11817 if (((completeWild->negNsSet != NULL) &&
11818 (completeWild->negNsSet->value != NULL) &&
11819 (curWild->nsSet != NULL)) ||
11820 ((curWild->negNsSet != NULL) &&
11821 (curWild->negNsSet->value != NULL) &&
11822 (completeWild->nsSet != NULL))) {
11823
11824 int nsFound, absentFound = 0;
11825
11826 if (completeWild->nsSet != NULL) {
11827 cur = completeWild->nsSet;
11828 curB = curWild->negNsSet;
11829 } else {
11830 cur = curWild->nsSet;
11831 curB = completeWild->negNsSet;
11832 }
11833 nsFound = 0;
11834 while (cur != NULL) {
11835 if (cur->value == NULL)
11836 absentFound = 1;
11837 else if (cur->value == curB->value)
11838 nsFound = 1;
11839 if (nsFound && absentFound)
11840 break;
11841 cur = cur->next;
11842 }
11843
11844 if (nsFound && absentFound) {
11845 /*
11846 * 5.1 If the set S includes both the negated namespace
11847 * name and ·absent·, then any must be the value.
11848 */
11849 completeWild->any = 1;
11850 if (completeWild->nsSet != NULL) {
11851 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11852 completeWild->nsSet = NULL;
11853 }
11854 if (completeWild->negNsSet != NULL) {
11855 xmlFree(completeWild->negNsSet);
11856 completeWild->negNsSet = NULL;
11857 }
11858 } else if (nsFound && (!absentFound)) {
11859 /*
11860 * 5.2 If the set S includes the negated namespace name
11861 * but not ·absent·, then a pair of not and ·absent· must
11862 * be the value.
11863 */
11864 if (completeWild->nsSet != NULL) {
11865 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11866 completeWild->nsSet = NULL;
11867 }
11868 if (completeWild->negNsSet == NULL) {
11869 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11870 if (completeWild->negNsSet == NULL)
11871 return (-1);
11872 }
11873 completeWild->negNsSet->value = NULL;
11874 } else if ((!nsFound) && absentFound) {
11875 /*
11876 * 5.3 If the set S includes ·absent· but not the negated
11877 * namespace name, then the union is not expressible.
11878 */
11879 xmlSchemaPErr(ctxt, completeWild->node,
11880 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011881 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011882 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011883 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011884 } else if ((!nsFound) && (!absentFound)) {
11885 /*
11886 * 5.4 If the set S does not include either the negated namespace
11887 * name or ·absent·, then whichever of O1 or O2 is a pair of not
11888 * and a namespace name must be the value.
11889 */
11890 if (completeWild->negNsSet == NULL) {
11891 if (completeWild->nsSet != NULL) {
11892 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11893 completeWild->nsSet = NULL;
11894 }
11895 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11896 if (completeWild->negNsSet == NULL)
11897 return (-1);
11898 completeWild->negNsSet->value = curWild->negNsSet->value;
11899 }
11900 }
11901 return (0);
11902 }
11903 /*
11904 * 6.
11905 */
11906 if (((completeWild->negNsSet != NULL) &&
11907 (completeWild->negNsSet->value == NULL) &&
11908 (curWild->nsSet != NULL)) ||
11909 ((curWild->negNsSet != NULL) &&
11910 (curWild->negNsSet->value == NULL) &&
11911 (completeWild->nsSet != NULL))) {
11912
11913 if (completeWild->nsSet != NULL) {
11914 cur = completeWild->nsSet;
11915 } else {
11916 cur = curWild->nsSet;
11917 }
11918 while (cur != NULL) {
11919 if (cur->value == NULL) {
11920 /*
11921 * 6.1 If the set S includes ·absent·, then any must be the
11922 * value.
11923 */
11924 completeWild->any = 1;
11925 if (completeWild->nsSet != NULL) {
11926 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11927 completeWild->nsSet = NULL;
11928 }
11929 if (completeWild->negNsSet != NULL) {
11930 xmlFree(completeWild->negNsSet);
11931 completeWild->negNsSet = NULL;
11932 }
11933 return (0);
11934 }
11935 cur = cur->next;
11936 }
11937 if (completeWild->negNsSet == NULL) {
11938 /*
11939 * 6.2 If the set S does not include ·absent·, then a pair of not
11940 * and ·absent· must be the value.
11941 */
11942 if (completeWild->nsSet != NULL) {
11943 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11944 completeWild->nsSet = NULL;
11945 }
11946 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11947 if (completeWild->negNsSet == NULL)
11948 return (-1);
11949 completeWild->negNsSet->value = NULL;
11950 }
11951 return (0);
11952 }
11953 return (0);
11954
11955}
11956
Daniel Veillard50355f02004-06-08 17:52:16 +000011957/**
11958 * xmlSchemaIntersectWildcards:
11959 * @ctxt: the schema parser context
11960 * @completeWild: the first wildcard
11961 * @curWild: the second wildcard
11962 *
11963 * Intersects the namespace constraints of the given wildcards.
11964 * @completeWild will hold the resulting intersection.
11965 * Returns a positive error code on failure, -1 in case of an
11966 * internal error, 0 otherwise.
11967 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011968static int
11969xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
11970 xmlSchemaWildcardPtr completeWild,
11971 xmlSchemaWildcardPtr curWild)
11972{
William M. Brack803812b2004-06-03 02:11:24 +000011973 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011974
11975 /*
11976 * 1 If O1 and O2 are the same value, then that value must be the
11977 * value.
11978 */
11979 if ((completeWild->any == curWild->any) &&
11980 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11981 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
11982
11983 if ((completeWild->negNsSet == NULL) ||
11984 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
11985
11986 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011987 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011988
11989 /*
11990 * Check equality of sets.
11991 */
11992 cur = completeWild->nsSet;
11993 while (cur != NULL) {
11994 found = 0;
11995 curB = curWild->nsSet;
11996 while (curB != NULL) {
11997 if (cur->value == curB->value) {
11998 found = 1;
11999 break;
12000 }
12001 curB = curB->next;
12002 }
12003 if (!found)
12004 break;
12005 cur = cur->next;
12006 }
12007 if (found)
12008 return(0);
12009 } else
12010 return(0);
12011 }
12012 }
12013 /*
12014 * 2 If either O1 or O2 is any, then the other must be the value.
12015 */
12016 if ((completeWild->any != curWild->any) && (completeWild->any)) {
12017 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12018 return(-1);
12019 return(0);
12020 }
12021 /*
12022 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12023 * name or ·absent·) and the other is a set of (namespace names or
12024 * ·absent·), then that set, minus the negated value if it was in
12025 * the set, minus ·absent· if it was in the set, must be the value.
12026 */
12027 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12028 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12029 const xmlChar *neg;
12030
12031 if (completeWild->nsSet == NULL) {
12032 neg = completeWild->negNsSet->value;
12033 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12034 return(-1);
12035 } else
12036 neg = curWild->negNsSet->value;
12037 /*
12038 * Remove absent and negated.
12039 */
12040 prev = NULL;
12041 cur = completeWild->nsSet;
12042 while (cur != NULL) {
12043 if (cur->value == NULL) {
12044 if (prev == NULL)
12045 completeWild->nsSet = cur->next;
12046 else
12047 prev->next = cur->next;
12048 xmlFree(cur);
12049 break;
12050 }
12051 prev = cur;
12052 cur = cur->next;
12053 }
12054 if (neg != NULL) {
12055 prev = NULL;
12056 cur = completeWild->nsSet;
12057 while (cur != NULL) {
12058 if (cur->value == neg) {
12059 if (prev == NULL)
12060 completeWild->nsSet = cur->next;
12061 else
12062 prev->next = cur->next;
12063 xmlFree(cur);
12064 break;
12065 }
12066 prev = cur;
12067 cur = cur->next;
12068 }
12069 }
12070
12071 return(0);
12072 }
12073 /*
12074 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
12075 * then the intersection of those sets must be the value.
12076 */
12077 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
12078 int found;
12079
12080 cur = completeWild->nsSet;
12081 prev = NULL;
12082 while (cur != NULL) {
12083 found = 0;
12084 curB = curWild->nsSet;
12085 while (curB != NULL) {
12086 if (cur->value == curB->value) {
12087 found = 1;
12088 break;
12089 }
12090 curB = curB->next;
12091 }
12092 if (!found) {
12093 if (prev == NULL)
12094 completeWild->nsSet = cur->next;
12095 else
12096 prev->next = cur->next;
12097 tmp = cur->next;
12098 xmlFree(cur);
12099 cur = tmp;
12100 continue;
12101 }
12102 prev = cur;
12103 cur = cur->next;
12104 }
12105
12106 return(0);
12107 }
12108 /* 5 If the two are negations of different namespace names,
12109 * then the intersection is not expressible
12110 */
12111 if ((completeWild->negNsSet != NULL) &&
12112 (curWild->negNsSet != NULL) &&
12113 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
12114 (completeWild->negNsSet->value != NULL) &&
12115 (curWild->negNsSet->value != NULL)) {
12116
12117 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012118 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000012119 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012120 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012121 }
12122 /*
12123 * 6 If the one is a negation of a namespace name and the other
12124 * is a negation of ·absent·, then the one which is the negation
12125 * of a namespace name must be the value.
12126 */
12127 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12128 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
12129 (completeWild->negNsSet->value == NULL)) {
12130 completeWild->negNsSet->value = curWild->negNsSet->value;
12131 }
12132 return(0);
12133}
12134
Daniel Veillard50355f02004-06-08 17:52:16 +000012135/**
12136 * xmlSchemaIsWildcardNsConstraintSubset:
12137 * @ctxt: the schema parser context
12138 * @wildA: the first wildcard
12139 * @wildB: the second wildcard
12140 *
12141 * Returns 1 if the namespace constraint of @wildA is an intensional
12142 * subset of @wildB, 0 otherwise.
12143 */
12144static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000012145xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
12146 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000012147{
Daniel Veillard3646d642004-06-02 19:19:14 +000012148
Daniel Veillard50355f02004-06-08 17:52:16 +000012149 /*
12150 * Schema Component Constraint: Wildcard Subset
12151 */
12152 /*
12153 * 1 super must be any.
12154 */
12155 if (wildB->any)
12156 return (1);
12157 /*
12158 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12159 * 2.2 super must be a pair of not and the same value.
12160 */
12161 if ((wildA->negNsSet != NULL) &&
12162 (wildB->negNsSet != NULL) &&
12163 (wildA->negNsSet->value == wildA->negNsSet->value))
12164 return (1);
12165 /*
12166 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
12167 */
12168 if (wildA->nsSet != NULL) {
12169 /*
12170 * 3.2.1 super must be the same set or a superset thereof.
12171 */
12172 if (wildB->nsSet != NULL) {
12173 xmlSchemaWildcardNsPtr cur, curB;
12174 int found = 0;
12175
12176 cur = wildA->nsSet;
12177 while (cur != NULL) {
12178 found = 0;
12179 curB = wildB->nsSet;
12180 while (curB != NULL) {
12181 if (cur->value == curB->value) {
12182 found = 1;
12183 break;
12184 }
12185 curB = curB->next;
12186 }
12187 if (!found)
12188 return (0);
12189 cur = cur->next;
12190 }
12191 if (found)
12192 return (1);
12193 } else if (wildB->negNsSet != NULL) {
12194 xmlSchemaWildcardNsPtr cur;
12195 /*
12196 * 3.2.2 super must be a pair of not and a namespace name or
12197 * ·absent· and that value must not be in sub's set.
12198 */
12199 cur = wildA->nsSet;
12200 while (cur != NULL) {
12201 if (cur->value == wildB->negNsSet->value)
12202 return (0);
12203 cur = cur->next;
12204 }
12205 return (1);
12206 }
12207 }
12208 return (0);
12209}
12210
12211/**
12212 * xmlSchemaBuildCompleteAttributeWildcard:
12213 * @ctxt: the schema parser context
12214 * @attrs: the attribute list
12215 * @completeWild: the resulting complete wildcard
12216 *
12217 * Returns -1 in case of an internal error, 0 otherwise.
12218 */
12219static int
12220xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
12221 xmlSchemaAttributePtr attrs,
12222 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000012223{
12224 while (attrs != NULL) {
12225 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12226 xmlSchemaAttributeGroupPtr group;
12227
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012228 group = (xmlSchemaAttributeGroupPtr) attrs;
12229 /*
12230 * Handle attribute group references.
12231 */
12232 if (group->ref != NULL) {
12233 if (group->refItem == NULL) {
12234 /*
12235 * TODO: Should we raise a warning here?
12236 */
12237 /*
12238 * The referenced attribute group definition could not
12239 * be resolved beforehand, so skip.
12240 */
12241 attrs = attrs->next;
12242 continue;
12243 } else
12244 group = group->refItem;
12245 }
12246 /*
12247 * For every attribute group definition, an intersected wildcard
12248 * will be created (assumed that a wildcard exists on the
12249 * particular attr. gr. def. or on any contained attr. gr. def
12250 * at all).
12251 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12252 * that the intersection will be performed only once.
12253 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012254 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12255 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012256 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
12257 group->attributes, &group->attributeWildcard) == -1)
12258 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012259 }
12260 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
12261 }
12262 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012263 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012264 /*
12265 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012266 *
12267 * Although the complete wildcard might not correspond to any
12268 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012269 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012270 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12271 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12272 group->attributeWildcard->node);
Daniel Veillard50355f02004-06-08 17:52:16 +000012273 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
12274 completeWild, group->attributeWildcard) == -1)
12275 return (-1);
12276 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012277 (*completeWild)->node = group->attributeWildcard->node;
12278 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012279 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012280 }
12281 }
12282 attrs = attrs->next;
12283 }
12284
Daniel Veillard50355f02004-06-08 17:52:16 +000012285 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012286}
12287
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012288static int
12289xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12290 int *fixed,
12291 const xmlChar **value,
12292 xmlSchemaValPtr *val)
12293{
12294 *fixed = 0;
12295 *value = NULL;
12296 if (val != 0)
12297 *val = NULL;
12298
12299 if (item->defValue == NULL)
12300 item = item->refDecl;
12301
12302 if (item == NULL)
12303 return (0);
12304
12305 if (item->defValue != NULL) {
12306 *value = item->defValue;
12307 if (val != 0)
12308 *val = item->defVal;
12309 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12310 *fixed = 1;
12311 return (1);
12312 }
12313 return (0);
12314}
Daniel Veillard3646d642004-06-02 19:19:14 +000012315/**
12316 * xmlSchemaMatchesWildcardNs:
12317 * @wild: the wildcard
12318 * @ns: the namespace
12319 *
12320 *
12321 * Returns 1 if the given namespace matches the wildcard,
12322 * 0 otherwise.
12323 */
12324static int
12325xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
12326{
12327 if (wild == NULL)
12328 return(0);
12329
12330 if (wild->any)
12331 return(1);
12332 else if (wild->nsSet != NULL) {
12333 xmlSchemaWildcardNsPtr cur;
12334
12335 cur = wild->nsSet;
12336 while (cur != NULL) {
12337 if (xmlStrEqual(cur->value, ns))
12338 return(1);
12339 cur = cur->next;
12340 }
12341 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
12342 (!xmlStrEqual(wild->negNsSet->value, ns)))
12343 return(1);
12344
12345 return(0);
12346}
12347
12348/**
12349 * xmlSchemaBuildAttributeValidation:
12350 * @ctxt: the schema parser context
12351 * @type: the complex type definition
12352 *
12353 *
12354 * Builds the wildcard and the attribute uses on the given complex type.
12355 * Returns -1 if an internal error occurs, 0 otherwise.
12356 */
12357static int
12358xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
12359{
12360 xmlSchemaTypePtr baseType = NULL;
12361 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000012362 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012363 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012364 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000012365 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012366 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012367 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012368
Daniel Veillard01fa6152004-06-29 17:04:39 +000012369 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012370 /*
12371 * Complex Type Definition with complex content Schema Component.
12372 *
12373 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012374 * TODO: Add checks for absent referenced attribute declarations and
12375 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012376 */
12377 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012378 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012379 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000012380 "attribute uses already builded.\n",
12381 NULL, NULL);
12382 return (-1);
12383 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012384 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012385 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012386 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012387 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012388 type->name, NULL);
12389 return (-1);
12390 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012391 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012392 if (baseType == anyType)
12393 baseIsAnyType = 1;
12394 /*
12395 * Inherit the attribute uses of the base type.
12396 */
12397 /*
12398 * NOTE: It is allowed to "extend" the anyType complex type.
12399 */
12400 if (!baseIsAnyType) {
12401 if (baseType != NULL) {
12402 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
12403 tmp = (xmlSchemaAttributeLinkPtr)
12404 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12405 if (tmp == NULL) {
12406 xmlSchemaPErrMemory(ctxt,
12407 "building attribute uses of complexType", NULL);
12408 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012409 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012410 tmp->attr = cur->attr;
12411 tmp->next = NULL;
12412 if (type->attributeUses == NULL) {
12413 type->attributeUses = tmp;
12414 } else
12415 lastBaseUse->next = tmp;
12416 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012417 }
12418 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012419 }
12420 if ((type->subtypes != NULL) &&
12421 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
12422 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012423 /*
12424 * type --> (<simpleContent>|<complexContent>)
12425 * --> (<restriction>|<extension>) --> attributes
12426 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012427 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012428 } else {
12429 /* Short hand form of the complexType. */
12430 attrs = type->attributes;
12431 }
12432 /*
12433 * Handle attribute wildcards.
12434 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012435 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
12436 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012437 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012438 * NOTE: During the parse time, the wildcard is created on the complexType
12439 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012440 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012441 if (err == -1) {
12442 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
12443 "Internal error: xmlSchemaBuildAttributeValidation: "
12444 "failed to build an intersected attribute wildcard.\n",
12445 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012446 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012447 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012448
12449 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12450 ((baseIsAnyType) ||
12451 ((baseType != NULL) &&
12452 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12453 (baseType->attributeWildcard != NULL)))) {
12454 if (type->attributeWildcard != NULL) {
12455 /*
12456 * Union the complete wildcard with the base wildcard.
12457 */
12458 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
12459 baseType->attributeWildcard) == -1)
12460 return (-1);
12461 } else {
12462 /*
12463 * Just inherit the wildcard.
12464 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012465 /*
12466 * NOTE: This is the only case where an attribute
12467 * wildcard is shared.
12468 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012469 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012470 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012471 }
12472
12473 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12474 if (type->attributeWildcard != NULL) {
12475 /*
12476 * Derivation Valid (Restriction, Complex)
12477 * 4.1 The {base type definition} must also have one.
12478 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012479 if (baseType->attributeWildcard == NULL) {
12480 xmlSchemaPCustomErr(ctxt,
12481 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
12482 NULL, type, NULL,
12483 "The type has an attribute wildcard, "
12484 "but the base type %s does not have one",
12485 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12486 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012487 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012488 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012489 type->attributeWildcard, baseType->attributeWildcard) == 0) {
12490 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012491 xmlSchemaPCustomErr(ctxt,
12492 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
12493 NULL, type, NULL,
12494 "The attribute wildcard is not a valid "
12495 "subset of the wildcard in the base type %s",
12496 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12497 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012498 return (1);
12499 }
12500 /* 4.3 Unless the {base type definition} is the ·ur-type
12501 * definition·, the complex type definition's {attribute
12502 * wildcard}'s {process contents} must be identical to or
12503 * stronger than the {base type definition}'s {attribute
12504 * wildcard}'s {process contents}, where strict is stronger
12505 * than lax is stronger than skip.
12506 */
12507 if ((type->baseType != anyType) &&
12508 (type->attributeWildcard->processContents <
12509 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012510 xmlSchemaPCustomErr(ctxt,
12511 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
12512 NULL, type, NULL,
12513 "The 'process contents' of the attribute wildcard is weaker than "
12514 "the one in the base type %s",
12515 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12516 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012517 return (1);
12518 }
12519 }
12520 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12521 /*
12522 * Derivation Valid (Extension)
12523 * At this point the type and the base have both, either
12524 * no wildcard or a wildcard.
12525 */
12526 if ((baseType->attributeWildcard != NULL) &&
12527 (baseType->attributeWildcard != type->attributeWildcard)) {
12528 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012529 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012530 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012531 xmlSchemaPCustomErr(ctxt,
12532 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
12533 NULL, type, NULL,
12534 "The attribute wildcard is not a valid "
12535 "superset of the one in the base type %s",
12536 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12537 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012538 return (1);
12539 }
12540 }
12541 }
12542
Daniel Veillard3646d642004-06-02 19:19:14 +000012543 /*
12544 * Gather attribute uses defined by this type.
12545 */
12546 if (attrs != NULL) {
12547 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
12548 &uses, &lastUse) == -1) {
12549 return (-1);
12550 }
12551 }
12552 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
12553 * "Two distinct attribute declarations in the {attribute uses} must
12554 * not have identical {name}s and {target namespace}s."
12555 *
12556 * For "extension" this is done further down.
12557 */
12558 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
12559 cur = uses;
12560 while (cur != NULL) {
12561 tmp = cur->next;
12562 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012563 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12564 xmlSchemaGetAttrName(tmp->attr))) &&
12565 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
12566 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12567
12568 xmlSchemaPAttrUseErr(ctxt,
12569 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12570 NULL, type, NULL, cur->attr,
12571 "Duplicate attribute use %s specified",
12572 xmlSchemaFormatNsUriLocal(&str,
12573 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12574 xmlSchemaGetAttrName(tmp->attr))
12575 );
12576 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012577 break;
12578 }
12579 tmp = tmp->next;
12580 }
12581 cur = cur->next;
12582 }
12583 }
12584 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12585 /*
12586 * Derive by restriction.
12587 */
12588 if (baseIsAnyType) {
12589 type->attributeUses = uses;
12590 } else {
12591 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012592 const xmlChar *bEffValue;
12593 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012594
12595 cur = uses;
12596 while (cur != NULL) {
12597 found = 0;
12598 base = type->attributeUses;
12599 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012600 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12601 xmlSchemaGetAttrName(base->attr)) &&
12602 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
12603 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012604
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012605 found = 1;
12606
Daniel Veillard3646d642004-06-02 19:19:14 +000012607 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12608 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12609 /*
12610 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000012611 */
12612 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012613 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012614 NULL, type, NULL, cur->attr,
12615 "The 'optional' use is inconsistent with a matching "
12616 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012617 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12618 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12619 /*
12620 * derivation-ok-restriction 3
12621 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012622 xmlSchemaPCustomErr(ctxt,
12623 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12624 NULL, type, NULL,
12625 "A matching attribute use for the 'required' "
12626 "attribute use %s of the base type is missing",
12627 xmlSchemaFormatNsUriLocal(&str,
12628 xmlSchemaGetAttrTargetNsURI(base->attr),
12629 xmlSchemaGetAttrName(base->attr)));
12630 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012631 } else {
12632 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012633 * 2.1.3 [Definition:] Let the effective value
12634 * constraint of an attribute use be its {value
12635 * constraint}, if present, otherwise its {attribute
12636 * declaration}'s {value constraint} .
12637 */
12638 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
12639 &bEffValue, 0);
12640 /*
12641 * 2.1.3 ... one of the following must be true
12642 *
12643 * 2.1.3.1 B's ·effective value constraint· is
12644 * ·absent· or default.
12645 */
12646 if ((bEffValue != NULL) &&
12647 (effFixed == 1)) {
12648 const xmlChar *rEffValue = NULL;
12649
12650 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
12651 &rEffValue, 0);
12652 /*
12653 * 2.1.3.2 R's ·effective value constraint· is
12654 * fixed with the same string as B's.
12655 */
12656 if ((effFixed == 0) ||
12657 (! xmlStrEqual(rEffValue, bEffValue))) {
12658 xmlSchemaPAttrUseErr(ctxt,
12659 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12660 NULL, type, NULL, cur->attr,
12661 "The effective value constraint of the "
12662 "attribute use is inconsistent with "
12663 "its correspondent of the base type",
12664 NULL);
12665 }
12666 }
12667 /*
12668 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
12669 */
12670 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012671 * Override the attribute use.
12672 */
12673 base->attr = cur->attr;
12674 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012675
Daniel Veillard3646d642004-06-02 19:19:14 +000012676 break;
12677 }
12678 base = base->next;
12679 }
12680
12681 if (!found) {
12682 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12683 /*
12684 * derivation-ok-restriction 2.2
12685 */
12686 if ((type->attributeWildcard != NULL) &&
12687 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
12688 cur->attr->targetNamespace))
12689 found = 1;
12690
12691 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012692 xmlSchemaPAttrUseErr(ctxt,
12693 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12694 NULL, type, NULL, cur->attr,
12695 "Neither a matching attribute use, "
12696 "nor a matching wildcard in the base type does exist",
12697 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012698 } else {
12699 /*
12700 * Add the attribute use.
12701 *
12702 * Note that this may lead to funny derivation error reports, if
12703 * multiple equal attribute uses exist; but this is not
12704 * allowed anyway, and it will be reported beforehand.
12705 */
12706 tmp = cur;
12707 if (prev != NULL)
12708 prev->next = cur->next;
12709 else
12710 uses = cur->next;
12711 cur = cur->next;
12712 if (type->attributeUses == NULL) {
12713 type->attributeUses = tmp;
12714 } else
12715 lastBaseUse->next = tmp;
12716 lastBaseUse = tmp;
12717
12718 continue;
12719 }
12720 }
12721 }
12722 prev = cur;
12723 cur = cur->next;
12724 }
12725 if (uses != NULL)
12726 xmlSchemaFreeAttributeUseList(uses);
12727 }
12728 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12729 /*
12730 * The spec allows only appending, and not other kinds of extensions.
12731 *
12732 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
12733 */
12734 if (uses != NULL) {
12735 if (type->attributeUses == NULL) {
12736 type->attributeUses = uses;
12737 } else
12738 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012739 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012740 } else {
12741 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000012742 * Derive implicitely from the ur-type.
12743 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012744 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012745 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012746 /*
12747 * 3.4.6 -> Complex Type Definition Properties Correct
12748 */
12749 if (type->attributeUses != NULL) {
12750 cur = type->attributeUses;
12751 prev = NULL;
12752 while (cur != NULL) {
12753 /*
12754 * 4. Two distinct attribute declarations in the {attribute uses} must
12755 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012756 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012757 * Note that this was already done for "restriction" and types derived from
12758 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012759 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012760 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12761 tmp = cur->next;
12762 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012763 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12764 xmlSchemaGetAttrName(tmp->attr))) &&
12765 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
12766 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012767
Daniel Veillardc0826a72004-08-10 14:17:33 +000012768 xmlSchemaPAttrUseErr(ctxt,
12769 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12770 NULL, type, NULL, tmp->attr,
12771 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012772 break;
12773 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012774 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012775 }
12776 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012777 /*
12778 * 5. Two distinct attribute declarations in the {attribute uses} must
12779 * not have {type definition}s which are or are derived from ID.
12780 */
12781 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012782 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012783 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012784 xmlSchemaPAttrUseErr(ctxt,
12785 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12786 NULL, type, NULL, cur->attr,
12787 "There must not exist more than one attribute use, "
12788 "declared of type 'ID' or derived from it",
12789 NULL);
12790 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000012791 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012792 id = cur;
12793 }
12794 /*
12795 * Remove "prohibited" attribute uses. The reason this is done at this late
12796 * stage is to be able to catch dublicate attribute uses. So we had to keep
12797 * prohibited uses in the list as well.
12798 */
12799 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12800 tmp = cur;
12801 if (prev == NULL)
12802 type->attributeUses = cur->next;
12803 else
12804 prev->next = cur->next;
12805 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012806 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012807 } else {
12808 prev = cur;
12809 cur = cur->next;
12810 }
12811 }
12812 }
12813 /*
12814 * TODO: This check should be removed if we are 100% sure of
12815 * the base type attribute uses already being built.
12816 */
12817 if ((baseType != NULL) && (!baseIsAnyType) &&
12818 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012819 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012820 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012821 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012822 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000012823 baseType->name, NULL);
12824 }
12825 return (0);
12826}
12827
12828/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000012829 * xmlSchemaTypeFinalContains:
12830 * @schema: the schema
12831 * @type: the type definition
12832 * @final: the final
12833 *
12834 * Evaluates if a type definition contains the given "final".
12835 * This does take "finalDefault" into account as well.
12836 *
12837 * Returns 1 if the type does containt the given "final",
12838 * 0 otherwise.
12839 */
12840static int
12841xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
12842{
12843 int tfinal = final, tflags = type->flags;
12844
12845 if (type == NULL)
12846 return (0);
12847 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
12848 switch (final) {
12849 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
12850 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
12851 break;
12852 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
12853 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
12854 break;
12855 case XML_SCHEMAS_TYPE_FINAL_LIST:
12856 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
12857 break;
12858 case XML_SCHEMAS_TYPE_FINAL_UNION:
12859 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
12860 break;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000012861 default:
12862 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012863 }
12864 tflags = schema->flags;
12865 }
12866 if (tflags & tfinal)
12867 return (1);
12868 else
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000012869 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012870}
12871
12872/**
12873 * xmlSchemaGetUnionSimpleTypeMemberTypes:
12874 * @type: the Union Simple Type
12875 *
12876 * Returns a list of member types of @type if existing,
12877 * returns NULL otherwise.
12878 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012879static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000012880xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
12881{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012882 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012883 if (type->memberTypes != NULL)
12884 return (type->memberTypes);
12885 else
12886 type = type->baseType;
12887 }
12888 return (NULL);
12889}
12890
12891/**
12892 * xmlSchemaGetListSimpleTypeItemType:
12893 * @type: the simple type definition
12894 *
12895 * Returns the item type definition of the list simple type.
12896 */
12897static xmlSchemaTypePtr
12898xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
12899{
12900 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
12901 return (NULL);
12902 /*
12903 * Note: In libxml2, the built-in types do not reflect
12904 * the datatype hierarchy (yet?) - we have to treat them
12905 * in a special way.
12906 */
12907 if (type->type == XML_SCHEMA_TYPE_BASIC)
12908 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012909 return (type->subtypes);
12910}
12911
12912
12913static int
12914xmlSchemaGetParticleTotalRangeMin(xmlSchemaTreeItemPtr particle)
12915{
12916 if ((particle->children == NULL) ||
12917 ( ((xmlSchemaParticlePtr) particle)->minOccurs == 0))
12918 return (0);
12919 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
12920 int min = 0, cur;
12921 xmlSchemaTreeItemPtr part = particle->children->children;
12922
12923 if (part == NULL)
12924 return (0);
12925 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
12926 (part->children->type == XML_SCHEMA_TYPE_ANY))
12927 min = ((xmlSchemaParticlePtr) part)->minOccurs;
12928 else
12929 min = xmlSchemaGetParticleTotalRangeMin(part);
12930 if (min == 0)
12931 return (0);
12932 part = part->next;
12933 while (part != NULL) {
12934 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
12935 (part->children->type == XML_SCHEMA_TYPE_ANY))
12936 cur = ((xmlSchemaParticlePtr) part)->minOccurs;
12937 else
12938 cur = xmlSchemaGetParticleTotalRangeMin(part);
12939 if (cur == 0)
12940 return (0);
12941 if (min > cur)
12942 min = cur;
12943 part = part->next;
12944 }
12945 return (((xmlSchemaParticlePtr) particle)->minOccurs * min);
12946 } else {
12947 /* <all> and <sequence> */
12948 int sum = 0;
12949 xmlSchemaTreeItemPtr part = particle->children->children;
12950
12951 if (part == NULL)
12952 return (0);
12953 do {
12954 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
12955 (part->children->type == XML_SCHEMA_TYPE_ANY))
12956 sum += ((xmlSchemaParticlePtr) part)->minOccurs;
12957 else
12958 sum += xmlSchemaGetParticleTotalRangeMin(part);
12959 part = part->next;
12960 } while (part != NULL);
12961 return (((xmlSchemaParticlePtr) particle)->minOccurs * sum);
12962 }
12963}
12964
12965
12966static int
12967xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
12968{
12969 if ((particle == NULL) || (particle->minOccurs == 0) ||
12970 (particle->children == NULL))
12971 return (1);
12972
12973 if (IS_MODEL_GROUP(particle->children)) {
12974 if (xmlSchemaGetParticleTotalRangeMin(
12975 (xmlSchemaTreeItemPtr) particle) == 0)
12976 return (1);
12977 }
12978 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012979}
12980
12981/**
12982 * xmlSchemaCheckCOSSTDerivedOK:
12983 * @type: the derived simple type definition
12984 * @baseType: the base type definition
12985 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000012986 * Schema Component Constraint:
12987 * Type Derivation OK (Simple) (cos-st-derived-OK)
12988 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000012989 * Checks wheter @type can be validly
12990 * derived from @baseType.
12991 *
12992 * Returns 0 on success, an positive error code otherwise.
12993 */
12994static int
12995xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
12996 xmlSchemaTypePtr type,
12997 xmlSchemaTypePtr baseType,
12998 int subset)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000012999{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013000 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013001 * 1 They are the same type definition.
13002 * TODO: The identy check might have to be more complex than this.
13003 */
13004 if (type == baseType)
13005 return (0);
13006 /*
13007 * 2.1 restriction is not in the subset, or in the {final}
13008 * of its own {base type definition};
13009 */
13010 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
13011 (xmlSchemaTypeFinalContains(schema,
13012 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13013 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
13014 }
13015 /* 2.2 */
13016 if (type->baseType == baseType) {
13017 /*
13018 * 2.2.1 D's ·base type definition· is B.
13019 */
13020 return (0);
13021 }
13022 /*
13023 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13024 * and is validly derived from B given the subset, as defined by this
13025 * constraint.
13026 */
13027 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
13028 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
13029 return (0);
13030 }
13031 /*
13032 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
13033 * definition·.
13034 */
13035 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
13036 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
13037 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
13038 return (0);
13039 }
13040 /*
13041 * 2.2.4 B's {variety} is union and D is validly derived from a type
13042 * definition in B's {member type definitions} given the subset, as
13043 * defined by this constraint.
13044 *
13045 * NOTE: This seems not to involve built-in types, since there is no
13046 * built-in Union Simple Type.
13047 */
13048 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13049 xmlSchemaTypeLinkPtr cur;
13050
13051 cur = baseType->memberTypes;
13052 while (cur != NULL) {
13053 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
13054 cur->type, subset) == 0)
13055 return (0);
13056 cur = cur->next;
13057 }
13058 }
13059
13060 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13061}
13062
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013063/**
13064 * xmlSchemaCheckTypeDefCircularInternal:
13065 * @pctxt: the schema parser context
13066 * @ctxtType: the type definition
13067 * @ancestor: an ancestor of @ctxtType
13068 *
13069 * Checks st-props-correct (2) + ct-props-correct (3).
13070 * Circular type definitions are not allowed.
13071 *
13072 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13073 * circular, 0 otherwise.
13074 */
13075static int
13076xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13077 xmlSchemaTypePtr ctxtType,
13078 xmlSchemaTypePtr ancestor)
13079{
13080 int ret;
13081
13082 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13083 return (0);
13084
13085 if (IS_NOT_TYPEFIXED(ancestor))
13086 xmlSchemaTypeFixup(ancestor, pctxt, NULL);
13087 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13088 /*
13089 * Avoid inifinite recursion on circular types not yet checked.
13090 */
13091 return (0);
13092 }
13093 if (ctxtType == ancestor) {
13094 xmlSchemaPCustomErr(pctxt,
13095 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13096 NULL, ctxtType, GET_NODE(ctxtType),
13097 "The definition is circular", NULL);
13098 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13099 }
13100 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13101 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13102 ancestor->baseType);
13103 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13104 return (ret);
13105}
13106
13107/**
13108 * xmlSchemaCheckGroupDefCircular:
13109 * @item: the complex/simple type definition
13110 * @ctxt: the parser context
13111 * @name: the name
13112 *
13113 * Checks for circular type definitions.
13114 */
13115static void
13116xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
13117 xmlSchemaParserCtxtPtr ctxt,
13118 const xmlChar * name ATTRIBUTE_UNUSED)
13119{
13120 if ((item == NULL) ||
13121 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13122 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13123 return;
13124 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13125
13126}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013127
13128/**
13129 * xmlSchemaCheckSTPropsCorrect:
13130 * @ctxt: the schema parser context
13131 * @type: the simple type definition
13132 *
13133 * Checks st-props-correct.
13134 *
13135 * Returns 0 if the properties are correct,
13136 * if not, a positive error code and -1 on internal
13137 * errors.
13138 */
13139static int
13140xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
13141 xmlSchemaTypePtr type)
13142{
13143 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13144 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013145 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013146
Daniel Veillardc0826a72004-08-10 14:17:33 +000013147 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013148 /*
13149 * Schema Component Constraint: Simple Type Definition Properties Correct
13150 *
13151 * NOTE: This is somehow redundant, since we actually built a simple type
13152 * to have all the needed information; this acts as an self test.
13153 */
13154 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13155 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013156 /* Base type: If the datatype has been ·derived· by ·restriction·
13157 * then the Simple Type Definition component from which it is ·derived·,
13158 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
13159 */
13160 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013161 /*
13162 * TODO: Think about: "modulo the impact of Missing
13163 * Sub-components (§5.3)."
13164 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013165 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013166 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013167 NULL, type, NULL,
13168 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013169 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013170
Daniel Veillard01fa6152004-06-29 17:04:39 +000013171 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013172 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013173 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013174 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013175 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013176 "The base type '%s' is not a simple type",
13177 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013178 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013179 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13180 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013181 if ((baseType->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
13182 ((type->flags &
13183 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13184 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
13185 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013186 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013187 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013188 NULL, type, NULL,
13189 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013190 "the simple ur-type definition as base type, not '%s'",
13191 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013192 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013193 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13194 }
13195 /*
13196 * Variety: One of {atomic, list, union}.
13197 */
13198 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13199 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
13200 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013201 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013202 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013203 NULL, type, NULL,
13204 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013205 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13206 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013207 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013208
13209 /*
13210 * 3 The {final} of the {base type definition} must not contain restriction.
13211 */
13212 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
13213 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13214 xmlSchemaPCustomErr(ctxt,
13215 XML_SCHEMAP_ST_PROPS_CORRECT_3,
13216 NULL, type, NULL,
13217 "The 'final' of its base type '%s' must not contain "
13218 "'restriction'",
13219 xmlSchemaGetComponentQName(&str, baseType));
13220 FREE_AND_NULL(str)
13221 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
13222 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013223
13224 /*
13225 * 2 All simple type definitions must be derived ultimately from the ·simple
13226 * ur-type definition (so· circular definitions are disallowed). That is, it
13227 * must be possible to reach a built-in primitive datatype or the ·simple
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013228 * ur-type definition· by repeatedly following the {base type definition}.
13229 *
13230 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013231 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013232 return (0);
13233}
13234
13235/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013236 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013237 * @ctxt: the schema parser context
13238 * @type: the simple type definition
13239 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013240 * Schema Component Constraint:
13241 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13242
13243 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013244 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013245 *
13246 * Returns -1 on internal errors, 0 if the type is validly derived,
13247 * a positive error code otherwise.
13248 */
13249static int
13250xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013251 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013252{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013253 xmlChar *str = NULL;
13254
Daniel Veillard01fa6152004-06-29 17:04:39 +000013255 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
13256 xmlSchemaPErr(ctxt, type->node,
13257 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013258 "xmlSchemaCheckCOSSTRestricts: The given "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013259 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013260 type->name, NULL);
13261 return (-1);
13262 }
13263
13264 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
13265 xmlSchemaTypePtr primitive;
13266 /*
13267 * 1.1 The {base type definition} must be an atomic simple
13268 * type definition or a built-in primitive datatype.
13269 */
13270 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013271 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013272 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013273 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013274 "The base type '%s' is not an atomic simple type",
13275 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013276 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013277 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13278 }
13279 /* 1.2 The {final} of the {base type definition} must not contain
13280 * restriction.
13281 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013282 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013283 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13284 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013285 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013286 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013287 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013288 "The final of its base type '%s' must not contain 'restriction'",
13289 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013290 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013291 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13292 }
13293
13294 /*
13295 * 1.3.1 DF must be an allowed constraining facet for the {primitive
13296 * type definition}, as specified in the appropriate subsection of 3.2
13297 * Primitive datatypes.
13298 */
13299 if (type->facets != NULL) {
13300 xmlSchemaFacetPtr facet;
13301 int ok = 1;
13302
13303 primitive = xmlSchemaGetPrimitiveType(type);
13304 if (primitive == NULL) {
13305 xmlSchemaPErr(ctxt, type->node,
13306 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013307 "xmlSchemaCheckCOSSTRestricts: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013308 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013309 type->name, NULL);
13310 return (-1);
13311 }
13312 facet = type->facets;
13313 do {
13314 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013315 ok = 0;
13316 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013317 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013318 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013319 }
13320 facet = facet->next;
13321 } while (facet != NULL);
13322 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013323 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013324 }
13325 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013326 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13327 * of the {base type definition} (call this BF),then the DF's {value}
13328 * must be a valid restriction of BF's {value} as defined in
13329 * [XML Schemas: Datatypes]."
13330 *
13331 * NOTE (1.3.2) Facet derivation constraints are currently handled in
13332 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013333 */
13334 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13335 xmlSchemaTypePtr itemType = NULL;
13336
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013337 itemType = type->subtypes;
13338 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013339 xmlSchemaPErr(ctxt, type->node,
13340 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013341 "Internal error: xmlSchemaCheckCOSSTRestricts: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013342 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013343 type->name, NULL);
13344 return (-1);
13345 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013346 if (IS_NOT_TYPEFIXED(itemType))
13347 xmlSchemaTypeFixup(itemType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013348 /*
13349 * 2.1 The {item type definition} must have a {variety} of atomic or
13350 * union (in which case all the {member type definitions}
13351 * must be atomic).
13352 */
13353 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13354 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013355 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013356 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013357 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013358 "The item type '%s' does not have a variety of atomic or union",
13359 xmlSchemaGetComponentQName(&str, itemType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013360 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013361 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13362 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13363 xmlSchemaTypeLinkPtr member;
13364
13365 member = itemType->memberTypes;
13366 while (member != NULL) {
13367 if ((member->type->flags &
13368 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013369 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013370 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013371 NULL, type, NULL,
13372 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013373 "member type '%s' of this item type is not atomic",
13374 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013375 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013376 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13377 }
13378 member = member->next;
13379 }
13380 }
13381
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013382 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013383 xmlSchemaFacetPtr facet;
13384 /*
13385 * This is the case if we have: <simpleType><list ..
13386 */
13387 /*
13388 * 2.3.1
13389 * 2.3.1.1 The {final} of the {item type definition} must not
13390 * contain list.
13391 */
13392 if (xmlSchemaTypeFinalContains(ctxt->schema,
13393 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013394 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013395 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013396 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013397 "The final of its item type '%s' must not contain 'list'",
13398 xmlSchemaGetComponentQName(&str, itemType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013399 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013400 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13401 }
13402 /*
13403 * 2.3.1.2 The {facets} must only contain the whiteSpace
13404 * facet component.
13405 */
13406 if (type->facets != NULL) {
13407 facet = type->facets;
13408 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013409 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13410 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013411 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013412 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013413 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13414 }
13415 facet = facet->next;
13416 } while (facet != NULL);
13417 }
13418 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013419 * MABY TODO: (Hmm, not really) Datatypes states:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013420 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13421 * whose ·lexical space· allows space (such as string or anyURI)or
13422 * a ·union· datatype any of whose {member type definitions}'s
13423 * ·lexical space· allows space.
13424 */
13425 } else {
13426 /*
13427 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013428 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013429 */
13430 /*
13431 * 2.3.2
13432 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13433 */
13434 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013435 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013436 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013437 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013438 "The base type '%s' must be a list type",
13439 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013440 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013441 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13442 }
13443 /*
13444 * 2.3.2.2 The {final} of the {base type definition} must not
13445 * contain restriction.
13446 */
13447 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13448 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013449 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013450 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013451 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013452 "The 'final' of the base type '%s' must not contain 'restriction'",
13453 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013454 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013455 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13456 }
13457 /*
13458 * 2.3.2.3 The {item type definition} must be validly derived
13459 * from the {base type definition}'s {item type definition} given
13460 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13461 */
13462 {
13463 xmlSchemaTypePtr baseItemType;
13464
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013465 baseItemType = type->baseType->subtypes;
13466 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013467 xmlSchemaPErr(ctxt, type->node,
13468 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013469 "Internal error: xmlSchemaCheckCOSSTRestricts, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013470 "List simple type '%s': Failed to "
13471 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013472 type->name, type->baseType->name);
13473 return (-1);
13474 }
13475 if ((itemType != baseItemType) &&
13476 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
13477 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013478 xmlChar *strBIT = NULL, *strBT = NULL;
13479 xmlSchemaPCustomErrExt(ctxt,
13480 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
13481 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013482 "The item type '%s' is not validly derived from the "
13483 "item type '%s' of the base type '%s'",
13484 xmlSchemaGetComponentQName(&str, itemType),
13485 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13486 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013487
13488 FREE_AND_NULL(str)
13489 FREE_AND_NULL(strBIT)
13490 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013491 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13492 }
13493 }
13494
13495 if (type->facets != NULL) {
13496 xmlSchemaFacetPtr facet;
13497 int ok = 1;
13498 /*
13499 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
13500 * and enumeration facet components are allowed among the {facets}.
13501 */
13502 facet = type->facets;
13503 do {
13504 switch (facet->type) {
13505 case XML_SCHEMA_FACET_LENGTH:
13506 case XML_SCHEMA_FACET_MINLENGTH:
13507 case XML_SCHEMA_FACET_MAXLENGTH:
13508 case XML_SCHEMA_FACET_WHITESPACE:
13509 /*
13510 * TODO: 2.5.1.2 List datatypes
13511 * The value of ·whiteSpace· is fixed to the value collapse.
13512 */
13513 case XML_SCHEMA_FACET_PATTERN:
13514 case XML_SCHEMA_FACET_ENUMERATION:
13515 break;
13516 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013517 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013518 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013519 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013520 /*
13521 * We could return, but it's nicer to report all
13522 * invalid facets.
13523 */
13524 ok = 0;
13525 }
13526 }
13527 facet = facet->next;
13528 } while (facet != NULL);
13529 if (ok == 0)
13530 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13531 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013532 * SPEC (2.3.2.5) (same as 1.3.2)
13533 *
13534 * NOTE (2.3.2.5) This is currently done in
13535 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013536 */
13537 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013538 }
13539 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13540 /*
13541 * 3.1 The {member type definitions} must all have {variety} of
13542 * atomic or list.
13543 */
13544 xmlSchemaTypeLinkPtr member;
13545
13546 member = type->memberTypes;
13547 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013548 if (IS_NOT_TYPEFIXED(member->type))
13549 xmlSchemaTypeFixup(member->type, ctxt, NULL);
13550
Daniel Veillard01fa6152004-06-29 17:04:39 +000013551 if (((member->type->flags &
13552 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13553 ((member->type->flags &
13554 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013555 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013556 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013557 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013558 "The member type '%s' is neither an atomic, nor a list type",
13559 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013560 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013561 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13562 }
13563 member = member->next;
13564 }
13565 /*
13566 * 3.3.1 If the {base type definition} is the ·simple ur-type
13567 * definition·
13568 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013569 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013570 /*
13571 * 3.3.1.1 All of the {member type definitions} must have a
13572 * {final} which does not contain union.
13573 */
13574 member = type->memberTypes;
13575 while (member != NULL) {
13576 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
13577 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013578 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013579 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013580 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013581 "The 'final' of member type '%s' contains 'union'",
13582 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013583 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013584 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13585 }
13586 member = member->next;
13587 }
13588 /*
13589 * 3.3.1.2 The {facets} must be empty.
13590 */
13591 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013592 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013593 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013594 NULL, type, NULL,
13595 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013596 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13597 }
13598 } else {
13599 /*
13600 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013601 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013602 */
13603 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013604 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013605 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013606 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013607 "The base type '%s' is not a union type",
13608 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013609 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013610 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13611 }
13612 /*
13613 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13614 */
13615 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13616 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013617 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013618 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013619 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013620 "The 'final' of its base type '%s' must not contain 'restriction'",
13621 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013622 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013623 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13624 }
13625 /*
13626 * 3.3.2.3 The {member type definitions}, in order, must be validly
13627 * derived from the corresponding type definitions in the {base
13628 * type definition}'s {member type definitions} given the empty set,
13629 * as defined in Type Derivation OK (Simple) (§3.14.6).
13630 */
13631 {
13632 xmlSchemaTypeLinkPtr baseMember;
13633
13634 /*
13635 * OPTIMIZE: if the type is restricting, it has no local defined
13636 * member types and inherits the member types of the base type;
13637 * thus a check for equality can be skipped.
13638 */
13639 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013640 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000013641 * union simple type can have other member types as the member
13642 * types of it's base type. This check seems not necessary with
13643 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013644 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013645 */
13646 if (type->memberTypes != NULL) {
13647 member = type->memberTypes;
13648 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
13649 if ((member == NULL) && (baseMember != NULL)) {
13650 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013651 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013652 "Internal error: xmlSchemaCheckCOSSTRestricts, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013653 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013654 "of member types in the base type\n",
13655 type->name, NULL);
13656 }
13657 while (member != NULL) {
13658 if (baseMember == NULL) {
13659 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013660 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013661 "Internal error: "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013662 "xmlSchemaCheckCOSSTRestricts "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013663 "(3.3.2.3), union simple type '%s', unequal number "
13664 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013665 type->name, NULL);
13666 }
13667 if ((member->type != baseMember->type) &&
13668 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
13669 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013670 xmlChar *strBMT = NULL, *strBT = NULL;
13671
13672 xmlSchemaPCustomErrExt(ctxt,
13673 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13674 NULL, type, NULL,
13675 "The member type %s is not validly derived from its "
13676 "corresponding member type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013677 xmlSchemaGetComponentQName(&str, member->type),
13678 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13679 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013680 FREE_AND_NULL(str)
13681 FREE_AND_NULL(strBMT)
13682 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013683 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
13684 }
13685 member = member->next;
13686 baseMember = baseMember->next;
13687 }
13688 }
13689 }
13690 /*
13691 * 3.3.2.4 Only pattern and enumeration facet components are
13692 * allowed among the {facets}.
13693 */
13694 if (type->facets != NULL) {
13695 xmlSchemaFacetPtr facet;
13696 int ok = 1;
13697
13698 facet = type->facets;
13699 do {
13700 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13701 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013702 xmlSchemaPIllegalFacetListUnionErr(ctxt,
13703 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
13704 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013705 ok = 0;
13706 }
13707 facet = facet->next;
13708 } while (facet != NULL);
13709 if (ok == 0)
13710 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
13711
13712 }
13713 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013714 * SPEC (3.3.2.5) (same as 1.3.2)
13715 *
13716 * NOTE (3.3.2.5) This is currently done in
13717 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013718 */
13719 }
13720 }
13721
13722 return (0);
13723}
13724
13725/**
13726 * xmlSchemaCheckSRCSimpleType:
13727 * @ctxt: the schema parser context
13728 * @type: the simple type definition
13729 *
13730 * Checks crc-simple-type constraints.
13731 *
13732 * Returns 0 if the constraints are satisfied,
13733 * if not a positive error code and -1 on internal
13734 * errors.
13735 */
13736static int
13737xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
13738 xmlSchemaTypePtr type)
13739{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013740 /*
13741 * src-simple-type.1 The corresponding simple type definition, if any,
13742 * must satisfy the conditions set out in Constraints on Simple Type
13743 * Definition Schema Components (§3.14.6).
13744 */
13745 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
13746 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
13747 /*
13748 * TODO: Removed this, since it got annoying to get an
13749 * extra error report, if anything failed until now.
13750 * Enable this if needed.
13751 */
13752 /*
13753 xmlSchemaPErr(ctxt, type->node,
13754 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013755 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013756 "on simple type definitions.\n",
13757 type->name, NULL);
13758 */
13759 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
13760 }
13761
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013762 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013763 /*
13764 * src-simple-type.2 If the <restriction> alternative is chosen,
13765 * either it must have a base [attribute] or a <simpleType> among its
13766 * [children], but not both.
13767 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013768 /*
13769 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013770 * NOTE: This is checked in the parse function of <restriction>.
William M. Brack2f2a6632004-08-20 23:09:47 +000013771 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013772 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013773 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
13774 * an itemType [attribute] or a <simpleType> among its [children],
13775 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013776 *
13777 * REMOVED: This is checked in the parse function of <list>.
13778 */
13779 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013780 xmlSchemaTypeLinkPtr member;
13781 xmlSchemaTypePtr ancestor, anySimpleType;
13782
13783 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13784
13785 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
13786 * the <union> alternative is chosen, there must not be any entries
13787 * in the memberTypes [attribute] at any depth which resolve to the
13788 * component corresponding to the <simpleType>.
13789 */
13790 member = type->memberTypes;
13791 while (member != NULL) {
13792 ancestor = member->type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013793 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
13794 if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013795 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013796 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013797 NULL, type, NULL,
13798 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013799 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013800 }
13801 if (IS_NOT_TYPEFIXED(ancestor))
13802 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
13803 if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013804 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013805 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000013806 * type as item type, which in turn has a list ST as member
13807 * type, we will assume this here as well, since this check
13808 * was not yet performed.
13809 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013810 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013811
Daniel Veillard01fa6152004-06-29 17:04:39 +000013812 ancestor = ancestor->baseType;
13813 }
13814 member = member->next;
13815 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013816 }
13817
13818 return (0);
13819}
13820
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013821#if 0 /* Not yet used code for ST schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000013822static int
13823xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
13824 const xmlChar * value,
13825 xmlSchemaTypePtr type,
13826 int fireErrors)
13827{
13828 int ret;
13829 /*
13830 * 3.14.4 Simple Type Definition Validation Rules
13831 * Validation Rule: String Valid
13832 */
13833 /*
13834 * 1 It is schema-valid with respect to that definition as defined
13835 * by Datatype Valid in [XML Schemas: Datatypes].
13836 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013837 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
13838 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000013839 return (ret);
13840 /*
13841 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
13842 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
13843 * the string must be a ·declared entity name·.
13844 */
13845 /*
13846 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
13847 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
13848 * then every whitespace-delimited substring of the string must be a ·declared
13849 * entity name·.
13850 */
13851 /*
13852 * 2.3 otherwise no further condition applies.
13853 */
13854
13855 return (0);
13856}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013857#endif
13858
William M. Brack2f2a6632004-08-20 23:09:47 +000013859
13860static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013861xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
13862{
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000013863 if (vctxt->pctxt == NULL) {
13864 if (vctxt->schema != NULL)
13865 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
13866 else
13867 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013868 if (vctxt->pctxt == NULL) {
13869 xmlSchemaVErr(vctxt, NULL,
13870 XML_SCHEMAV_INTERNAL,
13871 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
13872 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000013873 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013874 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013875 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013876 /* TODO: Pass user data. */
13877 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
13878 }
13879 return (0);
13880}
13881
13882static int
13883xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
13884{
13885 if (ctxt->vctxt == NULL) {
13886 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
13887 if (ctxt->vctxt == NULL) {
13888 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013889 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013890 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
13891 "failed to create a temp. validation context.\n",
13892 NULL, NULL);
13893 return (-1);
13894 }
13895 /* TODO: Pass user data. */
13896 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
13897 }
13898 return (0);
13899}
13900
13901/**
13902 * xmlSchemaCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013903 * @pctxt: the schema parser context
13904 * @vctxt: the temporary schema validation context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013905 * @type: the simple type definition
13906 * @value: the default value
13907 * @node: an optional node (the holder of the value)
13908 *
13909 * Checks the "cos-valid-default" constraints.
13910 *
13911 * Returns 0 if the constraints are satisfied,
13912 * if not, a positive error code and -1 on internal
13913 * errors.
13914 */
13915static int
13916xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
13917 xmlSchemaValidCtxtPtr vctxt,
13918 xmlSchemaTypePtr type,
13919 const xmlChar *value,
13920 xmlNodePtr node)
13921{
13922 int ret = 0;
13923
13924 /*
13925 * cos-valid-default:
13926 * Schema Component Constraint: Element Default Valid (Immediate)
13927 * For a string to be a valid default with respect to a type
13928 * definition the appropriate case among the following must be true:
13929 */
13930 /*
13931 * NOTE: This has to work without a given node (the holder of the
13932 * value), since it should work on the component, i.e. an underlying
13933 * DOM must not be mandatory.
13934 */
13935 if ((pctxt == NULL) || (vctxt == NULL)) {
13936 xmlSchemaPErr(pctxt, node,
13937 XML_SCHEMAP_INTERNAL,
13938 "Internal error: xmlSchemaCheckCOSValidDefault, "
13939 "bad arguments: the parser and/or validation context is "
13940 "missing.\n",
13941 NULL, NULL);
13942 return (-1);
13943 }
13944 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013945 /*
13946 * Complex type.
13947 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013948 * SPEC (2.1) "its {content type} must be a simple type definition
13949 * or mixed."
13950 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
13951 * type}'s particle must be ·emptiable· as defined by
13952 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000013953 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013954 if ((! HAS_SIMPLE_CONTENT(type)) &&
13955 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
13956 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013957 xmlSchemaPSimpleTypeErr(pctxt,
13958 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
13959 NULL, NULL, node,
13960 type, NULL, NULL,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013961 "For a string to be a valid default, the type definition "
13962 "must be a simple type or a complex type with mixed content "
13963 "and a particle emptiable",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013964 NULL, NULL);
13965 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
13966 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013967 }
13968 /*
13969 * 1 If the type definition is a simple type definition, then the string
13970 * must be ·valid· with respect to that definition as defined by String
13971 * Valid (§3.14.4).
13972 *
13973 * AND
13974 *
13975 * 2.2.1 If the {content type} is a simple type definition, then the
13976 * string must be ·valid· with respect to that simple type definition
13977 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013978 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013979 vctxt->node = node;
13980 vctxt->cur = NULL;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013981 if (IS_SIMPLE_TYPE(type))
13982 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value,
13983 1, 1, 1, 0);
13984 else if (HAS_SIMPLE_CONTENT(type))
13985 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type->contentTypeDef,
13986 value, 1, 1, 1, 0);
13987 else
13988 return (ret);
13989
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013990 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
13991 if (ret < 0) {
13992 xmlSchemaPErr(pctxt, node,
13993 /* NOTNICE: error code: This function will be used during
13994 * schema construction and xsi:type validation.
13995 */
13996 XML_SCHEMAP_INTERNAL,
13997 "Internal error: xmlSchemaCheckCOSValidDefault, "
13998 "while validating a value constaint value.\n",
13999 NULL, NULL);
14000
14001 }
14002 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014003}
14004
14005/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014006 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014007 * @ctxt: the schema parser context
14008 * @type: the complex type definition
14009 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014010 *.(4.6) Constraints on Complex Type Definition Schema Components
14011 * Schema Component Constraint:
14012 * Complex Type Definition Properties Correct (ct-props-correct)
14013 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014014 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014015 * Returns 0 if the constraints are satisfied, a positive
14016 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014017 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014018static int
14019xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14020 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014021{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014022 /*
14023 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14024 *
14025 * SPEC (1) "The values of the properties of a complex type definition must
14026 * be as described in the property tableau in The Complex Type Definition
14027 * Schema Component (§3.4.1), modulo the impact of Missing
14028 * Sub-components (§5.3)."
14029 */
14030 if ((type->baseType != NULL) &&
14031 (IS_SIMPLE_TYPE(type->baseType)) &&
14032 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14033 /*
14034 * SPEC (2) "If the {base type definition} is a simple type definition,
14035 * the {derivation method} must be extension."
14036 */
14037 xmlSchemaPCustomErr(pctxt,
14038 XML_SCHEMAP_SRC_CT_1,
14039 NULL, type, NULL,
14040 "If the base type is a simple type, the derivation method must be "
14041 "'extension'", NULL);
14042 return (XML_SCHEMAP_SRC_CT_1);
14043 }
14044 /*
14045 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14046 * definition·. That is, it must be possible to reach the ·ur-type
14047 * definition by repeatedly following the {base type definition}."
14048 *
14049 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14050 *
14051 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
14052 * must not have identical {name}s and {target namespace}s."
14053 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14054 * must not have {type definition}s which are or are derived from ID."
14055 *
14056 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14057 */
14058 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014059}
14060
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014061static int
14062xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14063 xmlSchemaTypePtr typeB)
14064{
14065 /*
14066 * TODO: This should implement component-identity
14067 * in the future.
14068 */
14069 if ((typeA == NULL) || (typeB == NULL))
14070 return (0);
14071 return (typeA == typeB);
14072}
14073
14074/**
14075 * xmlSchemaCheckCOSCTExtends:
14076 * @ctxt: the schema parser context
14077 * @derivedType: the to-be derived complex type definition
14078 * @baseType: the base complex type definition
14079 * @subset: the given subset
14080 *
14081 * Schema Component Constraint:
14082 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14083 *
14084 * STATUS: completed
14085 *
14086 * Returns 0 if the constraints are satisfied, or 1
14087 * if not.
14088 */
14089static int
14090xmlSchemaCheckCOSCTDerivedOK(xmlSchemaPtr schema,
14091 xmlSchemaTypePtr type,
14092 xmlSchemaTypePtr baseType,
14093 int set)
14094{
14095 int equal = xmlSchemaAreEqualTypes(type, baseType);
14096 /* TODO: Error codes. */
14097 /*
14098 * SPEC "For a complex type definition (call it D, for derived)
14099 * to be validly derived from a type definition (call this
14100 * B, for base) given a subset of {extension, restriction}
14101 * all of the following must be true:"
14102 */
14103 if (! equal) {
14104 /*
14105 * SPEC (1) "If B and D are not the same type definition, then the
14106 * {derivation method} of D must not be in the subset."
14107 */
14108 if (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
14109 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
14110 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
14111 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
14112 return (0);
14113 } else {
14114 /*
14115 * SPEC (2.1) "B and D must be the same type definition."
14116 */
14117 return (1);
14118 }
14119 /*
14120 * SPEC (2.2) "B must be D's {base type definition}."
14121 */
14122 if (type->baseType == baseType)
14123 return (1);
14124 /*
14125 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14126 * definition·."
14127 */
14128 if (IS_ANYTYPE(type->baseType))
14129 return (0);
14130
14131 if (IS_COMPLEX_TYPE(type->baseType)) {
14132 /*
14133 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14134 * must be validly derived from B given the subset as defined by this
14135 * constraint."
14136 */
14137 return (xmlSchemaCheckCOSCTDerivedOK(schema, type->baseType,
14138 baseType, set));
14139 } else {
14140 /*
14141 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14142 * must be validly derived from B given the subset as defined in Type
14143 * Derivation OK (Simple) (§3.14.6).
14144 */
14145 return (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType,
14146 set));
14147 }
14148}
14149
14150/**
14151 * xmlSchemaCheckCOSDerivedOK:
14152 * @type: the derived simple type definition
14153 * @baseType: the base type definition
14154 *
14155 * Calls:
14156 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
14157 *
14158 * Checks wheter @type can be validly derived from @baseType.
14159 *
14160 * Returns 0 on success, an positive error code otherwise.
14161 */
14162static int
14163xmlSchemaCheckCOSDerivedOK(xmlSchemaPtr schema,
14164 xmlSchemaTypePtr type,
14165 xmlSchemaTypePtr baseType,
14166 int set)
14167{
14168 if (IS_SIMPLE_TYPE(type))
14169 return (xmlSchemaCheckCOSSTDerivedOK(schema, type, baseType, set));
14170 else
14171 return (xmlSchemaCheckCOSCTDerivedOK(schema, type, baseType, set));
14172}
14173
William M. Brack2f2a6632004-08-20 23:09:47 +000014174/**
14175 * xmlSchemaCheckCOSCTExtends:
14176 * @ctxt: the schema parser context
14177 * @type: the complex type definition
14178 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014179 * (3.4.6) Constraints on Complex Type Definition Schema Components
14180 * Schema Component Constraint:
14181 * Derivation Valid (Extension) (cos-ct-extends)
14182 *
14183 * STATUS:
14184 * missing:
14185 * (1.5)
14186 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014187 *
14188 * Returns 0 if the constraints are satisfied, a positive
14189 * error code if not and -1 if an internal error occured.
14190 */
14191static int
14192xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14193 xmlSchemaTypePtr type)
14194{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014195 xmlSchemaTypePtr base = type->baseType;
14196 /*
14197 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14198 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014199 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014200 /*
14201 * SPEC (1) "If the {base type definition} is a complex type definition,
14202 * then all of the following must be true:"
14203 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014204 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14205 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014206 * SPEC (1.1) "The {final} of the {base type definition} must not
14207 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014208 */
14209 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14210 xmlSchemaPCustomErr(ctxt,
14211 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14212 NULL, type, NULL,
14213 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014214 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014215 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14216 }
14217 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014218 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
14219 * uses}
William M. Brack2f2a6632004-08-20 23:09:47 +000014220 * of the complex type definition itself, that is, for every attribute
14221 * use in the {attribute uses} of the {base type definition}, there
14222 * must be an attribute use in the {attribute uses} of the complex
14223 * type definition itself whose {attribute declaration} has the same
14224 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014225 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014226 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014227 * NOTE (1.2): This will be already satisfied by the way the attribute
14228 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14229 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014230 */
14231
14232 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014233 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14234 * definition must also have one, and the base type definition's
14235 * {attribute wildcard}'s {namespace constraint} must be a subset
14236 * of the complex type definition's {attribute wildcard}'s {namespace
14237 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014238 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014239 * NOTE (1.3) This is already checked in
14240 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014241 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014242 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014243 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014244 if ((type->contentTypeDef != NULL) &&
14245 (type->contentTypeDef == base->contentTypeDef)) {
14246 /*
14247 * SPEC (1.4.1) "The {content type} of the {base type definition}
14248 * and the {content type} of the complex type definition itself
14249 * must be the same simple type definition"
14250 * PASS
14251 */
14252 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14253 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14254 /*
14255 * SPEC (1.4.2) "The {content type} of both the {base type
14256 * definition} and the complex type definition itself must
14257 * be empty."
14258 * PASS
14259 */
14260 } else {
14261 /*
14262 * SPEC (1.4.3) "All of the following must be true:"
14263 */
14264 if (type->subtypes == NULL) {
14265 /*
14266 * SPEC 1.4.3.1 The {content type} of the complex type
14267 * definition itself must specify a particle.
14268 */
14269 xmlSchemaPCustomErr(ctxt,
14270 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14271 NULL, type, NULL,
14272 "The content type must specify a particle", NULL);
14273 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14274 }
14275 /*
14276 * SPEC (1.4.3.2) "One of the following must be true:"
14277 */
14278 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14279 /*
14280 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14281 * definition} must be empty.
14282 * PASS
14283 */
14284 } else {
14285 /*
14286 * SPEC (1.4.3.2.2) "All of the following must be true:"
14287 */
14288 if ((type->contentType != base->contentType) ||
14289 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14290 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14291 /*
14292 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14293 * or both must be element-only."
14294 */
14295 xmlSchemaPCustomErr(ctxt,
14296 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14297 NULL, type, NULL,
14298 "The content type of both, the type and its base "
14299 "type, must either 'mixed' or 'element-only'", NULL);
14300 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14301 }
14302 /*
14303 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14304 * complex type definition must be a ·valid extension·
14305 * of the {base type definition}'s particle, as defined
14306 * in Particle Valid (Extension) (§3.9.6)."
14307 *
14308 * NOTE that we won't check "Particle Valid (Extension)",
14309 * since it is ensured by the derivation process in
14310 * xmlSchemaTypeFixup(). We need to implement this when heading
14311 * for a construction API
14312 */
14313 }
14314 /*
14315 * TODO (1.5)
14316 */
14317 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014318 } else {
14319 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014320 * SPEC (2) "If the {base type definition} is a simple type definition,
14321 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014322 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014323 if (type->contentTypeDef != base) {
14324 /*
14325 * SPEC (2.1) "The {content type} must be the same simple type
14326 * definition."
14327 */
14328 xmlSchemaPCustomErr(ctxt,
14329 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14330 NULL, type, NULL,
14331 "The content type must be the simple base type", NULL);
14332 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14333 }
14334 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14335 /*
14336 * SPEC (2.2) "The {final} of the {base type definition} must not
14337 * contain extension"
14338 * NOTE that this is the same as (1.1).
14339 */
14340 xmlSchemaPCustomErr(ctxt,
14341 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14342 NULL, type, NULL,
14343 "The 'final' of the base type definition "
14344 "contains 'extension'", NULL);
14345 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14346 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014347 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014348 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014349}
14350
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014351/**
14352 * xmlSchemaCheckDerivationOKRestriction:
14353 * @ctxt: the schema parser context
14354 * @type: the complex type definition
14355 *
14356 * (3.4.6) Constraints on Complex Type Definition Schema Components
14357 * Schema Component Constraint:
14358 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14359 *
14360 * STATUS:
14361 * missing:
14362 * (5.4.2), (5.2.2.1)
14363 *
14364 * Returns 0 if the constraints are satisfied, a positive
14365 * error code if not and -1 if an internal error occured.
14366 */
14367static int
14368xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14369 xmlSchemaTypePtr type)
14370{
14371 xmlSchemaTypePtr base;
14372
14373 /*
14374 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14375 * temporarily only.
14376 */
14377 base = type->baseType;
14378 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14379 /*
14380 * SPEC (1) "The {base type definition} must be a complex type
14381 * definition whose {final} does not contain restriction."
14382 */
14383 xmlSchemaPCustomErr(ctxt,
14384 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14385 NULL, type, NULL,
14386 "The 'final' of the base type definition "
14387 "contains 'restriction'", NULL);
14388 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14389 }
14390 /*
14391 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14392 *
14393 * SPEC (5) "One of the following must be true:"
14394 */
14395 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14396 /*
14397 * SPEC (5.1) "The {base type definition} must be the
14398 * ·ur-type definition·."
14399 * PASS
14400 */
14401 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14402 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14403 /*
14404 * SPEC (5.2.1) "The {content type} of the complex type definition
14405 * must be a simple type definition"
14406 *
14407 * SPEC (5.2.2) "One of the following must be true:"
14408 */
14409 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14410 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14411 /*
14412 * SPEC (5.2.2.1) "The {content type} of the {base type
14413 * definition} must be a simple type definition from which
14414 * the {content type} is validly derived given the empty
14415 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14416 * URGENT TODO
14417 */
14418 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14419 (xmlSchemaIsParticleEmptiable(
14420 (xmlSchemaParticlePtr) base->subtypes))) {
14421 /*
14422 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14423 * and have a particle which is ·emptiable· as defined in
14424 * Particle Emptiable (§3.9.6)."
14425 * PASS
14426 */
14427 } else {
14428 xmlSchemaPCustomErr(ctxt,
14429 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14430 NULL, type, NULL,
14431 "The content type of the base type must be either "
14432 "a simple type or 'mixed' and an emptiable particle", NULL);
14433 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14434 }
14435 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14436 /*
14437 * SPEC (5.3.1) "The {content type} of the complex type itself must
14438 * be empty"
14439 */
14440 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14441 /*
14442 * SPEC (5.3.2.1) "The {content type} of the {base type
14443 * definition} must also be empty."
14444 * PASS
14445 */
14446 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14447 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14448 xmlSchemaIsParticleEmptiable(
14449 (xmlSchemaParticlePtr) base->subtypes)) {
14450 /*
14451 * SPEC (5.3.2.2) "The {content type} of the {base type
14452 * definition} must be elementOnly or mixed and have a particle
14453 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14454 * PASS
14455 */
14456 } else {
14457 xmlSchemaPCustomErr(ctxt,
14458 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14459 NULL, type, NULL,
14460 "The content type of the base type must be either "
14461 "empty or 'mixed' (or 'elements-only') and an emptiable "
14462 "particle", NULL);
14463 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14464 }
14465 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14466 ((type->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14467 (base->contentType == XML_SCHEMA_CONTENT_MIXED))) {
14468 /*
14469 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14470 * itself must be element-only"
14471 * SPEC (5.4.1.2) "The {content type} of the complex type definition
14472 * itself and of the {base type definition} must be mixed"
14473 */
14474 /*
14475 * SPEC (5.4.2) "The particle of the complex type definition itself
14476 * must be a ·valid restriction· of the particle of the {content
14477 * type} of the {base type definition} as defined in Particle Valid
14478 * (Restriction) (§3.9.6).
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014479 * URGENT TODO: (5.4.2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014480 */
14481 } else {
14482 xmlSchemaPCustomErr(ctxt,
14483 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14484 NULL, type, NULL,
14485 "The type is not a valid restriction of its base type", NULL);
14486 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14487 }
14488 return (0);
14489}
14490
14491/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014492 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014493 * @ctxt: the schema parser context
14494 * @type: the complex type definition
14495 *
14496 * (3.4.6) Constraints on Complex Type Definition Schema Components
14497 *
14498 * Returns 0 if the constraints are satisfied, a positive
14499 * error code if not and -1 if an internal error occured.
14500 */
14501static int
14502xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14503 xmlSchemaTypePtr type)
14504{
14505 int ret;
14506 /*
14507 * Complex Type Definition Properties Correct
14508 */
14509 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14510 if (ret != 0)
14511 return (ret);
14512 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14513 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14514 else
14515 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14516 return (ret);
14517}
14518
14519/**
14520 * xmlSchemaCheckSRCCT:
14521 * @ctxt: the schema parser context
14522 * @type: the complex type definition
14523 *
14524 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
14525 * Schema Representation Constraint:
14526 * Complex Type Definition Representation OK (src-ct)
14527 *
14528 * Returns 0 if the constraints are satisfied, a positive
14529 * error code if not and -1 if an internal error occured.
14530 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014531static int
14532xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
14533 xmlSchemaTypePtr type)
14534{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014535 xmlSchemaTypePtr base;
14536 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014537
14538 /*
14539 * TODO: Adjust the error codes here, as I used
14540 * XML_SCHEMAP_SRC_CT_1 only yet.
14541 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014542 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014543 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014544 /*
14545 * 1 If the <complexContent> alternative is chosen, the type definition
14546 * ·resolved· to by the ·actual value· of the base [attribute]
14547 * must be a complex type definition;
14548 */
14549 if (! IS_COMPLEX_TYPE(base)) {
14550 xmlChar *str = NULL;
14551 xmlSchemaPCustomErr(ctxt,
14552 XML_SCHEMAP_SRC_CT_1,
14553 NULL, type, type->node,
14554 "If using <complexContent>, the base type is expected to be "
14555 "a complex type. The base type '%s' is a simple type",
14556 xmlSchemaFormatQName(&str, base->targetNamespace,
14557 base->name));
14558 FREE_AND_NULL(str)
14559 return (XML_SCHEMAP_SRC_CT_1);
14560 }
14561 } else {
14562 /*
14563 * SPEC
14564 * 2 If the <simpleContent> alternative is chosen, all of the
14565 * following must be true:
14566 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14567 * base [attribute] must be one of the following:
14568 */
14569 if (IS_SIMPLE_TYPE(base)) {
14570 if ((type->flags &
14571 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14572 xmlChar *str = NULL;
14573 /*
14574 * 2.1.3 only if the <extension> alternative is also
14575 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014576 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014577 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014578 xmlSchemaPCustomErr(ctxt,
14579 XML_SCHEMAP_SRC_CT_1,
14580 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014581 "If using <simpleContent> and <restriction>, the base "
14582 "type must be a complex type. The base type '%s' is "
14583 "a simple type",
14584 xmlSchemaFormatQName(&str, base->targetNamespace,
14585 base->name));
14586 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014587 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014588 }
14589 } else {
14590 /* Base type is a complex type. */
14591 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14592 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14593 /*
14594 * 2.1.1 a complex type definition whose {content type} is a
14595 * simple type definition;
14596 * PASS
14597 */
14598 if (base->contentTypeDef == NULL) {
14599 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014600 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014601 "Internal error: xmlSchemaCheckSRCCT, "
14602 "'%s', base type has no content type",
14603 type->name);
14604 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014605 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014606 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14607 (type->flags &
14608 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014609
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014610 /*
14611 * 2.1.2 only if the <restriction> alternative is also
14612 * chosen, a complex type definition whose {content type}
14613 * is mixed and a particle emptiable.
14614 */
14615 if (! xmlSchemaIsParticleEmptiable(
14616 (xmlSchemaParticlePtr) base->subtypes)) {
14617 ret = XML_SCHEMAP_SRC_CT_1;
14618 } else if ((type->contentTypeDef == NULL) ||
14619 (type->contentTypeDef->baseType == NULL)) {
14620 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014621 /*
14622 * 2.2 If clause 2.1.2 above is satisfied, then there
14623 * must be a <simpleType> among the [children] of
14624 * <restriction>.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014625 */
14626 /* TODO: Change error code to ..._SRC_CT_2_2. */
14627 xmlSchemaPCustomErr(ctxt,
14628 XML_SCHEMAP_SRC_CT_1,
14629 NULL, type, NULL,
14630 "A <simpleType> is expected among the children "
14631 "of <restriction>, if <simpleContent> is used and "
14632 "the base type '%s' is a complex type",
14633 xmlSchemaFormatQName(&str, base->targetNamespace,
14634 base->name));
14635 FREE_AND_NULL(str)
14636 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014637 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014638 } else {
14639 ret = XML_SCHEMAP_SRC_CT_1;
14640 }
14641 }
14642 if (ret > 0) {
14643 xmlChar *str = NULL;
14644 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
14645 xmlSchemaPCustomErr(ctxt,
14646 XML_SCHEMAP_SRC_CT_1,
14647 NULL, type, NULL,
14648 "If <simpleContent> and <restriction> is used, the "
14649 "base type must be a simple type or a complex type with "
14650 "mixed content and particle emptiable. The base type "
14651 "'%s' is none of those",
14652 xmlSchemaFormatQName(&str, base->targetNamespace,
14653 base->name));
14654 } else {
14655 xmlSchemaPCustomErr(ctxt,
14656 XML_SCHEMAP_SRC_CT_1,
14657 NULL, type, NULL,
14658 "If <simpleContent> and <extension> is used, the "
14659 "base type must be a simple type. The base type '%s' "
14660 "is a complex type",
14661 xmlSchemaFormatQName(&str, base->targetNamespace,
14662 base->name));
14663 }
14664 FREE_AND_NULL(str)
14665 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014666 }
14667 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014668 * SPEC (3) "The corresponding complex type definition component must
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014669 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014670 * Definition Schema Components (§3.4.6);"
14671 * NOTE (3) will be done in xmlSchemaTypeFixup().
14672 */
14673 /*
14674 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014675 * above for {attribute wildcard} is satisfied, the intensional
14676 * intersection must be expressible, as defined in Attribute Wildcard
14677 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014678 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014679 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014680 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014681}
William M. Brack2f2a6632004-08-20 23:09:47 +000014682
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014683#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
14684 xmlSchemaPCustomErrExt(pctxt, \
14685 XML_SCHEMAP_INVALID_FACET_VALUE, \
14686 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
14687 "It is an error for both '%s' and '%s' to be specified on the "\
14688 "same type definition", \
14689 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
14690 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
14691
14692#define FACET_RESTR_ERR(fac1, msg) \
14693 xmlSchemaPCustomErr(pctxt, \
14694 XML_SCHEMAP_INVALID_FACET_VALUE, \
14695 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
14696 msg, NULL);
14697
14698#define FACET_RESTR_FIXED_ERR(fac) \
14699 xmlSchemaPCustomErr(pctxt, \
14700 XML_SCHEMAP_INVALID_FACET_VALUE, \
14701 NULL, (xmlSchemaTypePtr) fac, fac->node, \
14702 "The base type's facet is 'fixed', thus the value must not " \
14703 "differ", NULL);
14704
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014705static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014706xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
14707 xmlSchemaFacetPtr facet1,
14708 xmlSchemaFacetPtr facet2,
14709 int lessGreater,
14710 int orEqual,
14711 int ofBase)
14712{
14713 xmlChar *msg = NULL;
14714
14715 msg = xmlStrdup(BAD_CAST "'");
14716 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
14717 msg = xmlStrcat(msg, BAD_CAST "' has to be");
14718 if (lessGreater == 0)
14719 msg = xmlStrcat(msg, BAD_CAST " equal to");
14720 if (lessGreater == 1)
14721 msg = xmlStrcat(msg, BAD_CAST " greater than");
14722 else
14723 msg = xmlStrcat(msg, BAD_CAST " less than");
14724
14725 if (orEqual)
14726 msg = xmlStrcat(msg, BAD_CAST " or equal to");
14727 msg = xmlStrcat(msg, BAD_CAST " '");
14728 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
14729 if (ofBase)
14730 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
14731 else
14732 msg = xmlStrcat(msg, BAD_CAST "'");
14733
14734 xmlSchemaPCustomErr(pctxt,
14735 XML_SCHEMAP_INVALID_FACET_VALUE,
14736 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
14737 (const char *) msg, NULL);
14738
14739 if (msg != NULL)
14740 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014741}
14742
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014743static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014744xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
14745 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014746{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014747 xmlSchemaTypePtr base = type->baseType;
14748 xmlSchemaFacetLinkPtr link, cur, last = NULL;
14749 xmlSchemaFacetPtr facet, bfacet,
14750 flength = NULL, ftotdig = NULL, ffracdig = NULL,
14751 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
14752 fmininc = NULL, fmaxinc = NULL,
14753 fminexc = NULL, fmaxexc = NULL,
14754 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
14755 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
14756 bfmininc = NULL, bfmaxinc = NULL,
14757 bfminexc = NULL, bfmaxexc = NULL;
14758 int res, err = 0, fixedErr;
14759 /*
14760 * 3 The {facets} of R are the union of S and the {facets}
14761 * of B, eliminating duplicates. To eliminate duplicates,
14762 * when a facet of the same kind occurs in both S and the
14763 * {facets} of B, the one in the {facets} of B is not
14764 * included, with the exception of enumeration and pattern
14765 * facets, for which multiple occurrences with distinct values
14766 * are allowed.
14767 */
14768 if ((type->facetSet == NULL) && (base->facetSet == NULL))
14769 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014770
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014771 last = type->facetSet;
14772 if (last != NULL)
14773 while (last->next != NULL)
14774 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014775
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014776 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
14777 facet = cur->facet;
14778 switch (facet->type) {
14779 case XML_SCHEMA_FACET_LENGTH:
14780 flength = facet; break;
14781 case XML_SCHEMA_FACET_MINLENGTH:
14782 fminlen = facet; break;
14783 case XML_SCHEMA_FACET_MININCLUSIVE:
14784 fmininc = facet; break;
14785 case XML_SCHEMA_FACET_MINEXCLUSIVE:
14786 fminexc = facet; break;
14787 case XML_SCHEMA_FACET_MAXLENGTH:
14788 fmaxlen = facet; break;
14789 case XML_SCHEMA_FACET_MAXINCLUSIVE:
14790 fmaxinc = facet; break;
14791 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
14792 fmaxexc = facet; break;
14793 case XML_SCHEMA_FACET_TOTALDIGITS:
14794 ftotdig = facet; break;
14795 case XML_SCHEMA_FACET_FRACTIONDIGITS:
14796 ffracdig = facet; break;
14797 default:
14798 break;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014799 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014800 }
14801 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
14802 facet = cur->facet;
14803 switch (facet->type) {
14804 case XML_SCHEMA_FACET_LENGTH:
14805 bflength = facet; break;
14806 case XML_SCHEMA_FACET_MINLENGTH:
14807 bfminlen = facet; break;
14808 case XML_SCHEMA_FACET_MININCLUSIVE:
14809 bfmininc = facet; break;
14810 case XML_SCHEMA_FACET_MINEXCLUSIVE:
14811 bfminexc = facet; break;
14812 case XML_SCHEMA_FACET_MAXLENGTH:
14813 bfmaxlen = facet; break;
14814 case XML_SCHEMA_FACET_MAXINCLUSIVE:
14815 bfmaxinc = facet; break;
14816 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
14817 bfmaxexc = facet; break;
14818 case XML_SCHEMA_FACET_TOTALDIGITS:
14819 bftotdig = facet; break;
14820 case XML_SCHEMA_FACET_FRACTIONDIGITS:
14821 bffracdig = facet; break;
14822 default:
14823 break;
14824 }
14825 }
14826 err = 0;
14827 /*
14828 * length and minLength or maxLength (2.2) + (3.2)
14829 */
14830 if (flength && (fminlen || fmaxlen)) {
14831 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
14832 "either of 'minLength' or 'maxLength' to be specified on "
14833 "the same type definition")
14834 }
14835 /*
14836 * Mutual exclusions in the same derivation step.
14837 */
14838 if ((fmaxinc) && (fmaxexc)) {
14839 /*
14840 * SCC "maxInclusive and maxExclusive"
14841 */
14842 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
14843 }
14844 if ((fmininc) && (fminexc)) {
14845 /*
14846 * SCC "minInclusive and minExclusive"
14847 */
14848 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014849 }
14850
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014851 if (flength && bflength) {
14852 /*
14853 * SCC "length valid restriction"
14854 * The values have to be equal.
14855 */
14856 res = xmlSchemaCompareValues(flength->val, bflength->val);
14857 if (res == -2)
14858 goto internal_error;
14859 /*
14860 * TODO: Maby a bug in the spec.
14861 */
14862 if (res != 0)
14863 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
14864 if ((res != 0) && (bflength->fixed)) {
14865 FACET_RESTR_FIXED_ERR(flength)
14866 }
14867
14868 }
14869 if (fminlen && bfminlen) {
14870 /*
14871 * SCC "minLength valid restriction"
14872 * minLength >= BASE minLength
14873 */
14874 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
14875 if (res == -2)
14876 goto internal_error;
14877 if (res == -1)
14878 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
14879 if ((res != 0) && (bfminlen->fixed)) {
14880 FACET_RESTR_FIXED_ERR(fminlen)
14881 }
14882 }
14883 if (fmaxlen && bfmaxlen) {
14884 /*
14885 * SCC "maxLength valid restriction"
14886 * maxLength <= BASE minLength
14887 */
14888 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
14889 if (res == -2)
14890 goto internal_error;
14891 if (res == 1)
14892 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
14893 if ((res != 0) && (bfmaxlen->fixed)) {
14894 FACET_RESTR_FIXED_ERR(fmaxlen)
14895 }
14896 }
14897 /*
14898 * SCC "length and minLength or maxLength"
14899 */
14900 if (! flength)
14901 flength = bflength;
14902 if (flength) {
14903 if (! fminlen)
14904 flength = bflength;
14905 if (fminlen) {
14906 /* (1.1) length >= minLength */
14907 res = xmlSchemaCompareValues(flength->val, fminlen->val);
14908 if (res == -2)
14909 goto internal_error;
14910 if (res == -1)
14911 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
14912 }
14913 if (! fmaxlen)
14914 fmaxlen = bfmaxlen;
14915 if (fmaxlen) {
14916 /* (2.1) length <= maxLength */
14917 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
14918 if (res == -2)
14919 goto internal_error;
14920 if (res == 1)
14921 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
14922 }
14923 }
14924 if (fmaxinc) {
14925 /*
14926 * "maxInclusive"
14927 */
14928 if (fmininc) {
14929 /* SCC "maxInclusive >= minInclusive" */
14930 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
14931 if (res == -2)
14932 goto internal_error;
14933 if (res == -1) {
14934 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
14935 }
14936 }
14937 /*
14938 * SCC "maxInclusive valid restriction"
14939 */
14940 if (bfmaxinc) {
14941 /* maxInclusive <= BASE maxInclusive */
14942 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
14943 if (res == -2)
14944 goto internal_error;
14945 if (res == 1)
14946 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
14947 if ((res != 0) && (bfmaxinc->fixed)) {
14948 FACET_RESTR_FIXED_ERR(fmaxinc)
14949 }
14950 }
14951 if (bfmaxexc) {
14952 /* maxInclusive < BASE maxExclusive */
14953 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
14954 if (res == -2)
14955 goto internal_error;
14956 if (res != -1) {
14957 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
14958 }
14959 }
14960 if (bfmininc) {
14961 /* maxInclusive >= BASE minInclusive */
14962 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
14963 if (res == -2)
14964 goto internal_error;
14965 if (res == -1) {
14966 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
14967 }
14968 }
14969 if (bfminexc) {
14970 /* maxInclusive > BASE minExclusive */
14971 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
14972 if (res == -2)
14973 goto internal_error;
14974 if (res != 1) {
14975 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
14976 }
14977 }
14978 }
14979 if (fmaxexc) {
14980 /*
14981 * "maxExclusive >= minExclusive"
14982 */
14983 if (fminexc) {
14984 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
14985 if (res == -2)
14986 goto internal_error;
14987 if (res == -1) {
14988 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
14989 }
14990 }
14991 /*
14992 * "maxExclusive valid restriction"
14993 */
14994 if (bfmaxexc) {
14995 /* maxExclusive <= BASE maxExclusive */
14996 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
14997 if (res == -2)
14998 goto internal_error;
14999 if (res == 1) {
15000 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15001 }
15002 if ((res != 0) && (bfmaxexc->fixed)) {
15003 FACET_RESTR_FIXED_ERR(fmaxexc)
15004 }
15005 }
15006 if (bfmaxinc) {
15007 /* maxExclusive <= BASE maxInclusive */
15008 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15009 if (res == -2)
15010 goto internal_error;
15011 if (res == 1) {
15012 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15013 }
15014 }
15015 if (bfmininc) {
15016 /* maxExclusive > BASE minInclusive */
15017 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15018 if (res == -2)
15019 goto internal_error;
15020 if (res != 1) {
15021 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15022 }
15023 }
15024 if (bfminexc) {
15025 /* maxExclusive > BASE minExclusive */
15026 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15027 if (res == -2)
15028 goto internal_error;
15029 if (res != 1) {
15030 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15031 }
15032 }
15033 }
15034 if (fminexc) {
15035 /*
15036 * "minExclusive < maxInclusive"
15037 */
15038 if (fmaxinc) {
15039 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15040 if (res == -2)
15041 goto internal_error;
15042 if (res != -1) {
15043 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15044 }
15045 }
15046 /*
15047 * "minExclusive valid restriction"
15048 */
15049 if (bfminexc) {
15050 /* minExclusive >= BASE minExclusive */
15051 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15052 if (res == -2)
15053 goto internal_error;
15054 if (res == -1) {
15055 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15056 }
15057 if ((res != 0) && (bfminexc->fixed)) {
15058 FACET_RESTR_FIXED_ERR(fminexc)
15059 }
15060 }
15061 if (bfmaxinc) {
15062 /* minExclusive <= BASE maxInclusive */
15063 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15064 if (res == -2)
15065 goto internal_error;
15066 if (res == 1) {
15067 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15068 }
15069 }
15070 if (bfmininc) {
15071 /* minExclusive >= BASE minInclusive */
15072 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15073 if (res == -2)
15074 goto internal_error;
15075 if (res == -1) {
15076 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15077 }
15078 }
15079 if (bfmaxexc) {
15080 /* minExclusive < BASE maxExclusive */
15081 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15082 if (res == -2)
15083 goto internal_error;
15084 if (res != -1) {
15085 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15086 }
15087 }
15088 }
15089 if (fmininc) {
15090 /*
15091 * "minInclusive < maxExclusive"
15092 */
15093 if (fmaxexc) {
15094 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15095 if (res == -2)
15096 goto internal_error;
15097 if (res != -1) {
15098 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15099 }
15100 }
15101 /*
15102 * "minExclusive valid restriction"
15103 */
15104 if (bfmininc) {
15105 /* minInclusive >= BASE minInclusive */
15106 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15107 if (res == -2)
15108 goto internal_error;
15109 if (res == -1) {
15110 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15111 }
15112 if ((res != 0) && (bfmininc->fixed)) {
15113 FACET_RESTR_FIXED_ERR(fmininc)
15114 }
15115 }
15116 if (bfmaxinc) {
15117 /* minInclusive <= BASE maxInclusive */
15118 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15119 if (res == -2)
15120 goto internal_error;
15121 if (res == -1) {
15122 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15123 }
15124 }
15125 if (bfminexc) {
15126 /* minInclusive > BASE minExclusive */
15127 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15128 if (res == -2)
15129 goto internal_error;
15130 if (res != 1)
15131 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15132 }
15133 if (bfmaxexc) {
15134 /* minInclusive < BASE maxExclusive */
15135 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15136 if (res == -2)
15137 goto internal_error;
15138 if (res != -1)
15139 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15140 }
15141 }
15142 if (ftotdig && bftotdig) {
15143 /*
15144 * SCC " totalDigits valid restriction"
15145 * totalDigits <= BASE totalDigits
15146 */
15147 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15148 if (res == -2)
15149 goto internal_error;
15150 if (res == 1)
15151 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15152 -1, 1, 1);
15153 if ((res != 0) && (bftotdig->fixed)) {
15154 FACET_RESTR_FIXED_ERR(ftotdig)
15155 }
15156 }
15157 if (ffracdig && bffracdig) {
15158 /*
15159 * SCC "fractionDigits valid restriction"
15160 * fractionDigits <= BASE fractionDigits
15161 */
15162 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15163 if (res == -2)
15164 goto internal_error;
15165 if (res == 1)
15166 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15167 -1, 1, 1);
15168 if ((res != 0) && (bffracdig->fixed)) {
15169 FACET_RESTR_FIXED_ERR(ffracdig)
15170 }
15171 }
15172 /*
15173 * SCC "fractionDigits less than or equal to totalDigits"
15174 */
15175 if (! ftotdig)
15176 ftotdig = bftotdig;
15177 if (! ffracdig)
15178 ffracdig = bffracdig;
15179 if (ftotdig && ffracdig) {
15180 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15181 if (res == -2)
15182 goto internal_error;
15183 if (res == 1)
15184 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15185 -1, 1, 0);
15186 }
15187 /*
15188 * *Enumerations* won' be added here, since only the first set
15189 * of enumerations in the ancestor-or-self axis is used
15190 * for validation, plus we need to use the base type of those
15191 * enumerations for whitespace.
15192 *
15193 * *Patterns*: won't be add here, since they are ORed at
15194 * type level and ANDed at ancestor level. This will
15195 * happed during validation by walking the base axis
15196 * of the type.
15197 */
15198 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15199 bfacet = cur->facet;
15200 /*
15201 * Special handling of enumerations and patterns.
15202 * TODO: hmm, they should not appear in the set, so remove this.
15203 */
15204 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
15205 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
15206 continue;
15207 /*
15208 * Search for a duplicate facet in the current type.
15209 */
15210 link = type->facetSet;
15211 err = 0;
15212 fixedErr = 0;
15213 while (link != NULL) {
15214 facet = link->facet;
15215 if (facet->type == bfacet->type) {
15216 switch (facet->type) {
15217 case XML_SCHEMA_FACET_WHITESPACE:
15218 /*
15219 * The whitespace must be stronger.
15220 */
15221 if (facet->whitespace < bfacet->whitespace) {
15222 FACET_RESTR_ERR(flength,
15223 "The 'whitespace' value has to be equal to "
15224 "or stronger than the 'whitespace' value of "
15225 "the base type")
15226 }
15227 if ((bfacet->fixed) &&
15228 (facet->whitespace != bfacet->whitespace)) {
15229 FACET_RESTR_FIXED_ERR(facet)
15230 }
15231 break;
15232 default:
15233 break;
15234 }
15235 /* Duplicate found. */
15236 break;
15237 }
15238 link = link->next;
15239 }
15240 /*
15241 * If no duplicate was found: add the base types's facet
15242 * to the set.
15243 */
15244 if (link == NULL) {
15245 link = (xmlSchemaFacetLinkPtr)
15246 xmlMalloc(sizeof(xmlSchemaFacetLink));
15247 if (link == NULL) {
15248 xmlSchemaPErrMemory(pctxt,
15249 "deriving facets, creating a facet link", NULL);
15250 return (-1);
15251 }
15252 link->facet = cur->facet;
15253 link->next = NULL;
15254 if (last == NULL)
15255 type->facetSet = link;
15256 else
15257 last->next = link;
15258 last = link;
15259 }
15260
15261 }
15262
15263 return (0);
15264internal_error:
15265 xmlSchemaPCustomErr(pctxt,
15266 XML_SCHEMAP_INVALID_FACET_VALUE,
15267 NULL, type, NULL,
15268 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15269 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015270}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015271
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015272/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015273 * xmlSchemaTypeFixup:
15274 * @typeDecl: the schema type definition
15275 * @ctxt: the schema parser context
15276 *
15277 * Fixes the content model of the type.
15278 */
15279static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015280xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015281 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000015282{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015283 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000015284 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015285 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
15286 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015287 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015288 if (! IS_NOT_TYPEFIXED(type))
15289 return;
15290 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000015291 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015292 name = type->name;
15293
15294 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
15295 xmlSchemaTypePtr baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015296
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015297 /*
15298 * Resolve & type-fix the base type.
15299 */
15300 baseType = type->baseType;
15301 if (baseType == NULL) {
15302 baseType = xmlSchemaGetType(ctxt->schema,
15303 type->base, type->baseNs);
15304 if (baseType == NULL) {
15305 xmlSchemaPResCompAttrErr(ctxt,
15306 XML_SCHEMAP_SRC_RESOLVE,
15307 NULL, type, type->node,
15308 "base", type->base, type->baseNs,
15309 XML_SCHEMA_TYPE_SIMPLE, NULL);
15310 return;
15311 }
15312 type->baseType = baseType;
15313 }
15314 if (IS_NOT_TYPEFIXED(baseType))
15315 xmlSchemaTypeFixup(baseType, ctxt, NULL);
15316 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
15317 /*
15318 * Skip fixup if the base type is invalid.
15319 * TODO: Generate a warning!
15320 */
15321 return;
15322 }
15323 /*
15324 * This basically checks if the base type can be derived.
15325 */
15326 if (xmlSchemaCheckSRCCT(ctxt, type) != 0) {
15327 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
15328 return;
15329 }
15330 /*
15331 * Fixup the content type.
15332 */
15333 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
15334 /*
15335 * Corresponds to <complexType><simpleContent>...
15336 */
15337 if ((IS_COMPLEX_TYPE(baseType)) &&
15338 (baseType->contentTypeDef != NULL) &&
15339 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
15340 /*
15341 * SPEC (1) If <restriction> + base type is <complexType>,
15342 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000015343 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015344 * NOTE (1.1) is handled during parsing of <restriction>.
15345 *
15346 * (1.2) "...otherwise (<restriction> has no <simpleType> among
15347 * its [children]), the simple type definition which is the
15348 * {content type} of the ... base type."
Daniel Veillard01fa6152004-06-29 17:04:39 +000015349 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015350 if (type->contentTypeDef->baseType == NULL) {
15351 /*
15352 * <simpleContent><restriction> has *no* <simpleType>
15353 * child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015354 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015355 type->contentTypeDef->baseType =
15356 baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015357 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015358 } else if ((IS_COMPLEX_TYPE(baseType)) &&
15359 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
15360 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
15361 /*
15362 * SPEC (2) If <restriction> + base is a mixed <complexType> with
15363 * an emptiable particle, then a simple type definition which
15364 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015365 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015366 if ((type->contentTypeDef == NULL) ||
15367 (type->contentTypeDef->baseType == NULL)) {
15368 /*
15369 * TODO: Check if this ever happens.
15370 */
15371 xmlSchemaPCustomErr(ctxt,
15372 XML_SCHEMAP_INTERNAL,
15373 NULL, type, NULL,
15374 "Internal error: xmlSchemaTypeFixup, "
15375 "complex type '%s': the <simpleContent><restriction> "
15376 "is missing a <simpleType> child, but was not catched "
15377 "by xmlSchemaCheckSRCCT()", type->name);
15378 }
15379 } else if ((IS_COMPLEX_TYPE(baseType)) &&
15380 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
15381 /*
15382 * SPEC (3) If <extension> + base is <complexType> with
15383 * <simpleType> content, "...then the {content type} of that
15384 * complex type definition"
15385 */
15386 if (baseType->contentTypeDef == NULL) {
15387 /*
15388 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
15389 * should have catched this already.
15390 */
15391 xmlSchemaPCustomErr(ctxt,
15392 XML_SCHEMAP_INTERNAL,
15393 NULL, type, NULL,
15394 "Internal error: xmlSchemaTypeFixup, "
15395 "complex type '%s': the <extension>ed base type is "
15396 "a complex type with no simple content type",
15397 type->name);
15398 }
15399 type->contentTypeDef = baseType->contentTypeDef;
15400 } else if ((IS_SIMPLE_TYPE(baseType)) &&
15401 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
15402 /*
15403 * SPEC (4) <extension> + base is <simpleType>
15404 * "... then that simple type definition"
15405 */
15406 type->contentTypeDef = baseType;
15407 } else {
15408 /*
15409 * TODO: Check if this ever happens.
15410 */
15411 xmlSchemaPCustomErr(ctxt,
15412 XML_SCHEMAP_INTERNAL,
15413 NULL, type, NULL,
15414 "Internal error: xmlSchemaTypeFixup, "
15415 "complex type '%s' with <simpleContent>: unhandled "
15416 "derivation case", type->name);
15417 }
15418 } else {
15419 int dummySequence = 0;
15420 xmlSchemaParticlePtr particle =
15421 (xmlSchemaParticlePtr) type->subtypes;
15422 /*
15423 * Corresponds to <complexType><complexContent>...
15424 *
15425 * NOTE that the effective mixed was already set during parsing of
15426 * <complexType> and <complexContent>; its flag value is
15427 * XML_SCHEMAS_TYPE_MIXED.
15428 *
15429 * Compute the "effective content":
15430 * (2.1.1) + (2.1.2) + (2.1.3)
15431 */
15432 if ((particle == NULL) ||
15433 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
15434 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
15435 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
15436 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
15437 (particle->minOccurs == 0))) &&
15438 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
15439 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
15440 /*
15441 * SPEC (2.1.4) "If the ·effective mixed· is true, then
15442 * a particle whose properties are as follows:..."
15443 *
15444 * Empty sequence model group with
15445 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
15446 * NOTE that we sill assign it the <complexType> node to
15447 * somehow anchor it in the doc.
15448 */
15449 if ((particle == NULL) ||
15450 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015451 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015452 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015453 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015454 particle = xmlSchemaAddParticle(ctxt, ctxt->schema,
15455 type->node, 1, 1);
15456 if (particle == NULL)
15457 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015458 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015459 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015460 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015461 particle->children = (xmlSchemaTreeItemPtr)
15462 xmlSchemaAddModelGroup(ctxt, ctxt->schema,
15463 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
15464 if (particle->children == NULL)
15465 return;
15466
15467 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015468 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015469 dummySequence = 1;
15470 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
15471 } else {
15472 /*
15473 * SPEC (2.1.5) "otherwise empty"
15474 */
15475 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
15476 }
15477 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015478 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015479 * SPEC (2.2) "otherwise the particle corresponding to the
15480 * <all>, <choice>, <group> or <sequence> among the
15481 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000015482 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015483 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
15484 }
15485 /*
15486 * Compute the "content type".
15487 */
15488 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015489 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015490 * SPEC (3.1) "If <restriction>..."
15491 * (3.1.1) + (3.1.2) */
15492 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
15493 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
15494 type->contentType = XML_SCHEMA_CONTENT_MIXED;
15495 }
15496 } else {
15497 /*
15498 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015499 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015500 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
15501 /*
15502 * SPEC (3.2.1)
15503 */
15504 type->contentType = baseType->contentType;
15505 type->subtypes = baseType->subtypes;
15506 /*
15507 * NOTE that the effective mixed is ignored here.
15508 */
15509 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
15510 /*
15511 * SPEC (3.2.2)
15512 */
15513 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
15514 type->contentType = XML_SCHEMA_CONTENT_MIXED;
15515 } else {
15516 /*
15517 * SPEC (3.2.3)
15518 */
15519 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
15520 type->contentType = XML_SCHEMA_CONTENT_MIXED;
15521 /*
15522 * "A model group whose {compositor} is sequence and whose
15523 * {particles} are..."
15524 */
15525 if (! dummySequence) {
15526 xmlSchemaTreeItemPtr effectiveContent =
15527 (xmlSchemaTreeItemPtr) type->subtypes;
15528 /*
15529 * Create the particle.
15530 */
15531 particle = xmlSchemaAddParticle(ctxt, ctxt->schema,
15532 type->node, 1, 1);
15533 if (particle == NULL)
15534 return;
15535 /*
15536 * Create the "sequence" model group.
15537 */
15538 particle->children = (xmlSchemaTreeItemPtr)
15539 xmlSchemaAddModelGroup(ctxt, ctxt->schema,
15540 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
15541 if (particle->children == NULL)
15542 return;
15543 type->subtypes = (xmlSchemaTypePtr) particle;
15544 /*
15545 * SPEC "the particle of the {content type} of
15546 * the ... base ..."
15547 * Create a duplicate of the base type's particle
15548 * and assign its "term" to it.
15549 */
15550 particle->children->children =
15551 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(ctxt,
15552 ctxt->schema, type->node,
15553 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
15554 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
15555 if (particle->children->children == NULL)
15556 return;
15557 particle = (xmlSchemaParticlePtr)
15558 particle->children->children;
15559 particle->children =
15560 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
15561 /*
15562 * SPEC "followed by the ·effective content·."
15563 */
15564 particle->next = effectiveContent;
15565 } else {
15566 /*
15567 * This is the case when there is already an empty
15568 * <sequence> with minOccurs==maxOccurs==1.
15569 * Just add the base types's content type.
15570 * NOTE that, although we miss to add an intermediate
15571 * <sequence>, this should produce no difference to
15572 * neither the regex compilation of the content model,
15573 * nor to the complex type contraints.
15574 */
15575 particle->children->children =
15576 (xmlSchemaTreeItemPtr) baseType->subtypes;
15577 }
15578 }
15579 }
15580 }
15581 /*
15582 * Apply the complex type component constraints; this will not
15583 * check attributes, since this is done in
15584 * xmlSchemaBuildAttributeValidation().
15585 */
15586 if (xmlSchemaCheckCTComponent(ctxt, type) != 0)
15587 return;
15588 /*
15589 * Inherit & check constraints for attributes.
15590 */
15591 xmlSchemaBuildAttributeValidation(ctxt, type);
15592 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
15593 /*
15594 * Simple Type Definition Schema Component
15595 */
15596 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
15597 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15598 /*
15599 * Corresponds to <simpleType><list>...
15600 * Resolve the itemType.
15601 */
15602 if ((type->subtypes == NULL) && (type->ref != NULL)) {
15603 type->subtypes = xmlSchemaGetType(ctxt->schema,
15604 type->ref, type->refNs);
15605 if ((type->subtypes == NULL) ||
15606 (! IS_SIMPLE_TYPE(type->subtypes))) {
15607 type->subtypes = NULL;
15608 xmlSchemaPResCompAttrErr(ctxt,
15609 XML_SCHEMAP_SRC_RESOLVE,
15610 NULL, type, type->node,
15611 "itemType", type->ref, type->refNs,
15612 XML_SCHEMA_TYPE_SIMPLE, NULL);
15613 }
15614 }
15615 if (type->subtypes == NULL) {
15616 /*
15617 * This one is really needed, so get out.
15618 */
15619 return;
15620 }
15621 if (IS_NOT_TYPEFIXED(type->subtypes))
15622 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
15623 /* Base type:
15624 * 2 If the <list> or <union> alternative is chosen,
15625 * then the ·simple ur-type definition·.
15626 */
15627 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
15628 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
15629 /*
15630 * Corresponds to <simpleType><union>...
15631 * Resolve the member types.
15632 */
15633 xmlSchemaResolveUnionMemberTypes(ctxt, type);
15634 if (type->memberTypes == NULL) {
15635 /*
15636 * This one is really needed, so get out.
15637 */
15638 return;
15639 }
15640 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
15641 } else {
15642 xmlSchemaTypePtr baseType;
15643 /*
15644 * Corresponds to <simpleType><restriction>...
15645 *
15646 * Resolve the base type.
15647 */
15648 if ((type->baseType == NULL) && (type->base != NULL)) {
15649 baseType = xmlSchemaGetType(ctxt->schema,
15650 type->base, type->baseNs);
15651
15652 if (baseType == NULL) {
15653 xmlSchemaPResCompAttrErr(ctxt,
15654 XML_SCHEMAP_SRC_RESOLVE,
15655 NULL, type, type->node,
15656 "base", type->base, type->baseNs,
15657 XML_SCHEMA_TYPE_SIMPLE, NULL);
15658 }
15659 type->baseType = baseType;
15660 } else
15661 baseType = type->baseType;
15662
15663 if (baseType == NULL)
15664 return;
15665
15666 if (IS_NOT_TYPEFIXED(baseType))
15667 xmlSchemaTypeFixup(baseType, ctxt, NULL);
15668 /*
15669 * Variety
15670 * If the <restriction> alternative is chosen, then the
15671 * {variety} of the {base type definition}.
15672 */
15673 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
15674 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
15675 else if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15676 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
15677 /*
15678 * Inherit the itemType.
15679 */
15680 type->subtypes = baseType->subtypes;
15681 } else if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
15682 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
15683 /*
15684 * NOTE that we won't assign the memberTypes of the base,
15685 * since this will make trouble when freeing them; we will
15686 * use a lookup function to access them instead.
15687 */
15688 }
15689
15690 /*
15691 * Some optimization for validation:
15692 * If there are no facets beside the "whitespace" facet,
15693 * then a value needs not to checked against against a
15694 * facet, thus no computed value is needed.
15695 */
15696#if 0
15697 if (baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
15698 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15699 else {
15700 for (cur = type->facetSet; cur != NULL;
15701 cur = cur->next) {
15702 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15703 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15704 break;
15705 }
15706 }
15707 }
15708#endif
15709 }
15710 /*
15711 * Check constraints.
15712 *
15713 * TODO: Split this somehow, we need to know first if we can derive
15714 * from the base type at all!
15715 */
15716 if (type->baseType != NULL) {
15717 /*
15718 * Schema Component Constraint: Simple Type Restriction
15719 * (Facets)
15720 * NOTE: Satisfaction of 1 and 2 arise from the fixup
15721 * applied beforehand.
15722 */
15723 xmlSchemaCheckSRCSimpleType(ctxt, type);
15724 xmlSchemaCheckFacetValues(type, ctxt);
15725 xmlSchemaDeriveAndValidateFacets(ctxt, type);
15726 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015727 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015728
Daniel Veillard8651f532002-04-17 09:06:27 +000015729#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015730 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015731 xmlGenericError(xmlGenericErrorContext,
15732 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015733 type->node->doc->URL,
15734 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000015735 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015736 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000015737 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015738 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
15739 switch (type->contentType) {
15740 case XML_SCHEMA_CONTENT_SIMPLE:
15741 xmlGenericError(xmlGenericErrorContext, "simple\n");
15742 break;
15743 case XML_SCHEMA_CONTENT_ELEMENTS:
15744 xmlGenericError(xmlGenericErrorContext, "elements\n");
15745 break;
15746 case XML_SCHEMA_CONTENT_UNKNOWN:
15747 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
15748 break;
15749 case XML_SCHEMA_CONTENT_EMPTY:
15750 xmlGenericError(xmlGenericErrorContext, "empty\n");
15751 break;
15752 case XML_SCHEMA_CONTENT_MIXED:
15753 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
15754 type->subtypes))
15755 xmlGenericError(xmlGenericErrorContext,
15756 "mixed as emptiable particle\n");
15757 else
15758 xmlGenericError(xmlGenericErrorContext, "mixed\n");
15759 break;
15760 /* Removed, since not used. */
15761 /*
15762 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
15763 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
15764 break;
15765 */
15766 case XML_SCHEMA_CONTENT_BASIC:
15767 xmlGenericError(xmlGenericErrorContext, "basic\n");
15768 break;
15769 default:
15770 xmlGenericError(xmlGenericErrorContext,
15771 "not registered !!!\n");
15772 break;
15773 }
Daniel Veillard8651f532002-04-17 09:06:27 +000015774 }
15775#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015776}
15777
15778/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000015779 * xmlSchemaCheckFacet:
15780 * @facet: the facet
15781 * @typeDecl: the schema type definition
15782 * @ctxt: the schema parser context or NULL
15783 * @name: name of the type
15784 *
15785 * Checks the default values types, especially for facets
15786 *
15787 * Returns 0 if okay or -1 in cae of error
15788 */
15789int
15790xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015791 xmlSchemaTypePtr typeDecl,
15792 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000015793{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000015794 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015795 int ret = 0, reuseValCtxt = 0;
15796
Daniel Veillardce682bc2004-11-05 17:22:25 +000015797 if ((facet == NULL) || (typeDecl == NULL))
15798 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015799 /*
15800 * TODO: will the parser context be given if used from
15801 * the relaxNG module?
15802 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000015803
15804 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015805 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000015806 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000015807 }
15808 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015809 case XML_SCHEMA_FACET_MININCLUSIVE:
15810 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15811 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015812 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15813 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015814 /*
15815 * Okay we need to validate the value
15816 * at that point.
15817 */
15818 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015819 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015820
15821 /* 4.3.5.5 Constraints on enumeration Schema Components
15822 * Schema Component Constraint: enumeration valid restriction
15823 * It is an ·error· if any member of {value} is not in the
15824 * ·value space· of {base type definition}.
15825 *
15826 * minInclusive, maxInclusive, minExclusive, maxExclusive:
15827 * The value ·must· be in the
15828 * ·value space· of the ·base type·.
15829 */
15830 /*
15831 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015832 * on the facet. In this implementation of XML Schemata the
15833 * type holding a facet, won't be a built-in type.
15834 * Thus to ensure that other API
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015835 * calls (relaxng) do work, if the given type is a built-in
15836 * type, we will assume that the given built-in type *is
15837 * already* the base type.
15838 */
15839 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
15840 base = typeDecl->baseType;
15841 if (base == NULL) {
15842 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015843 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015844 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015845 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015846 typeDecl->name, NULL);
15847 return (-1);
15848 }
15849 } else
15850 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015851 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015852 * This avoids perseverative creation of the
15853 * validation context if a parser context is
15854 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015855 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015856 if (ctxt != NULL) {
15857 reuseValCtxt = 1;
15858 if (ctxt->vctxt == NULL) {
15859 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
15860 return (-1);
15861 }
15862 vctxt = ctxt->vctxt;
15863 } else {
15864 vctxt = xmlSchemaNewValidCtxt(NULL);
15865 if (vctxt == NULL) {
15866 xmlSchemaPErr(ctxt, typeDecl->node,
15867 XML_SCHEMAP_INTERNAL,
15868 "Internal error: xmlSchemaCheckFacet, "
15869 "creating a new validation context.\n",
15870 NULL, NULL);
15871 return (-1);
15872 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015873 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015874
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015875 vctxt->node = facet->node;
15876 vctxt->cur = NULL;
15877 /*
15878 * NOTE: This call does not check the content nodes,
15879 * since they are not available:
15880 * facet->node is just the node holding the facet
15881 * definition, *not* the attribute holding the *value*
15882 * of the facet.
15883 */
15884 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015885 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015886 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015887 /* error code */
15888 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015889 xmlChar *str = NULL;
15890
15891 xmlSchemaPCustomErrExt(ctxt,
15892 XML_SCHEMAP_INVALID_FACET_VALUE,
15893 NULL, (xmlSchemaTypePtr) facet, facet->node,
15894 "The value '%s' of the facet does not validate "
15895 "against the base type '%s'",
15896 facet->value,
15897 xmlSchemaFormatQName(&str,
15898 base->targetNamespace, base->name), NULL);
15899 FREE_AND_NULL(str)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015900 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015901 /* xmlSchemaFacetTypeToString(facet->type), */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015902 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015903 } else if (ret < 0) {
15904 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015905 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015906 NULL, NULL, NULL,
15907 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015908 "failed to validate the value '%s' name of the "
15909 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015910 facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015911 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015912 base->name, NULL, NULL);
15913 ret = -1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015914 } else {
15915 if (vctxt->value != NULL) {
15916 facet->val = vctxt->value;
15917 vctxt->value = NULL;
15918 } else {
15919 xmlChar *str;
15920 /*
15921 * Ensure computed values even for type string.
15922 * TODO OPTIMIZE MEMORY: The value will be hold twice,
15923 * by the facet->value and by the computed value.
15924 */
15925 str = xmlStrdup(facet->value);
15926 if (xmlSchemaPostCreateVal(vctxt, typeDecl,
15927 BAD_CAST str, &(facet->val)) == -1) {
15928 FREE_AND_NULL(str)
15929 xmlSchemaPErr(ctxt, typeDecl->node,
15930 XML_SCHEMAP_INTERNAL,
15931 "Internal error: xmlSchemaCheckFacet, "
15932 "post-creating a computed value.\n",
15933 NULL, NULL);
15934 /* Note that we don't return a failure yet.*/
15935 }
15936 }
15937 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015938 if (reuseValCtxt == 0)
15939 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015940 break;
15941 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015942 case XML_SCHEMA_FACET_PATTERN:
15943 facet->regexp = xmlRegexpCompile(facet->value);
15944 if (facet->regexp == NULL) {
15945 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015946 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015947 "Type definition '%s': The value '%s' of the "
15948 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015949 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015950 ret = -1;
15951 }
15952 break;
15953 case XML_SCHEMA_FACET_TOTALDIGITS:
15954 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15955 case XML_SCHEMA_FACET_LENGTH:
15956 case XML_SCHEMA_FACET_MAXLENGTH:
15957 case XML_SCHEMA_FACET_MINLENGTH:{
15958 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000015959
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015960 tmp =
15961 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
15962 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000015963 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015964 if (tmp != 0) {
15965 /* error code */
15966 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015967 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015968 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015969 NULL, (xmlSchemaTypePtr) facet, facet->node,
15970 "The value '%s' of the facet is not a valid "
15971 "nonNegativeInteger", facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015972 }
15973 ret = -1;
15974 }
15975 break;
15976 }
15977 case XML_SCHEMA_FACET_WHITESPACE:{
15978 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
15979 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
15980 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
15981 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
15982 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
15983 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
15984 } else {
15985 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015986 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
15987 xmlSchemaPCustomErr(ctxt,
15988 XML_SCHEMAP_INVALID_FACET_VALUE,
15989 NULL, (xmlSchemaTypePtr) facet, facet->node,
15990 "The value '%s' of the facet is not a valid",
15991 facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015992 }
15993 ret = -1;
15994 }
15995 }
15996 default:
15997 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000015998 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015999 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016000}
16001
16002/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016003 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016004 * @typeDecl: the schema type definition
16005 * @ctxt: the schema parser context
16006 *
16007 * Checks the default values types, especially for facets
16008 */
16009static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016010xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16011 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016012{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016013 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016014 /*
16015 * NOTE: It is intended to use the facets list, instead
16016 * of facetSet.
16017 */
16018 if (typeDecl->facets != NULL) {
16019 xmlSchemaFacetPtr facet = typeDecl->facets;
16020
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016021 /*
16022 * Temporarily assign the "schema" to the validation context
16023 * of the parser context. This is needed for NOTATION validation.
16024 */
16025 if (ctxt->vctxt == NULL) {
16026 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16027 return;
16028 }
16029 ctxt->vctxt->schema = ctxt->schema;
16030
Daniel Veillard01fa6152004-06-29 17:04:39 +000016031 while (facet != NULL) {
16032 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16033 facet = facet->next;
16034 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016035
16036 ctxt->vctxt->schema = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016037 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016038}
16039
16040/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016041 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016042 * @ctxtMGroup: the searched model group
16043 * @selfMGroup: the second searched model group
16044 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016045 *
16046 * This one is intended to be used by
16047 * xmlSchemaCheckGroupDefCircular only.
16048 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016049 * Returns the particle with the circular model group definition reference,
16050 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016051 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016052static xmlSchemaTreeItemPtr
16053xmlSchemaGetCircModelGrDefRef(xmlSchemaTreeItemPtr ctxtMGroup,
16054 xmlSchemaTreeItemPtr selfMGroup,
16055 xmlSchemaTreeItemPtr particle)
16056{
16057 xmlSchemaTreeItemPtr circ = NULL;
16058 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016059
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016060 while (particle != NULL) {
16061 term = particle->children;
16062 if ((term != NULL) &&
16063 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16064 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
16065 (term->type == XML_SCHEMA_TYPE_ALL))) {
16066 if (term == ctxtMGroup)
16067 return (particle);
16068 /*
16069 * Avoid infinite recursion on circular references not yet
16070 * examined.
16071 */
16072 if (term == selfMGroup)
16073 return (NULL);
16074 circ = xmlSchemaGetCircModelGrDefRef(ctxtMGroup, term,
16075 term->children);
16076 if (circ != NULL)
16077 return (circ);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016078 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016079 particle = particle->next;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016080 }
16081 return (NULL);
16082}
16083
16084/**
16085 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016086 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016087 * @ctxt: the parser context
16088 * @name: the name
16089 *
16090 * Checks for circular references to model group definitions.
16091 */
16092static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016093xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016094 xmlSchemaParserCtxtPtr ctxt,
16095 const xmlChar * name ATTRIBUTE_UNUSED)
16096{
16097 /*
16098 * Schema Component Constraint: Model Group Correct
16099 * 2 Circular groups are disallowed. That is, within the {particles}
16100 * of a group there must not be at any depth a particle whose {term}
16101 * is the group itself.
16102 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016103 if ((item == NULL) ||
16104 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16105 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016106 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016107 {
16108 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016109
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016110 circ = xmlSchemaGetCircModelGrDefRef(item->children, NULL,
16111 item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016112 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016113 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016114 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016115 * TODO: The error report is not adequate: this constraint
16116 * is defined for model groups but not definitions, but since
16117 * there cannot be any circular model groups without a model group
16118 * definition (if not using a construction API), we check those
16119 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016120 */
16121 xmlSchemaPCustomErr(ctxt,
16122 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016123 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016124 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016125 "defined", xmlSchemaFormatQName(&str,
16126 item->targetNamespace, item->name));
16127 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016128 /*
16129 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016130 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016131 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016132 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016133 }
16134 }
16135}
16136
16137
16138/**
16139 * xmlSchemaGetCircAttrGrRef:
16140 * @ctxtGr: the searched attribute group
16141 * @attr: the current attribute list to be processed
16142 *
16143 * This one is intended to be used by
16144 * xmlSchemaCheckSRCAttributeGroupCircular only.
16145 *
16146 * Returns the circular attribute grou reference, otherwise NULL.
16147 */
16148static xmlSchemaAttributeGroupPtr
16149xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16150 xmlSchemaAttributePtr attr)
16151{
16152 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16153 int marked;
16154 /*
16155 * We will search for an attribute group reference which
16156 * references the context attribute group.
16157 */
16158 while (attr != NULL) {
16159 marked = 0;
16160 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16161 gr = (xmlSchemaAttributeGroupPtr) attr;
16162 if (gr->refItem != NULL) {
16163 if (gr->refItem == ctxtGr)
16164 return (gr);
16165 else if (gr->refItem->flags &
16166 XML_SCHEMAS_ATTRGROUP_MARKED) {
16167 attr = attr->next;
16168 continue;
16169 } else {
16170 /*
16171 * Mark as visited to avoid infinite recursion on
16172 * circular references not yet examined.
16173 */
16174 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16175 marked = 1;
16176 }
16177 }
16178 if (gr->attributes != NULL)
16179 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16180 /*
16181 * Unmark the visited group's attributes.
16182 */
16183 if (marked)
16184 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16185 if (circ != NULL)
16186 return (circ);
16187 }
16188 attr = attr->next;
16189 }
16190 return (NULL);
16191}
16192
16193/**
16194 * xmlSchemaCheckSRCAttributeGroupCircular:
16195 * attrGr: the attribute group definition
16196 * @ctxt: the parser context
16197 * @name: the name
16198 *
16199 * Checks for circular references of attribute groups.
16200 */
16201static void
16202xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
16203 xmlSchemaParserCtxtPtr ctxt,
16204 const xmlChar * name ATTRIBUTE_UNUSED)
16205{
16206 /*
16207 * Schema Representation Constraint:
16208 * Attribute Group Definition Representation OK
16209 * 3 Circular group reference is disallowed outside <redefine>.
16210 * That is, unless this element information item's parent is
16211 * <redefine>, then among the [children], if any, there must
16212 * not be an <attributeGroup> with ref [attribute] which resolves
16213 * to the component corresponding to this <attributeGroup>. Indirect
16214 * circularity is also ruled out. That is, when QName resolution
16215 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16216 * any <attributeGroup>s with a ref [attribute] among the [children],
16217 * it must not be the case that a ·QName· is encountered at any depth
16218 * which resolves to the component corresponding to this <attributeGroup>.
16219 */
16220 /*
16221 * Only global components can be referenced.
16222 */
16223 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
16224 (attrGr->attributes == NULL))
16225 return;
16226 else {
16227 xmlSchemaAttributeGroupPtr circ;
16228
16229 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16230 if (circ != NULL) {
16231 /*
16232 * TODO: Report the referenced attr group as QName.
16233 */
16234 xmlSchemaPCustomErr(ctxt,
16235 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16236 NULL, NULL, circ->node,
16237 "Circular reference to the attribute group '%s' "
16238 "defined", attrGr->name);
16239 /*
16240 * NOTE: We will cut the reference to avoid further
16241 * confusion of the processor.
16242 * BADSPEC: The spec should define how to process in this case.
16243 */
16244 circ->attributes = NULL;
16245 circ->refItem = NULL;
16246 }
16247 }
16248}
16249
16250/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000016251 * xmlSchemaAttrGrpFixup:
16252 * @attrgrpDecl: the schema attribute definition
16253 * @ctxt: the schema parser context
16254 * @name: the attribute name
16255 *
16256 * Fixes finish doing the computations on the attributes definitions
16257 */
16258static void
Daniel Veillard3646d642004-06-02 19:19:14 +000016259xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016260 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000016261{
16262 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016263 name = attrgrp->name;
16264 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016265 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000016266 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016267 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000016268
Daniel Veillardc0826a72004-08-10 14:17:33 +000016269 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
16270 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016271 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016272 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016273 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016274 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
16275 "ref", attrgrp->ref, attrgrp->refNs,
16276 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016277 return;
16278 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016279 attrgrp->refItem = ref;
16280 /*
16281 * Check for self reference!
16282 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016283 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000016284 attrgrp->attributes = ref->attributes;
16285 attrgrp->attributeWildcard = ref->attributeWildcard;
16286 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000016287}
16288
16289/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016290 * xmlSchemaAttrCheckValConstr:
16291 * @item: an schema attribute declaration/use
16292 * @ctxt: a schema parser context
16293 * @name: the name of the attribute
16294 *
16295 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000016296 *
16297 * Fixes finish doing the computations on the attributes definitions
16298 */
16299static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016300xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
16301 xmlSchemaParserCtxtPtr ctxt,
16302 const xmlChar * name ATTRIBUTE_UNUSED)
16303{
16304
16305 /*
16306 * a-props-correct
16307 * Schema Component Constraint: Attribute Declaration Properties Correct
16308 *
16309 * 2 if there is a {value constraint}, the canonical lexical
16310 * representation of its value must be ·valid· with respect
16311 * to the {type definition} as defined in String Valid (§3.14.4).
16312 */
16313
16314 if (item->defValue != NULL) {
16315 int ret;
16316 xmlNodePtr node;
16317 xmlSchemaTypePtr type;
16318
16319 if (item->subtypes == NULL) {
16320 xmlSchemaPErr(ctxt, item->node,
16321 XML_SCHEMAP_INTERNAL,
16322 "Internal error: xmlSchemaCheckAttrValConstr, "
16323 "type is missing... skipping validation of "
16324 "value constraint", NULL, NULL);
16325 return;
16326 }
16327
16328 /*
16329 * TODO: Try to avoid creating a new context.
16330 * TODO: This all is not very performant.
16331 */
16332 type = item->subtypes;
16333 /*
16334 * Ensure there's validation context.
16335 */
16336 if (ctxt->vctxt == NULL) {
16337 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
16338 xmlSchemaPErr(ctxt, item->node,
16339 XML_SCHEMAP_INTERNAL,
16340 "Internal error: xmlSchemaCheckAttrValConstr, "
16341 "creating a new validation context.\n",
16342 NULL, NULL);
16343 return;
16344 }
16345 }
16346
16347 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
16348 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
16349 else
16350 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
16351 ctxt->vctxt->node = node;
16352 ctxt->vctxt->cur = NULL;
16353 /*
16354 * NOTE: This call does not check the content nodes,
16355 * since they are not available:
16356 * facet->node is just the node holding the facet
16357 * definition, *not* the attribute holding the *value*
16358 * of the facet.
16359 */
16360 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
16361 item->defValue, 0, 1, 1, 0);
16362 if (ret == 0) {
16363 /*
16364 * Store the computed value.
16365 */
16366 item->defVal = ctxt->vctxt->value;
16367 ctxt->vctxt->value = NULL;
16368 } else if (ret > 0) {
16369 if (ctxt != NULL) {
16370 xmlSchemaPSimpleTypeErr(ctxt,
16371 XML_SCHEMAP_A_PROPS_CORRECT_2,
16372 NULL, NULL, node,
16373 type, NULL, item->defValue,
16374 NULL, NULL, NULL);
16375 }
16376 } else if (ret < 0) {
16377 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16378 NULL, NULL, node,
16379 "Internal error: xmlSchemaAttrCheckValConstr, "
16380 "failed to validate the value constraint of the "
16381 "attribute decl/use against the type '%s'",
16382 type->name);
16383 }
16384 }
16385}
16386
16387#if 0 /* Not used yet. */
16388static int
16389xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
16390 xmlSchemaElementPtr edecl)
16391{
16392 /*
16393 * TODO: 1 The values of the properties of an element declaration must be as
16394 * described in the property tableau in The Element Declaration Schema
16395 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
16396 */
16397 /*
16398 * 2 If there is a {value constraint}, the canonical lexical
16399 * representation of its value must be ·valid· with respect to the {type
16400 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
16401 *
16402 * NOTE: This is done in xmlSchemaCheckElemValConstr.
16403 */
16404 /*
16405 * 3 If there is a non-·absent· {substitution group affiliation},
16406 * then {scope} must be global.
16407 *
16408 * NOTE: This is done in xmlSchemaParseElement.
16409 * TODO: Move it to this layer here.
16410 */
16411 /*
16412 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
16413 * of the element declaration must be validly derived from the {type
16414 * definition} of the {substitution group affiliation}, given the value
16415 * of the {substitution group exclusions} of the {substitution group
16416 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
16417 * (if the {type definition} is complex) or as defined in
16418 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
16419 * simple).
16420 */
16421 /*
16422 * TODO: 5 If the {type definition} or {type definition}'s {content type}
16423 * is or is derived from ID then there must not be a {value constraint}.
16424 * Note: The use of ID as a type definition for elements goes beyond
16425 * XML 1.0, and should be avoided if backwards compatibility is desired
16426 */
16427 /*
16428 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
16429 * be possible to return to an element declaration by repeatedly following
16430 * the {substitution group affiliation} property.
16431 */
16432}
16433#endif
16434
16435/**
16436 * xmlSchemaCheckElemValConstr:
16437 * @item: an schema element declaration/particle
16438 * @ctxt: a schema parser context
16439 * @name: the name of the attribute
16440 *
16441 * Validates the value constraints of an element declaration.
16442 *
16443 * Fixes finish doing the computations on the element declarations.
16444 */
16445static void
16446xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
16447 xmlSchemaParserCtxtPtr ctxt,
16448 const xmlChar * name ATTRIBUTE_UNUSED)
16449{
16450 if (decl->value != NULL) {
16451 int ret;
16452 xmlNodePtr node = NULL;
16453 xmlSchemaTypePtr type;
16454
16455 /*
16456 * 2 If there is a {value constraint}, the canonical lexical
16457 * representation of its value must be ·valid· with respect to the {type
16458 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
16459 */
16460 if (decl->subtypes == NULL) {
16461 xmlSchemaPErr(ctxt, decl->node,
16462 XML_SCHEMAP_INTERNAL,
16463 "Internal error: xmlSchemaCheckElemValConstr, "
16464 "type is missing... skipping validation of "
16465 "the value constraint", NULL, NULL);
16466 return;
16467 }
16468 /*
16469 * Ensure there's a validation context.
16470 */
16471 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16472 return;
16473
16474 type = decl->subtypes;
16475
16476 if (decl->node != NULL) {
16477 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
16478 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
16479 else
16480 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
16481 }
16482 ctxt->vctxt->node = node;
16483 ctxt->vctxt->cur = NULL;
16484 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
16485 node);
16486 if (ret == 0) {
16487 /*
16488 * Consume the computed value.
16489 */
16490 decl->defVal = ctxt->vctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016491 ctxt->vctxt->value = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016492 } else if (ret < 0) {
16493 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16494 NULL, NULL, node,
16495 "Internal error: xmlSchemaElemCheckValConstr, "
16496 "failed to validate the value constraint of the "
16497 "element declaration '%s'",
16498 decl->name);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016499 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016500 }
16501}
16502
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016503
16504/**
16505 * xmlSchemaMiscRefFixup:
16506 * @item: an schema component
16507 * @ctxt: a schema parser context
16508 * @name: the internal name of the component
16509 *
16510 * Resolves references of misc. schema components.
16511 */
16512static void
16513xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
16514 xmlSchemaParserCtxtPtr ctxt,
16515 const xmlChar * name ATTRIBUTE_UNUSED)
16516{
16517 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
16518 if ((item->children != NULL) &&
16519 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
16520 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
16521 xmlSchemaTreeItemPtr refItem;
16522 /*
16523 * Resolve the reference.
16524 */
16525 item->children = NULL;
16526 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
16527 ref->itemType, ref->name, ref->targetNamespace);
16528 if (refItem == NULL) {
16529 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
16530 NULL, NULL, GET_NODE(item), "ref", ref->name,
16531 ref->targetNamespace, ref->itemType, NULL);
16532 } else {
16533 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
16534 /*
16535 * Assign the model group of the model group definition
16536 * to the particle's "term".
16537 */
16538 item->children = refItem->children;
16539 } else
16540 item->children = refItem;
16541 }
16542 }
16543 }
16544}
16545
16546
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016547/**
16548 * xmlSchemaAttrFixup:
16549 * @item: an schema attribute declaration/use.
16550 * @ctxt: a schema parser context
16551 * @name: the name of the attribute
16552 *
16553 * Fixes finish doing the computations on attribute declarations/uses.
16554 */
16555static void
16556xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
16557 xmlSchemaParserCtxtPtr ctxt,
16558 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000016559{
Daniel Veillardc0826a72004-08-10 14:17:33 +000016560 /*
16561 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016562 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000016563 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016564 /*
16565 * The simple type definition corresponding to the <simpleType> element
16566 * information item in the [children], if present, otherwise the simple
16567 * type definition ·resolved· to by the ·actual value· of the type
16568 * [attribute], if present, otherwise the ·simple ur-type definition·.
16569 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016570 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000016571 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016572 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
16573 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016574 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016575 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016576 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000016577
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016578 type = xmlSchemaGetType(ctxt->schema, item->typeName,
16579 item->typeNs);
16580 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016581 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016582 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016583 NULL, (xmlSchemaTypePtr) item, item->node,
16584 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016585 XML_SCHEMA_TYPE_SIMPLE, NULL);
16586 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016587 item->subtypes = type;
16588
16589 } else if (item->ref != NULL) {
16590 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000016591
Daniel Veillardc0826a72004-08-10 14:17:33 +000016592 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016593 * We have an attribute use here; assign the referenced
16594 * attribute declaration.
16595 */
16596 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016597 * TODO: Evaluate, what errors could occur if the declaration is not
16598 * found. It might be possible that the "typefixup" might crash if
16599 * no ref declaration was found.
16600 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016601 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
16602 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016603 xmlSchemaPResCompAttrErr(ctxt,
16604 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016605 NULL, (xmlSchemaTypePtr) item, item->node,
16606 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016607 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016608 return;
16609 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016610 item->refDecl = decl;
16611 xmlSchemaAttrFixup(decl, ctxt, NULL);
16612
16613 item->subtypes = decl->subtypes;
16614 /*
16615 * Attribute Use Correct
16616 * au-props-correct.2: If the {attribute declaration} has a fixed
16617 * {value constraint}, then if the attribute use itself has a
16618 * {value constraint}, it must also be fixed and its value must match
16619 * that of the {attribute declaration}'s {value constraint}.
16620 */
16621 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
16622 (item->defValue != NULL)) {
16623 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
16624 (!xmlStrEqual(item->defValue, decl->defValue))) {
16625 xmlSchemaPCustomErr(ctxt,
16626 XML_SCHEMAP_AU_PROPS_CORRECT_2,
16627 NULL, NULL, item->node,
16628 "The value constraint must be fixed "
16629 "and match the referenced attribute "
16630 "declarations's value constraint '%s'",
16631 decl->defValue);
16632 }
16633 /*
16634 * FUTURE: One should change the values of the attr. use
16635 * if ever validation should be attempted even if the
16636 * schema itself was not fully valid.
16637 */
16638 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016639 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016640 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
16641 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016642}
16643
16644/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016645 * xmlSchemaResolveIDCKeyRef:
16646 * @idc: the identity-constraint definition
16647 * @ctxt: the schema parser context
16648 * @name: the attribute name
16649 *
16650 * Resolve keyRef references to key/unique IDCs.
16651 */
16652static void
16653xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
16654 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000016655 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016656{
16657 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
16658 return;
16659 if (idc->ref->name != NULL) {
16660 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
16661 ctxt->schema->idcDef,
16662 idc->ref->name,
16663 idc->ref->targetNamespace);
16664 if (idc->ref->item == NULL) {
16665 /*
16666 * TODO: It is actually not an error to fail to resolve.
16667 */
16668 xmlSchemaPResCompAttrErr(ctxt,
16669 XML_SCHEMAP_SRC_RESOLVE,
16670 NULL, (xmlSchemaTypePtr) idc, idc->node,
16671 "refer", idc->ref->name,
16672 idc->ref->targetNamespace,
16673 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
16674 return;
16675 }
16676 }
16677}
16678
16679/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016680 * xmlSchemaParse:
16681 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000016682 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000016683 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000016684 * XML Shema struture which can be used to validate instances.
16685 * *WARNING* this interface is highly subject to change
16686 *
16687 * Returns the internal XML Schema structure built from the resource or
16688 * NULL in case of error
16689 */
16690xmlSchemaPtr
16691xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
16692{
16693 xmlSchemaPtr ret = NULL;
16694 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000016695 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000016696 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000016697
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016698 /*
16699 * This one is used if the schema to be parsed was specified via
16700 * the API; i.e. not automatically by the validated instance document.
16701 */
16702
Daniel Veillard4255d502002-04-16 15:50:10 +000016703 xmlSchemaInitTypes();
16704
Daniel Veillard6045c902002-10-09 21:13:59 +000016705 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000016706 return (NULL);
16707
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000016708 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000016709 ctxt->counter = 0;
16710 ctxt->container = NULL;
16711
16712 /*
16713 * First step is to parse the input document into an DOM/Infoset
16714 */
Daniel Veillard6045c902002-10-09 21:13:59 +000016715 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000016716 doc = xmlReadFile((const char *) ctxt->URL, NULL,
16717 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016718 if (doc == NULL) {
16719 xmlSchemaPErr(ctxt, NULL,
16720 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016721 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016722 ctxt->URL, NULL);
16723 return (NULL);
16724 }
Daniel Veillard6045c902002-10-09 21:13:59 +000016725 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000016726 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
16727 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016728 if (doc == NULL) {
16729 xmlSchemaPErr(ctxt, NULL,
16730 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016731 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016732 NULL, NULL);
16733 return (NULL);
16734 }
16735 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000016736 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000016737 } else if (ctxt->doc != NULL) {
16738 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000016739 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000016740 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016741 xmlSchemaPErr(ctxt, NULL,
16742 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016743 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016744 NULL, NULL);
16745 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000016746 }
16747
16748 /*
16749 * Then extract the root and Schema parse it
16750 */
16751 root = xmlDocGetRootElement(doc);
16752 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016753 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
16754 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016755 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000016756 if (!preserve) {
16757 xmlFreeDoc(doc);
16758 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016759 return (NULL);
16760 }
16761
16762 /*
16763 * Remove all the blank text nodes
16764 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000016765 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000016766
16767 /*
16768 * Then do the parsing for good
16769 */
16770 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000016771 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000016772 if (!preserve) {
16773 xmlFreeDoc(doc);
16774 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016775 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000016776 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016777 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000016778 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000016779 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016780 ctxt->ctxtType = NULL;
16781 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016782
16783
16784 if (ret->volatiles != NULL) {
16785 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
16786 int i;
16787 xmlSchemaTreeItemPtr item;
16788
16789 for (i = 0; i < list->nbItems; i++) {
16790 item = (xmlSchemaTreeItemPtr) list->items[i];
16791 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
16792 xmlSchemaMiscRefFixup(item, ctxt, NULL);
16793 /* xmlHashScan(ret->miscComps,
16794 (xmlHashScanner) xmlSchemaMiscRefFixup, ctxt); */
16795 }
16796 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016797 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000016798 * Then fixup all attributes declarations
16799 */
16800 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
16801
16802 /*
16803 * Then fixup all attributes group declarations
16804 */
16805 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
16806 ctxt);
16807
16808 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016809 * Resolve identity-constraint keyRefs.
16810 */
16811 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016812 /*
16813 * Check type defnitions for circular references.
16814 */
16815 xmlHashScan(ret->typeDecl, (xmlHashScanner)
16816 xmlSchemaCheckTypeDefCircular, ctxt);
16817 /*
16818 * Check model groups defnitions for circular references.
16819 */
16820 xmlHashScan(ret->groupDecl, (xmlHashScanner)
16821 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016822
16823 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016824 * Check attribute groups for circular references.
16825 */
16826 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
16827 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016828
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016829 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016830 * Then fix references of element declaration; apply constraints.
16831 */
16832 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016833 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000016834
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000016835 /*
16836 * We will stop here if the schema was not valid to avoid internal errors
16837 * on missing sub-components. This is not conforming to the spec, since it
16838 * allows missing components, but it might make further processing crash.
16839 * So see it as a very strict handling, which might be made more lax in the
16840 * future.
16841 */
16842 if (ctxt->nberrors != 0)
16843 goto exit;
16844 /*
16845 * Then fixup all types properties
16846 */
16847 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016848
Daniel Veillard4255d502002-04-16 15:50:10 +000016849 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016850 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000016851 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016852 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016853 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016854
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016855 /*
16856 * Validate the value constraint of attribute declarations/uses.
16857 */
16858 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
16859
16860 /*
16861 * Validate the value constraint of element declarations.
16862 */
16863 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
16864
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000016865exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000016866 if (ctxt->nberrors != 0) {
16867 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016868 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000016869 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016870 return (ret);
16871}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016872
Daniel Veillard4255d502002-04-16 15:50:10 +000016873/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000016874 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000016875 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000016876 * @err: the error callback
16877 * @warn: the warning callback
16878 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000016879 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000016880 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000016881 */
16882void
16883xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016884 xmlSchemaValidityErrorFunc err,
16885 xmlSchemaValidityWarningFunc warn, void *ctx)
16886{
Daniel Veillard4255d502002-04-16 15:50:10 +000016887 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016888 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016889 ctxt->error = err;
16890 ctxt->warning = warn;
16891 ctxt->userData = ctx;
16892}
16893
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000016894/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000016895 * xmlSchemaGetParserErrors:
16896 * @ctxt: a XMl-Schema parser context
16897 * @err: the error callback result
16898 * @warn: the warning callback result
16899 * @ctx: contextual data for the callbacks result
16900 *
16901 * Get the callback information used to handle errors for a parser context
16902 *
16903 * Returns -1 in case of failure, 0 otherwise
16904 */
16905int
16906xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
16907 xmlSchemaValidityErrorFunc * err,
16908 xmlSchemaValidityWarningFunc * warn, void **ctx)
16909{
16910 if (ctxt == NULL)
16911 return(-1);
16912 if (err != NULL)
16913 *err = ctxt->error;
16914 if (warn != NULL)
16915 *warn = ctxt->warning;
16916 if (ctx != NULL)
16917 *ctx = ctxt->userData;
16918 return(0);
16919}
16920
16921/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000016922 * xmlSchemaFacetTypeToString:
16923 * @type: the facet type
16924 *
16925 * Convert the xmlSchemaTypeType to a char string.
16926 *
16927 * Returns the char string representation of the facet type if the
16928 * type is a facet and an "Internal Error" string otherwise.
16929 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016930static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000016931xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
16932{
16933 switch (type) {
16934 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016935 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016936 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016937 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016938 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016939 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016940 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016941 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016942 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016943 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016944 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016945 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016946 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016947 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016948 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016949 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016950 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016951 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016952 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016953 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016954 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016955 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016956 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016957 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000016958 default:
16959 break;
16960 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016961 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000016962}
16963
Daniel Veillardc0826a72004-08-10 14:17:33 +000016964static int
16965xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
16966{
16967 xmlSchemaTypePtr anc;
16968
16969 /*
16970 * The normalization type can be changed only for types which are derived
16971 * from xsd:string.
16972 */
16973 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000016974 if (type->builtInType == XML_SCHEMAS_STRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016975 return(XML_SCHEMAS_FACET_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000016976 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016977 return(XML_SCHEMAS_FACET_REPLACE);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000016978 else if (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
16979 /*
16980 * Note that we assume a whitespace of preserve for anySimpleType.
16981 */
16982 return(XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016983 else {
16984 /*
16985 * For all ·atomic· datatypes other than string (and types ·derived·
16986 * by ·restriction· from it) the value of whiteSpace is fixed to
16987 * collapse
16988 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016989 return(XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016990 }
16991 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
16992 /*
16993 * For list types the facet "whiteSpace" is fixed to "collapse".
16994 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016995 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016996 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016997 return (XML_SCHEMAS_FACET_UNKNOWN);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016998 } else if (type->facetSet != NULL) {
16999 xmlSchemaTypePtr anyST;
17000 xmlSchemaFacetLinkPtr lin;
17001
17002 /*
17003 * Atomic types.
17004 */
17005 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17006 anc = type->baseType;
17007 do {
17008 /*
17009 * For all ·atomic· datatypes other than string (and types ·derived·
17010 * by ·restriction· from it) the value of whiteSpace is fixed to
17011 * collapse
17012 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017013 if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17014 (anc->builtInType == XML_SCHEMAS_NORMSTRING)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017015
17016 lin = type->facetSet;
17017 do {
17018 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017019 return(lin->facet->whitespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017020 }
17021 lin = lin->next;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017022 } while (lin != NULL);
17023 if (anc->builtInType == XML_SCHEMAS_NORMSTRING)
17024 return (XML_SCHEMAS_FACET_REPLACE);
17025 else
17026 return (XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017027 }
17028 anc = anc->baseType;
17029 } while (anc != anyST);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017030 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017031 }
17032 return (-1);
17033}
17034
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017035/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000017036 * xmlSchemaValidateFacetsInternal:
17037 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000017038 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000017039 * @facets: the list of facets to check
17040 * @value: the lexical repr of the value to validate
17041 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000017042 * @fireErrors: if 0, only internal errors will be fired;
17043 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000017044 *
17045 * Check a value against all facet conditions
17046 *
17047 * Returns 0 if the element is schemas valid, a positive error code
17048 * number otherwise and -1 in case of internal or API error.
17049 */
17050static int
17051xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017052 xmlSchemaTypePtr type,
17053 const xmlChar * value,
17054 unsigned long length,
17055 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000017056{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017057 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017058 xmlNodePtr node;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017059 xmlSchemaTypePtr biType; /* The build-in type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017060 xmlSchemaTypePtr tmpType;
17061 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000017062 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017063 xmlSchemaFacetPtr facet;
17064 unsigned long len = 0;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017065 xmlSchemaWhitespaceValueType ws;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017066
17067 ws = (xmlSchemaWhitespaceValueType) xmlSchemaGetWhiteSpaceFacetValue(type);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017068
Daniel Veillardc0826a72004-08-10 14:17:33 +000017069#ifdef DEBUG_UNION_VALIDATION
17070 printf("Facets of type: '%s'\n", (const char *) type->name);
17071 printf(" fireErrors: %d\n", fireErrors);
17072#endif
17073
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017074 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017075 /*
17076 * NOTE: Do not jump away, if the facetSet of the given type is
17077 * empty: until now, "pattern" facets of the *base types* need to
17078 * be checked as well.
17079 */
17080 biType = type->baseType;
17081 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
17082 biType = biType->baseType;
17083 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017084 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017085 "Internal error: xmlSchemaValidateFacetsInternal, "
17086 "the base type axis of the given type '%s' does not resolve to "
17087 "a built-in type.\n",
17088 type->name, NULL);
17089 return (-1);
17090 }
17091
17092 if (type->facetSet != NULL) {
17093 facetLink = type->facetSet;
17094 while (facetLink != NULL) {
17095 facet = facetLink->facet;
17096 /*
17097 * Skip the pattern "whiteSpace": it is used to
17098 * format the character content beforehand.
17099 */
17100 switch (facet->type) {
17101 case XML_SCHEMA_FACET_WHITESPACE:
17102 case XML_SCHEMA_FACET_PATTERN:
17103 case XML_SCHEMA_FACET_ENUMERATION:
17104 break;
17105 case XML_SCHEMA_FACET_LENGTH:
17106 case XML_SCHEMA_FACET_MINLENGTH:
17107 case XML_SCHEMA_FACET_MAXLENGTH:
17108 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
17109 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017110 value, length, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017111 len = length;
17112 } else
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017113 ret = xmlSchemaValidateLengthFacetWhtsp(facet,
17114 (xmlSchemaValType) biType->builtInType,
17115 value, ctxt->value, &len, ws);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017116 break;
17117 default:
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017118 ret = xmlSchemaValidateFacetWhtsp(facet, ws,
17119 biType->builtInType, value, ctxt->value, ws);
17120 /*
17121 * ret = xmlSchemaValidateFacet(biType, facet, value,
17122 * ctxt->value);
17123 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017124 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000017125 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017126 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017127 "Internal error: xmlSchemaValidateFacetsInternal, "
17128 "validating facet of type '%s'.\n",
17129 type->name, NULL);
17130 break;
17131 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017132 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017133 type, facet, NULL, NULL, NULL, NULL);
17134 }
17135
17136 facetLink = facetLink->next;
17137 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017138
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017139 }
17140
Daniel Veillardc0826a72004-08-10 14:17:33 +000017141 if (ret >= 0) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017142 xmlSchemaWhitespaceValueType fws;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017143 int found = 0;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017144 /*
17145 * Process enumerations. Facet values are in the value space
17146 * of the defining type's base type. This seems to be a bug in the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017147 * XML Schema 1.0 spec. Use the whitespace type of the base type.
17148 * Only the first set of enumerations in the ancestor-or-self axis
17149 * is used for validation.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017150 */
17151 tmpType = type;
17152 do {
17153 /*
17154 * Use the whitespace type of the base type.
17155 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017156 fws = (xmlSchemaWhitespaceValueType)
17157 xmlSchemaGetWhiteSpaceFacetValue(tmpType->baseType);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017158 retFacet = 0;
17159 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
17160 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017161 continue;
17162 found = 1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017163 retFacet = xmlSchemaValidateFacetWhtsp(facet, fws,
17164 biType->builtInType, value, ctxt->value, ws);
17165 if (retFacet == 0)
17166 break;
17167 else if (retFacet < 0) {
17168 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
17169 "Internal error: xmlSchemaValidateFacetsInternal, "
17170 "validating enumeration facet '%s' of type '%s'.\n",
17171 facet->value, tmpType->name);
17172 ret = -1;
17173 break;
17174 }
17175 }
17176 if (retFacet <= 0)
17177 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017178 tmpType = tmpType->baseType;
17179 } while ((! found) && (tmpType != NULL) &&
17180 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017181 if (retFacet > 0) {
Kasimier T. Buchcik53b5e052005-03-24 11:05:13 +000017182 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017183 if (fireErrors) {
17184 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, NULL,
17185 NULL, NULL, NULL, NULL);
17186 }
17187 }
17188 }
17189
17190 if (ret >= 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017191 /*
17192 * Process patters. Pattern facets are ORed at type level
17193 * and ANDed if derived. Walk the base type axis.
17194 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017195 tmpType = type;
17196 facet = NULL;
17197 do {
17198 retFacet = 0;
17199 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017200 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017201 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
17202 continue;
17203 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
17204 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017205 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017206 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017207 else if (retFacet < 0) {
17208 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
17209 "Internal error: xmlSchemaValidateFacetsInternal, "
17210 "validating 'pattern' facet '%s' of type '%s'.\n",
17211 facetLink->facet->value, tmpType->name);
17212 ret = -1;
17213 break;
17214 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000017215 /* Save the last non-validating facet. */
17216 facet = facetLink->facet;
17217 }
17218 if (retFacet != 0)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017219 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017220 tmpType = tmpType->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017221 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017222 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017223 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
17224 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017225 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017226 NULL, NULL, NULL, NULL);
17227 }
17228 }
17229 }
17230
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017231 return (ret);
17232}
17233
Daniel Veillard4255d502002-04-16 15:50:10 +000017234/************************************************************************
17235 * *
17236 * Simple type validation *
17237 * *
17238 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000017239
Daniel Veillard4255d502002-04-16 15:50:10 +000017240
17241/************************************************************************
17242 * *
17243 * DOM Validation code *
17244 * *
17245 ************************************************************************/
17246
Daniel Veillard4255d502002-04-16 15:50:10 +000017247static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017248 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000017249 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017250static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017251 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017252 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017253 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000017254
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017255static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017256static int xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017257
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017258/**
17259 * xmlSchemaGetFreshElemInfo:
17260 * @vctxt: the schema validation context
17261 *
17262 * Creates/reuses and initializes the element info item for
17263 * the currect tree depth.
17264 *
17265 * Returns the element info item or NULL on API or internal errors.
17266 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017267static xmlSchemaNodeInfoPtr
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017268xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt,
17269 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017270{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017271 xmlSchemaNodeInfoPtr info = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017272
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017273 if (depth > vctxt->sizeElemInfos) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017274 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017275 "Internal error: xmlSchemaGetFreshElemInfo, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017276 "an inconsistent depth encountered.\n",
17277 NULL, NULL);
17278 return (NULL);
17279 }
17280 if (vctxt->elemInfos == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017281 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
17282 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017283 if (vctxt->elemInfos == NULL) {
17284 xmlSchemaVErrMemory(vctxt,
17285 "allocating the element info array", NULL);
17286 return (NULL);
17287 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017288 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017289 vctxt->sizeElemInfos = 10;
17290 } else if (vctxt->sizeElemInfos == vctxt->depth) {
17291 int i = vctxt->sizeElemInfos;
17292
17293 vctxt->sizeElemInfos *= 2;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017294 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017295 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017296 sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017297 if (vctxt->elemInfos == NULL) {
17298 xmlSchemaVErrMemory(vctxt,
17299 "re-allocating the element info array", NULL);
17300 return (NULL);
17301 }
17302 /*
17303 * We need the new memory to be NULLed.
17304 * TODO: Use memset instead?
17305 */
17306 for (; i < vctxt->sizeElemInfos; i++)
17307 vctxt->elemInfos[i] = NULL;
17308 } else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017309 info = vctxt->elemInfos[depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017310
17311 if (info == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017312 info = (xmlSchemaNodeInfoPtr)
17313 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017314 if (info == NULL) {
17315 xmlSchemaVErrMemory(vctxt,
17316 "allocating an element info", NULL);
17317 return (NULL);
17318 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017319 vctxt->elemInfos[depth] = info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017320 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017321 memset(info, 0, sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017322 info->depth = depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017323
17324 return (info);
17325}
Daniel Veillard3646d642004-06-02 19:19:14 +000017326
17327/**
17328 * xmlSchemaFreeAttrStates:
17329 * @state: a list of attribute states
17330 *
17331 * Free the given list of attribute states
17332 *
17333 */
17334static void
17335xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
17336{
17337 xmlSchemaAttrStatePtr tmp;
17338 while (state != NULL) {
17339 tmp = state;
17340 state = state->next;
17341 xmlFree(tmp);
17342 }
17343}
17344
Daniel Veillard4255d502002-04-16 15:50:10 +000017345/**
17346 * xmlSchemaRegisterAttributes:
17347 * @ctxt: a schema validation context
17348 * @attrs: a list of attributes
17349 *
17350 * Register the list of attributes as the set to be validated on that element
17351 *
17352 * Returns -1 in case of error, 0 otherwise
17353 */
17354static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017355xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
17356{
Daniel Veillard3646d642004-06-02 19:19:14 +000017357 xmlSchemaAttrStatePtr tmp;
17358
17359 ctxt->attr = NULL;
17360 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000017361 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017362 if ((attrs->ns != NULL) &&
17363 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
17364 attrs = attrs->next;
17365 continue;
17366 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000017367 tmp = (xmlSchemaAttrStatePtr)
17368 xmlMalloc(sizeof(xmlSchemaAttrState));
17369 if (tmp == NULL) {
17370 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
17371 return (-1);
17372 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017373 tmp->attr = attrs;
17374 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
17375 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017376 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000017377 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017378 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000017379 else
17380 ctxt->attrTop->next = tmp;
17381 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017382 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000017383 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017384 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000017385}
17386
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000017387#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000017388/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017389 * xmlSchemaValidateCheckNodeList
17390 * @nodelist: the list of nodes
17391 *
17392 * Check the node list is only made of text nodes and entities pointing
17393 * to text nodes
17394 *
17395 * Returns 1 if true, 0 if false and -1 in case of error
17396 */
17397static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017398xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
17399{
Daniel Veillard4255d502002-04-16 15:50:10 +000017400 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017401 if (nodelist->type == XML_ENTITY_REF_NODE) {
17402 TODO /* implement recursion in the entity content */
17403 }
17404 if ((nodelist->type != XML_TEXT_NODE) &&
17405 (nodelist->type != XML_COMMENT_NODE) &&
17406 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000017407 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017408 return (0);
17409 }
17410 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000017411 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017412 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000017413}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000017414#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000017415
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017416static void
17417xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
17418{
17419 int i, nbItems;
17420 xmlSchemaTypePtr item, *items;
17421
17422
17423 /*
17424 * During the Assemble of the schema ctxt->curItems has
17425 * been filled with the relevant new items. Fix those up.
17426 */
17427 nbItems = ctxt->assemble->nbItems;
17428 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
17429
17430 for (i = 0; i < nbItems; i++) {
17431 item = items[i];
17432 switch (item->type) {
17433 case XML_SCHEMA_TYPE_ATTRIBUTE:
17434 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
17435 break;
17436 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017437 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017438 NULL, NULL, NULL);
17439 break;
17440 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
17441 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
17442 ctxt, NULL);
17443 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017444 case XML_SCHEMA_TYPE_PARTICLE:
17445 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017446 default:
17447 break;
17448 }
17449 }
17450 /*
17451 * Circularity checks.
17452 */
17453 for (i = 0; i < nbItems; i++) {
17454 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017455 switch (item->type) {
17456 case XML_SCHEMA_TYPE_COMPLEX:
17457 case XML_SCHEMA_TYPE_SIMPLE:
17458 xmlSchemaCheckTypeDefCircular(
17459 (xmlSchemaTypePtr) item, ctxt, NULL);
17460 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017461 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017462 xmlSchemaCheckGroupDefCircular(
17463 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017464 break;
17465 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
17466 xmlSchemaCheckAttributeGroupCircular(
17467 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
17468 break;
17469 default:
17470 break;
17471 }
17472 }
17473 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017474 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017475 */
17476 for (i = 0; i < nbItems; i++) {
17477 item = items[i];
17478 switch (item->type) {
17479 case XML_SCHEMA_TYPE_SIMPLE:
17480 case XML_SCHEMA_TYPE_COMPLEX:
17481 xmlSchemaTypeFixup(item, ctxt, NULL);
17482 break;
17483 default:
17484 break;
17485 }
17486 }
17487 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017488 * Build the content model for complex types.
17489 */
17490 for (i = 0; i < nbItems; i++) {
17491 item = items[i];
17492 switch (item->type) {
17493 case XML_SCHEMA_TYPE_COMPLEX:
17494 xmlSchemaBuildContentModel(item, ctxt, NULL);
17495 break;
17496 default:
17497 break;
17498 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017499 }
17500 /*
17501 * Validate value contraint values.
17502 */
17503 for (i = 0; i < nbItems; i++) {
17504 item = items[i];
17505 switch (item->type) {
17506 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017507 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
17508 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017509 break;
17510 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017511 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item,
17512 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017513 break;
17514 default:
17515 break;
17516 }
17517 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017518}
17519
17520/**
17521 * xmlSchemaAssembleByLocation:
17522 * @pctxt: a schema parser context
17523 * @vctxt: a schema validation context
17524 * @schema: the existing schema
17525 * @node: the node that fired the assembling
17526 * @nsName: the namespace name of the new schema
17527 * @location: the location of the schema
17528 *
17529 * Expands an existing schema by an additional schema.
17530 *
17531 * Returns 0 if the new schema is correct, a positive error code
17532 * number otherwise and -1 in case of an internal or API error.
17533 */
17534static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017535xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
17536 xmlSchemaPtr schema,
17537 xmlNodePtr node,
17538 const xmlChar *nsName,
17539 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017540{
17541 const xmlChar *targetNs, *oldtns;
17542 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017543 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017544 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017545 xmlSchemaParserCtxtPtr pctxt;
17546
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017547 /*
17548 * This should be used:
17549 * 1. on <import>(s)
17550 * 2. if requested by the validated instance
17551 * 3. if requested via the API
17552 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017553 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017554 return (-1);
17555 /*
17556 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017557 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017558 if ((vctxt->pctxt == NULL) &&
17559 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
17560 xmlSchemaVErr(vctxt, node,
17561 XML_SCHEMAV_INTERNAL,
17562 "Internal error: xmlSchemaAssembleByLocation, "
17563 "failed to create a temp. parser context.\n",
17564 NULL, NULL);
17565 return (-1);
17566 }
17567 pctxt = vctxt->pctxt;
17568 /*
17569 * Set the counter to produce unique names for anonymous items.
17570 */
17571 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017572 /*
17573 * Acquire the schema document.
17574 */
17575 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
17576 nsName, location, &doc, &targetNs, 0);
17577 if (ret != 0) {
17578 if (doc != NULL)
17579 xmlFreeDoc(doc);
17580 } else if (doc != NULL) {
17581 docElem = xmlDocGetRootElement(doc);
17582 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017583 * Create new assemble info.
17584 */
17585 if (pctxt->assemble == NULL) {
17586 pctxt->assemble = xmlSchemaNewAssemble();
17587 if (pctxt->assemble == NULL) {
17588 xmlSchemaVErrMemory(vctxt,
17589 "Memory error: xmlSchemaAssembleByLocation, "
17590 "allocating assemble info", NULL);
17591 xmlFreeDoc(doc);
17592 return (-1);
17593 }
17594 }
17595 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017596 * Save and reset the context & schema.
17597 */
17598 oldflags = schema->flags;
17599 oldtns = schema->targetNamespace;
17600 olddoc = schema->doc;
17601
17602 xmlSchemaClearSchemaDefaults(schema);
17603 schema->targetNamespace = targetNs;
17604 /* schema->nbCurItems = 0; */
17605 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017606 pctxt->ctxtType = NULL;
17607 pctxt->parentItem = NULL;
17608
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017609 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
17610 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017611 xmlSchemaPostSchemaAssembleFixup(pctxt);
17612 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017613 * Set the counter of items.
17614 */
17615 schema->counter = pctxt->counter;
17616 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017617 * Free the list of assembled components.
17618 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017619 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017620 /*
17621 * Restore the context & schema.
17622 */
17623 schema->flags = oldflags;
17624 schema->targetNamespace = oldtns;
17625 schema->doc = olddoc;
17626 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017627 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017628 return (ret);
17629}
17630
17631/**
17632 * xmlSchemaAssembleByXSIAttr:
17633 * @vctxt: a schema validation context
17634 * @xsiAttr: an xsi attribute
17635 * @noNamespace: whether a schema with no target namespace is exptected
17636 *
17637 * Expands an existing schema by an additional schema using
17638 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
17639 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
17640 * must be set to 1.
17641 *
17642 * Returns 0 if the new schema is correct, a positive error code
17643 * number otherwise and -1 in case of an internal or API error.
17644 */
17645static int
17646xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
17647 xmlAttrPtr xsiAttr,
17648 int noNamespace)
17649{
17650 xmlChar *value;
17651 const xmlChar *cur, *end;
17652 const xmlChar *nsname = NULL, *location;
17653 int count = 0;
17654 int ret = 0;
17655
17656 if (xsiAttr == NULL) {
17657 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
17658 NULL, NULL,
17659 "Internal error: xmlSchemaAssembleByXSIAttr, "
17660 "bad arguments", NULL);
17661 return (-1);
17662 }
17663 /*
17664 * Parse the value; we will assume an even number of values
17665 * to be given (this is how Xerces and XSV work).
17666 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017667 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017668 cur = value;
17669 do {
17670 if (noNamespace != 1) {
17671 /*
17672 * Get the namespace name.
17673 */
17674 while (IS_BLANK_CH(*cur))
17675 cur++;
17676 end = cur;
17677 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
17678 end++;
17679 if (end == cur)
17680 break;
17681 count++;
17682 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
17683 cur = end;
17684 }
17685 /*
17686 * Get the URI.
17687 */
17688 while (IS_BLANK_CH(*cur))
17689 cur++;
17690 end = cur;
17691 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
17692 end++;
17693 if (end == cur)
17694 break;
17695 count++;
17696 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017697 cur = end;
17698 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017699 xsiAttr->parent, nsname, location);
17700 if (ret == -1) {
17701 xmlSchemaVCustomErr(vctxt,
17702 XML_SCHEMAV_INTERNAL,
17703 (xmlNodePtr) xsiAttr, NULL,
17704 "Internal error: xmlSchemaAssembleByXSIAttr, "
17705 "assembling schemata", NULL);
17706 if (value != NULL)
17707 xmlFree(value);
17708 return (-1);
17709 }
17710 } while (*cur != 0);
17711 if (value != NULL)
17712 xmlFree(value);
17713 return (ret);
17714}
17715
17716/**
17717 * xmlSchemaAssembleByXSIElem:
17718 * @vctxt: a schema validation context
17719 * @elem: an element node possibly holding xsi attributes
17720 * @noNamespace: whether a schema with no target namespace is exptected
17721 *
17722 * Assembles an existing schema by an additional schema using
17723 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
17724 * of the given @elem.
17725 *
17726 * Returns 0 if the new schema is correct, a positive error code
17727 * number otherwise and -1 in case of an internal or API error.
17728 */
17729static int
17730xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
17731 xmlNodePtr elem)
17732{
17733 int ret = 0, retNs = 0;
17734 xmlAttrPtr attr;
17735
17736 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
17737 if (attr != NULL) {
17738 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
17739 if (retNs == -1)
17740 return (-1);
17741 }
17742 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
17743 if (attr != NULL) {
17744 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
17745 if (ret == -1)
17746 return (-1);
17747 }
17748 if (retNs != 0)
17749 return (retNs);
17750 else
17751 return (ret);
17752}
17753
Daniel Veillard4255d502002-04-16 15:50:10 +000017754/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017755 * xmlSchemaValidateCallback:
17756 * @ctxt: a schema validation context
17757 * @name: the name of the element detected (might be NULL)
17758 * @type: the type
17759 *
17760 * A transition has been made in the automata associated to an element
17761 * content model
17762 */
17763static void
17764xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017765 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017766 xmlSchemaBasicItemPtr item, xmlNodePtr node)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017767{
Daniel Veillard4255d502002-04-16 15:50:10 +000017768 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017769
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017770 /*
17771 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
17772 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017773 ctxt->node = node;
17774 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017775
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017776 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017777
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017778 /*
17779 * Assemble new schemata using xsi.
17780 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017781 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017782 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017783
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017784 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
17785 if (ret == -1) {
17786 xmlSchemaVCustomErr(ctxt,
17787 XML_SCHEMAV_INTERNAL,
17788 ctxt->node, NULL,
17789 "Internal error: xmlSchemaValidateElement, "
17790 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017791 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017792 }
17793 /*
17794 * NOTE: We won't react on schema parser errors here.
17795 * TODO: But a warning would be nice.
17796 */
17797 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017798 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017799 case XML_SCHEMA_TYPE_ELEMENT: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017800#ifdef DEBUG_CONTENT
17801 xmlGenericError(xmlGenericErrorContext,
17802 "xmlSchemaValidateCallback: %s, %s, %s\n",
17803 name, ((xmlSchemaElementPtr) item)->name, node->name);
17804#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017805 xmlSchemaValidateElementByDeclaration(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017806 (xmlSchemaElementPtr) item);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017807 break;
17808 }
17809 case XML_SCHEMA_TYPE_ANY:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017810#ifdef DEBUG_CONTENT
17811 xmlGenericError(xmlGenericErrorContext,
17812 "xmlSchemaValidateCallback: %s, <any>, %s\n",
17813 name, node->name);
17814#endif
17815 xmlSchemaValidateElementByWildcard(ctxt,
17816 (xmlSchemaWildcardPtr) item);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017817 break;
17818 default:
17819 break;
17820 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017821leave:
17822
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017823 xmlSchemaEndElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000017824 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017825}
Daniel Veillard4255d502002-04-16 15:50:10 +000017826
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017827static int
17828xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
17829 const xmlChar *value,
17830 xmlSchemaValPtr *val,
17831 xmlNodePtr node)
17832{
17833 int ret;
17834
17835 ret = xmlValidateQName(value, 1);
17836 if (ret != 0)
17837 return (ret);
17838
17839 {
17840 xmlChar *uri = NULL;
17841 xmlChar *local = NULL;
17842 xmlChar *prefix;
17843
17844 local = xmlSplitQName2(value, &prefix);
17845 if (prefix != NULL) {
17846 xmlNsPtr ns;
17847
17848 /*
17849 * TODO: Make this streamable.
17850 */
17851 if ((node == NULL) || (node->doc == NULL)) {
17852 xmlFree(prefix);
17853 xmlFree(local);
17854 return (3);
17855 }
17856
17857 ns = xmlSearchNs(node->doc, node, prefix);
17858 if (ns == NULL) {
17859 xmlFree(prefix);
17860 xmlFree(local);
17861 return (1);
17862 }
17863 }
17864 if (prefix != NULL) {
17865 if (xmlHashLookup2(vctxt->schema->notaDecl, local, uri) == NULL)
17866 ret = 1;
17867 } else if (xmlHashLookup2(vctxt->schema->notaDecl, value,
17868 NULL) == NULL)
17869 ret = 1;
17870
17871 if ((ret == 0) && (val != NULL)) {
17872 if (prefix != NULL) {
17873 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST local,
17874 BAD_CAST xmlStrdup(uri));
17875 local = NULL;
17876 } else
17877 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST xmlStrdup(value),
17878 NULL);
17879 if (*val == NULL)
17880 ret = -1;
17881 }
17882 if (local != NULL)
17883 xmlFree(local);
17884 }
17885
17886 return (ret);
17887}
17888
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017889static xmlSchemaTypePtr
17890xmlSchemaGetSimpleContentType(xmlSchemaTypePtr complexType)
17891{
17892 xmlSchemaTypePtr ret;
17893
17894 if (complexType->type != XML_SCHEMA_TYPE_COMPLEX)
17895 return (NULL);
17896 if (complexType->contentTypeDef != NULL)
17897 return (complexType->contentTypeDef);
17898 /*
17899 * TODO: This is only a workaround until the simple content
17900 * type is computed for complex types with simple content.
17901 */
17902 ret = complexType->baseType;
17903 while (ret != NULL) {
17904 if (IS_SIMPLE_TYPE(ret))
17905 return (ret);
17906 if (ret->builtInType == XML_SCHEMAS_ANYTYPE)
17907 return (NULL);
17908 if ((ret->type == XML_SCHEMA_TYPE_COMPLEX) &&
17909 (ret->contentTypeDef != NULL))
17910 ret = ret->contentTypeDef;
17911 else
17912 ret = ret->baseType;
17913 }
17914 return (ret);
17915}
17916
Daniel Veillard01fa6152004-06-29 17:04:39 +000017917/**
17918 * xmlSchemaValidateSimpleTypeValue:
17919 * @ctxt: a schema validation context
17920 * @value: the value to be validated
17921 * @fireErrors: shall errors be reported?
17922 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000017923 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017924 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000017925 *
17926 * Validates a value by the given type (user derived or built-in).
17927 *
17928 * Returns 0 if the value is valid, a positive error code
17929 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000017930 */
17931static int
17932xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017933 xmlSchemaTypePtr type,
17934 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017935 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017936 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017937 int normalize,
17938 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000017939{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017940 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017941 int ret = 0;
17942 xmlChar *normValue = NULL;
17943 int wtsp;
17944
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017945 node = ctxt->node;
17946 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017947 wtsp = ctxt->valueWS;
17948 /*
17949 * Normalize the value.
17950 */
17951 if (normalize &&
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017952 (ctxt->valueWS != XML_SCHEMAS_FACET_COLLAPSE)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017953 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
17954
17955 if ((norm != -1) && (norm > ctxt->valueWS)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017956 if (norm == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017957 normValue = xmlSchemaCollapseString(value);
17958 else
17959 normValue = xmlSchemaWhiteSpaceReplace(value);
17960 ctxt->valueWS = norm;
17961 if (normValue != NULL)
17962 value = (const xmlChar *) normValue;
17963 }
17964 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017965 /*
17966 * The nodes of a content must be checked only once,
17967 * this is not working since list types will fire this
17968 * multiple times.
17969 */
17970 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
17971 xmlNodePtr cur = ctxt->cur;
17972
17973 do {
17974 switch (cur->type) {
17975 case XML_TEXT_NODE:
17976 case XML_CDATA_SECTION_NODE:
17977 case XML_PI_NODE:
17978 case XML_COMMENT_NODE:
17979 case XML_XINCLUDE_START:
17980 case XML_XINCLUDE_END:
17981 break;
17982 case XML_ENTITY_REF_NODE:
17983 case XML_ENTITY_NODE:
17984 /* TODO: Scour the entities for illegal nodes. */
17985 TODO break;
17986 case XML_ELEMENT_NODE: {
17987 /* NOTE: Changed to an internal error, since the
17988 * existence of an element node will be already checked in
17989 * xmlSchemaValidateElementBySimpleType and in
17990 * xmlSchemaValidateElementByComplexType.
17991 */
17992 xmlSchemaVCustomErr(ctxt,
17993 XML_SCHEMAV_INTERNAL,
17994 /* XML_SCHEMAS_ERR_INVALIDELEM, */
17995 node, type,
17996 "Element '%s' found in simple type content",
17997 cur->name);
17998 return (XML_SCHEMAV_INTERNAL);
17999 }
18000 case XML_ATTRIBUTE_NODE:
18001 case XML_DOCUMENT_NODE:
18002 case XML_DOCUMENT_TYPE_NODE:
18003 case XML_DOCUMENT_FRAG_NODE:
18004 case XML_NOTATION_NODE:
18005 case XML_HTML_DOCUMENT_NODE:
18006 case XML_DTD_NODE:
18007 case XML_ELEMENT_DECL:
18008 case XML_ATTRIBUTE_DECL:
18009 case XML_ENTITY_DECL:
18010 case XML_NAMESPACE_DECL:
18011#ifdef LIBXML_DOCB_ENABLED
18012 case XML_DOCB_DOCUMENT_NODE:
18013#endif
18014 xmlSchemaVCustomErr(ctxt,
18015 XML_SCHEMAV_INTERNAL,
18016 /* XML_SCHEMAS_ERR_INVALIDELEM, */
18017 node, NULL,
18018 "Node of unexpected type found in simple type content",
18019 NULL);
18020 return (XML_SCHEMAV_INTERNAL);
18021 }
18022 cur = cur->next;
18023 } while (cur != NULL);
18024 }
18025
William M. Brack2f2a6632004-08-20 23:09:47 +000018026 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018027 xmlSchemaTypePtr simpType, anyType;
William M. Brack2f2a6632004-08-20 23:09:47 +000018028
18029 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
18030
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018031 simpType = xmlSchemaGetSimpleContentType(type);
18032 if (simpType == NULL) {
18033 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
18034 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18035 "failed to obtain the simple content type of the complex "
18036 "type '%s'\n",
18037 type->name, NULL);
18038 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000018039 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018040 ret = xmlSchemaValidateSimpleTypeValue(ctxt, simpType, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000018041 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018042 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000018043 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18044 "validating complex type '%s'\n",
18045 type->name, NULL);
18046 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
18047 /*
18048 * Check facets.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018049 *
18050 * TODO: This is somehow not nice, since if an error occurs
William M. Brack2f2a6632004-08-20 23:09:47 +000018051 * the reported type will be the complex type; the spec
18052 * wants a simple type to be created on the complex type
18053 * if it has a simple content. For now we have to live with
18054 * it.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018055 */
18056 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018057 value, 0, fireErrors);
18058 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018059 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000018060 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18061 "validating facets of complex type '%s'\n",
18062 type->name, NULL);
18063 } else if (ret > 0) {
18064 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000018065 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018066 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000018067 }
18068 }
18069 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018070
18071 if (ctxt->value != NULL) {
18072 xmlSchemaFreeValue(ctxt->value);
18073 ctxt->value = NULL;
18074 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018075 /*
18076 * STREAM-READ-CHILDREN.
18077 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018078 if ((type->builtInType == XML_SCHEMAS_NOTATION) &&
18079 (ctxt->schema != NULL)) {
18080 /*
18081 * NOTATIONs need to be processed here, since they need
18082 * to lookup in the hashtable of NOTATION declarations.
18083 */
18084 ret = xmlSchemaValidateNotation(ctxt, value, &(ctxt->value), node);
18085 } else
18086 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018087 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018088 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
18089 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
18090 else
18091 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018092 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018093 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018094 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018095 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018096 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018097 "validating built-in type '%s'\n", type->name, NULL);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018098 } else if ((ctxt->value == NULL) &&
18099 (type->builtInType == XML_SCHEMAS_STRING) &&
18100 (ctxt->nodeInfo != NULL) &&
18101 (ctxt->nodeInfo->flags & XML_SCHEMA_ELEM_INFO_VALUE_NEEDED)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018102 xmlChar *valdup;
18103 /*
18104 * Create a precomputed string value for "string" as well if
18105 * requested.
18106 */
18107 valdup = xmlStrdup(value);
18108 ctxt->value = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
18109 BAD_CAST valdup);
18110 if ((valdup != NULL) && (ctxt->value == NULL))
18111 xmlFree(valdup);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018112 }
18113 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
18114 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
18115 * a literal in the ·lexical space· of {base type definition}
18116 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018117 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018118 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018119 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018120 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018121 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018122 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018123 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018124 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018125 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018126 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018127 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018128 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000018129 * Check facets.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018130 */
18131 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018132 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018133 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018134 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018135 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018136 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018137 type->name, NULL);
18138 } else if (ret > 0) {
18139 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018140 /*
18141 Disabled, since the facet validation already reports errors.
18142 if (fireErrors)
18143 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
18144 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018145 }
18146 }
18147 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
18148
18149 xmlSchemaTypePtr tmpType;
18150 const xmlChar *cur, *end;
18151 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018152 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018153
18154 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
18155 * of white space separated tokens, each of which ·match·es a literal
18156 * in the ·lexical space· of {item type definition}
18157 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000018158
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000018159 if (value == NULL)
18160 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000018161 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018162 cur = value;
18163 do {
18164 while (IS_BLANK_CH(*cur))
18165 cur++;
18166 end = cur;
18167 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18168 end++;
18169 if (end == cur)
18170 break;
18171 tmp = xmlStrndup(cur, end - cur);
18172 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018173 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018174 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018175 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018176 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018177 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18178 "validating an item of list simple type '%s'\n",
18179 type->name, NULL);
18180 break;
18181 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018182 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018183 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018184 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018185 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018186 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018187 cur = end;
18188 } while (*cur != 0);
18189 /*
18190 * Check facets.
18191 */
18192 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018193 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018194 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018195 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018196 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018197 } else if ((ret == 0) && (applyFacets)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018198 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018199 value, len, fireErrors);
18200 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018201 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018202 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18203 "validating facets of list simple type '%s'\n",
18204 type->name, NULL);
18205 } else if (ret > 0) {
18206 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018207 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000018208 Disabled, since the facet validation already reports errors.
18209 if (fireErrors)
18210 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018211 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018212 }
18213
Daniel Veillard01fa6152004-06-29 17:04:39 +000018214 }
18215 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
18216 xmlSchemaTypeLinkPtr memberLink;
18217
18218 /*
18219 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
18220 * not apply directly; however, the normalization behavior of ·union·
18221 * types is controlled by the value of whiteSpace on that one of the
18222 * ·memberTypes· against which the ·union· is successfully validated.
18223 *
18224 * This means that the value is normalized by the first validating
18225 * member type, then the facets of the union type are applied. This
18226 * needs changing of the value!
18227 */
18228
18229 /*
18230 * 1.2.3 if {variety} is ·union· then the string must ·match· a
18231 * literal in the ·lexical space· of at least one member of
18232 * {member type definitions}
18233 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018234#ifdef DEBUG_UNION_VALIDATION
18235 printf("Union ST : '%s'\n", (const char *) type->name);
18236 printf(" fireErrors : %d\n", fireErrors);
18237 printf(" applyFacets: %d\n", applyFacets);
18238#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000018239 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
18240 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018241 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018242 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018243 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018244 type->name, NULL);
18245 ret = -1;
18246 }
18247 if (ret == 0) {
18248 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018249 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
18250 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018251 if ((ret <= 0) || (ret == 0))
18252 break;
18253 memberLink = memberLink->next;
18254 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018255 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018256 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018257 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018258 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018259 type->name, NULL);
18260 } else if (ret > 0) {
18261 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018262 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018263 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018264 }
18265 }
18266 /*
18267 * Apply facets (pattern, enumeration).
18268 */
18269 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
18270 int mws;
18271 /*
18272 * The normalization behavior of ·union· types is controlled by
18273 * the value of whiteSpace on that one of the ·memberTypes·
18274 * against which the ·union· is successfully validated.
18275 */
18276 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018277 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018278 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18279 "the value was already normalized for the union simple "
18280 "type '%s'.\n", type->name, NULL);
18281 }
18282 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
18283 if (mws > ctxt->valueWS) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018284 if (mws == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018285 normValue = xmlSchemaCollapseString(value);
18286 else
18287 normValue = xmlSchemaWhiteSpaceReplace(value);
18288 if (normValue != NULL)
18289 value = (const xmlChar *) normValue;
18290 }
18291
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018292 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018293 value, 0, fireErrors);
18294 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018295 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018296 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18297 "validating facets of union simple type '%s'\n",
18298 type->name, NULL);
18299 } else if (ret > 0) {
18300 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
18301 /*
18302 if (fireErrors)
18303 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
18304 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018305 }
18306 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018307 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018308 ctxt->valueWS = wtsp;
18309 if (normValue != NULL)
18310 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018311 return (ret);
18312}
18313
18314/**
18315 * xmlSchemaValidateSimpleTypeElement:
18316 * @ctxt: a schema validation context
18317 * @node: the element node to be validated.
18318 *
18319 * Validate the element against a simple type.
18320 *
18321 * Returns 0 if the element is valid, a positive error code
18322 * number otherwise and -1 in case of an internal or API error.
18323 */
18324static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018325xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018326 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018327 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018328 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000018329{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018330 xmlSchemaTypePtr oldtype;
18331 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018332 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018333 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018334 int ret = 0, retval = 0;
18335
Daniel Veillard01fa6152004-06-29 17:04:39 +000018336 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018337 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
18338 "Internal error: xmlSchemaValidateElementBySimpleType, "
18339 "bad arguments", NULL);
18340 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018341 }
18342
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018343 oldtype = ctxt->type;
18344 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018345 /*
18346 * cvc-type: 3.1.2 The element information item must have no element
18347 * information item [children].
18348 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018349 /*
18350 * STREAM: Child nodes are processed.
18351 */
18352 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018353 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018354 /*
18355 * TODO: Entities, will they produce elements as well?
18356 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018357 if (cur->type == XML_ELEMENT_NODE) {
18358 xmlSchemaVCustomErr(ctxt,
18359 XML_SCHEMAV_CVC_TYPE_3_1_2,
18360 node, type,
18361 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018362 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018363 }
18364 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018365 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018366
Daniel Veillard01fa6152004-06-29 17:04:39 +000018367 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018368 * cvc-type 3.1.1:
18369 *
18370 * The attributes of must be empty, excepting those whose namespace name
18371 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
18372 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018373 */
18374 /*
18375 * STREAM: Attribute nodes are processed.
18376 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018377 attr = node->properties;
18378 while (attr != NULL) {
18379 if ((attr->ns == NULL) ||
18380 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
18381 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
18382 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
18383 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
18384 (!xmlStrEqual
18385 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018386 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018387 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
18388 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018389 }
18390 attr = attr->next;
18391 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018392 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018393 * This will skip validation if the type is 'anySimpleType' and
18394 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018395 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018396 if ((! isNil) &&
18397 (valSimpleContent == 1) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018398 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
18399 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018400 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018401
18402 value = xmlNodeGetContent(node);
18403 /*
18404 * NOTE: This call will not check the content nodes, since
18405 * this should be checked here already.
18406 */
18407 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
18408 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000018409 if (value != NULL)
18410 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018411 if (retval != 0)
18412 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000018413 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018414 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018415 return (ret);
18416}
Daniel Veillard4255d502002-04-16 15:50:10 +000018417
18418/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018419 * xmlSchemaValQNameAcquire:
18420 * @value: the lexical represantation of the QName value
18421 * @node: the node to search for the corresponding namespace declaration
18422 * @nsName: the resulting namespace name if found
18423 *
18424 * Checks that a value conforms to the lexical space of the type QName;
18425 * if valid, the corresponding namespace name is searched and retured
18426 * as a copy in @nsName. The local name is returned in @localName as
18427 * a copy.
18428 *
18429 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
18430 * namespace declaration was found in scope; -1 in case of an internal or
18431 * API error.
18432 */
18433static int
18434xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
18435 xmlChar **nsName, xmlChar **localName)
18436{
18437 int ret;
18438 xmlChar *local = NULL;
18439
18440 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
18441 return (-1);
18442 *nsName = NULL;
18443 *localName = NULL;
18444 ret = xmlValidateQName(value, 1);
18445 if (ret == 0) {
18446 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018447 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018448
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018449 /*
18450 * NOTE: xmlSplitQName2 will return a duplicated
18451 * string.
18452 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018453 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018454 if (local == NULL)
18455 local = xmlStrdup(value);
18456 ns = xmlSearchNs(node->doc, node, prefix);
18457 /*
18458 * A namespace need not to be found if the prefix is NULL.
18459 */
18460 if (ns != NULL) {
18461 /*
18462 * TODO: Is it necessary to duplicate the URI here?
18463 */
18464 *nsName = xmlStrdup(ns->href);
18465 } else if (prefix != NULL) {
18466 xmlFree(prefix);
18467 if (local != NULL)
18468 xmlFree(local);
18469 return (2);
18470 }
18471 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018472 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018473 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018474 } else
18475 return (1);
18476 return (ret);
18477}
18478
18479/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018480 * xmlSchemaHasElemContent:
18481 * @node: the node
18482 *
18483 * Scours the content of the given node for element
18484 * nodes.
18485 *
18486 * Returns 1 if an element node is found,
18487 * 0 otherwise.
18488 */
18489static int
18490xmlSchemaHasElemContent(xmlNodePtr node)
18491{
18492 if (node == NULL)
18493 return (0);
18494 node = node->children;
18495 while (node != NULL) {
18496 if (node->type == XML_ELEMENT_NODE)
18497 return (1);
18498 node = node->next;
18499 }
18500 return (0);
18501}
18502/**
18503 * xmlSchemaHasElemOrCharContent:
18504 * @node: the node
18505 *
18506 * Scours the content of the given node for element
18507 * and character nodes.
18508 *
18509 * Returns 1 if an element or character node is found,
18510 * 0 otherwise.
18511 */
18512static int
18513xmlSchemaHasElemOrCharContent(xmlNodePtr node)
18514{
18515 if (node == NULL)
18516 return (0);
18517 node = node->children;
18518 while (node != NULL) {
18519 switch (node->type) {
18520 case XML_ELEMENT_NODE:
18521 /*
18522 * TODO: Ask Daniel if these are all character nodes.
18523 */
18524 case XML_TEXT_NODE:
18525 case XML_CDATA_SECTION_NODE:
18526 /*
18527 * TODO: How XML_ENTITY_NODEs evaluated?
18528 */
18529 case XML_ENTITY_REF_NODE:
18530 case XML_ENTITY_NODE:
18531 return (1);
18532 break;
18533 default:
18534 break;
18535 }
18536 node = node->next;
18537 }
18538 return (0);
18539}
18540
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018541/************************************************************************
18542 * *
18543 * Identity-constraints (IDC) *
18544 * *
18545 ************************************************************************/
18546
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018547/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018548 * xmlSchemaAugmentIDC:
18549 * @idcDef: the IDC definition
18550 *
18551 * Creates an augmented IDC definition item.
18552 *
18553 * Returns the item, or NULL on internal errors.
18554 */
18555static void
18556xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18557 xmlSchemaValidCtxtPtr vctxt)
18558{
18559 xmlSchemaIDCAugPtr aidc;
18560
18561 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18562 if (aidc == NULL) {
18563 xmlSchemaVErrMemory(vctxt,
18564 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18565 NULL);
18566 return;
18567 }
18568 aidc->bubbleDepth = -1;
18569 aidc->def = idcDef;
18570 aidc->next = NULL;
18571 if (vctxt->aidcs == NULL)
18572 vctxt->aidcs = aidc;
18573 else {
18574 aidc->next = vctxt->aidcs;
18575 vctxt->aidcs = aidc;
18576 }
18577}
18578
18579/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018580 * xmlSchemaIDCNewBinding:
18581 * @idcDef: the IDC definition of this binding
18582 *
18583 * Creates a new IDC binding.
18584 *
18585 * Returns the new binding in case of succeeded, NULL on internal errors.
18586 */
18587static xmlSchemaPSVIIDCBindingPtr
18588xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18589{
18590 xmlSchemaPSVIIDCBindingPtr ret;
18591
18592 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18593 sizeof(xmlSchemaPSVIIDCBinding));
18594 if (ret == NULL) {
18595 xmlSchemaVErrMemory(NULL,
18596 "allocating a PSVI IDC binding item", NULL);
18597 return (NULL);
18598 }
18599 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18600 ret->definition = idcDef;
18601 return (ret);
18602}
18603
18604/**
18605 * xmlSchemaIDCStoreNodeTableItem:
18606 * @vctxt: the WXS validation context
18607 * @item: the IDC node table item
18608 *
18609 * The validation context is used to store an IDC node table items.
18610 * They are stored to avoid copying them if IDC node-tables are merged
18611 * with corresponding parent IDC node-tables (bubbling).
18612 *
18613 * Returns 0 if succeeded, -1 on internal errors.
18614 */
18615static int
18616xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
18617 xmlSchemaPSVIIDCNodePtr item)
18618{
18619 /*
18620 * Add to gobal list.
18621 */
18622 if (vctxt->idcNodes == NULL) {
18623 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18624 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18625 if (vctxt->idcNodes == NULL) {
18626 xmlSchemaVErrMemory(vctxt,
18627 "allocating the IDC node table item list", NULL);
18628 return (-1);
18629 }
18630 vctxt->sizeIdcNodes = 20;
18631 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18632 vctxt->sizeIdcNodes *= 2;
18633 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18634 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
18635 sizeof(xmlSchemaPSVIIDCNodePtr));
18636 if (vctxt->idcNodes == NULL) {
18637 xmlSchemaVErrMemory(vctxt,
18638 "re-allocating the IDC node table item list", NULL);
18639 return (-1);
18640 }
18641 }
18642 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
18643
18644 return (0);
18645}
18646
18647/**
18648 * xmlSchemaIDCStoreKey:
18649 * @vctxt: the WXS validation context
18650 * @item: the IDC key
18651 *
18652 * The validation context is used to store an IDC key.
18653 *
18654 * Returns 0 if succeeded, -1 on internal errors.
18655 */
18656static int
18657xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
18658 xmlSchemaPSVIIDCKeyPtr key)
18659{
18660 /*
18661 * Add to gobal list.
18662 */
18663 if (vctxt->idcKeys == NULL) {
18664 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18665 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18666 if (vctxt->idcKeys == NULL) {
18667 xmlSchemaVErrMemory(vctxt,
18668 "allocating the IDC key storage list", NULL);
18669 return (-1);
18670 }
18671 vctxt->sizeIdcKeys = 40;
18672 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18673 vctxt->sizeIdcKeys *= 2;
18674 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18675 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
18676 sizeof(xmlSchemaPSVIIDCKeyPtr));
18677 if (vctxt->idcKeys == NULL) {
18678 xmlSchemaVErrMemory(vctxt,
18679 "re-allocating the IDC key storage list", NULL);
18680 return (-1);
18681 }
18682 }
18683 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
18684
18685 return (0);
18686}
18687
18688/**
18689 * xmlSchemaIDCAppendNodeTableItem:
18690 * @bind: the IDC binding
18691 * @ntItem: the node-table item
18692 *
18693 * Appends the IDC node-table item to the binding.
18694 *
18695 * Returns 0 on success and -1 on internal errors.
18696 */
18697static int
18698xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
18699 xmlSchemaPSVIIDCNodePtr ntItem)
18700{
18701 if (bind->nodeTable == NULL) {
18702 bind->sizeNodes = 10;
18703 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18704 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
18705 if (bind->nodeTable == NULL) {
18706 xmlSchemaVErrMemory(NULL,
18707 "allocating an array of IDC node-table items", NULL);
18708 return(-1);
18709 }
18710 } else if (bind->sizeNodes <= bind->nbNodes) {
18711 bind->sizeNodes *= 2;
18712 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18713 xmlRealloc(bind->nodeTable, bind->sizeNodes *
18714 sizeof(xmlSchemaPSVIIDCNodePtr));
18715 if (bind->nodeTable == NULL) {
18716 xmlSchemaVErrMemory(NULL,
18717 "re-allocating an array of IDC node-table items", NULL);
18718 return(-1);
18719 }
18720 }
18721 bind->nodeTable[bind->nbNodes++] = ntItem;
18722 return(0);
18723}
18724
18725/**
18726 * xmlSchemaIDCAquireBinding:
18727 * @vctxt: the WXS validation context
18728 * @matcher: the IDC matcher
18729 *
18730 * Looks up an PSVI IDC binding, for the IDC definition and
18731 * of the given matcher. If none found, a new one is created
18732 * and added to the IDC table.
18733 *
18734 * Returns an IDC binding or NULL on internal errors.
18735 */
18736static xmlSchemaPSVIIDCBindingPtr
18737xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
18738 xmlSchemaIDCMatcherPtr matcher)
18739{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018740 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018741
18742 info = vctxt->elemInfos[matcher->depth];
18743
18744 if (info->idcTable == NULL) {
18745 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
18746 if (info->idcTable == NULL)
18747 return (NULL);
18748 return(info->idcTable);
18749 } else {
18750 xmlSchemaPSVIIDCBindingPtr bind = NULL;
18751
18752 bind = info->idcTable;
18753 do {
18754 if (bind->definition == matcher->aidc->def)
18755 return(bind);
18756 if (bind->next == NULL) {
18757 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
18758 if (bind->next == NULL)
18759 return (NULL);
18760 return(bind->next);
18761 }
18762 bind = bind->next;
18763 } while (bind != NULL);
18764 }
18765 return (NULL);
18766}
18767
18768/**
18769 * xmlSchemaIDCFreeKey:
18770 * @key: the IDC key
18771 *
18772 * Frees an IDC key together with its compiled value.
18773 */
18774static void
18775xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
18776{
18777 if (key->compValue != NULL)
18778 xmlSchemaFreeValue(key->compValue);
18779 xmlFree(key);
18780}
18781
18782/**
18783 * xmlSchemaIDCFreeBinding:
18784 *
18785 * Frees an IDC binding. Note that the node table-items
18786 * are not freed.
18787 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018788static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018789xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
18790{
18791 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018792 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18793 int i;
18794 /*
18795 * Node-table items for keyrefs are not stored globally
18796 * to the validation context, since they are not bubbled.
18797 * We need to free them here.
18798 */
18799 for (i = 0; i < bind->nbNodes; i++) {
18800 xmlFree(bind->nodeTable[i]->keys);
18801 xmlFree(bind->nodeTable[i]);
18802 }
18803 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018804 xmlFree(bind->nodeTable);
18805 }
18806 xmlFree(bind);
18807}
18808
18809/**
18810 * xmlSchemaIDCFreeIDCTable:
18811 * @bind: the first IDC binding in the list
18812 *
18813 * Frees an IDC table, i.e. all the IDC bindings in the list.
18814 */
18815static void
18816xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
18817{
18818 xmlSchemaPSVIIDCBindingPtr prev;
18819
18820 while (bind != NULL) {
18821 prev = bind;
18822 bind = bind->next;
18823 xmlSchemaIDCFreeBinding(prev);
18824 }
18825}
18826
18827/**
18828 * xmlSchemaIDCFreeMatcherList:
18829 * @matcher: the first IDC matcher in the list
18830 *
18831 * Frees a list of IDC matchers.
18832 */
18833static void
18834xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
18835{
18836 xmlSchemaIDCMatcherPtr next;
18837
18838 while (matcher != NULL) {
18839 next = matcher->next;
18840 if (matcher->keySeqs != NULL) {
18841 int i;
18842 for (i = 0; i < matcher->sizeKeySeqs; i++)
18843 if (matcher->keySeqs[i] != NULL)
18844 xmlFree(matcher->keySeqs[i]);
18845 xmlFree(matcher->keySeqs);
18846 }
18847 xmlFree(matcher);
18848 matcher = next;
18849 }
18850}
18851
18852/**
18853 * xmlSchemaAreValuesEqual:
18854 * @ta: the first type
18855 * @a: the first value
18856 * @tb: the second type
18857 * @b: the second value
18858 *
18859 * Compares two values.
18860 *
18861 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
18862 */
18863static int
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018864xmlSchemaAreValuesEqual(xmlSchemaValidCtxtPtr vctxt,
18865 xmlSchemaTypePtr ta,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018866 xmlSchemaValPtr a,
18867 xmlSchemaTypePtr tb,
18868 xmlSchemaValPtr b)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018869{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018870 /* Same user derived/built-in derived/built-in primitive types. */
18871 if (ta == tb)
18872 goto compareValue;
18873
18874 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018875 * Note that comparison with anySimpleTypes with be supported for
18876 * string based types as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018877 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018878#if 0
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018879 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
18880 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
18881 return(0);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018882#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018883
18884 /*
18885 * 4.2.1 equal (data-types)
18886 *
18887 * the ·value space·s of all ·primitive· datatypes are disjoint
18888 * (they do not share any values)
18889 */
18890 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
18891 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
18892 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
18893 return(0);
18894
18895 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
18896 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
18897 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
18898 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
18899 TODO
18900 return(0);
18901 }
18902 /*
18903 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
18904 * T then the ·value space· of T' is a subset of the ·value space· of T.
18905 */
18906 /*
18907 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
18908 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
18909 */
18910
18911 {
18912 xmlSchemaTypePtr pta = ta, ptb = tb;
18913
18914 /* Note that we will compare the primitives here. */
18915 while ((pta->builtInType == 0) ||
18916 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
18917 pta = pta->baseType;
18918 while ((ptb->builtInType == 0) ||
18919 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
18920 ptb = ptb->baseType;
18921 if (pta == ptb)
18922 goto compareValue;
18923 return(0);
18924 }
18925compareValue:
18926 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018927 int ret;
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018928 int aws, bws;
18929
18930 aws = xmlSchemaGetWhiteSpaceFacetValue(ta);
18931 bws = xmlSchemaGetWhiteSpaceFacetValue(tb);
18932
18933 ret = xmlSchemaCompareValuesWhtsp(
18934 a, (xmlSchemaWhitespaceValueType) aws,
18935 b, (xmlSchemaWhitespaceValueType) bws);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018936 if (ret == 0)
18937 return(1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018938 else if (ret == -2) {
18939 xmlSchemaVErr(vctxt, vctxt->node,
18940 XML_SCHEMAV_INTERNAL,
18941 "Internal error: xmlSchemaAreValuesEqual, "
18942 "failed to compare the values.\n",
18943 NULL, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018944 return(-1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018945 } else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018946 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018947 }
18948}
18949
18950/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018951 * xmlSchemaIDCAddStateObject:
18952 * @vctxt: the WXS validation context
18953 * @matcher: the IDC matcher
18954 * @sel: the XPath information
18955 * @parent: the parent "selector" state object if any
18956 * @type: "selector" or "field"
18957 *
18958 * Creates/reuses and activates state objects for the given
18959 * XPath information; if the XPath expression consists of unions,
18960 * multiple state objects are created for every unioned expression.
18961 *
18962 * Returns 0 on success and -1 on internal errors.
18963 */
18964static int
18965xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
18966 xmlSchemaIDCMatcherPtr matcher,
18967 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018968 int type)
18969{
18970 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018971
18972 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018973 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018974 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018975 if (vctxt->xpathStatePool != NULL) {
18976 sto = vctxt->xpathStatePool;
18977 vctxt->xpathStatePool = sto->next;
18978 sto->next = NULL;
18979 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018980 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018981 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018982 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018983 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
18984 if (sto == NULL) {
18985 xmlSchemaVErrMemory(NULL,
18986 "allocating an IDC state object", NULL);
18987 return (-1);
18988 }
18989 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
18990 }
18991 /*
18992 * Add to global list.
18993 */
18994 if (vctxt->xpathStates != NULL)
18995 sto->next = vctxt->xpathStates;
18996 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018997
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018998 /*
18999 * Free the old xpath validation context.
19000 */
19001 if (sto->xpathCtxt != NULL)
19002 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
19003
19004 /*
19005 * Create a new XPath (pattern) validation context.
19006 */
19007 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
19008 (xmlPatternPtr) sel->xpathComp);
19009 if (sto->xpathCtxt == NULL) {
19010 xmlSchemaVErr(vctxt, vctxt->node,
19011 XML_SCHEMAV_INTERNAL,
19012 "Internal error: xmlSchemaIDCAddStateObject, "
19013 "failed to create the XPath validation context.\n",
19014 NULL, NULL);
19015 return (-1);
19016 }
19017 sto->type = type;
19018 sto->depth = vctxt->depth;
19019 sto->matcher = matcher;
19020 sto->sel = sel;
19021 sto->nbHistory = 0;
19022
19023#if DEBUG_IDC
19024 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
19025 sto->sel->xpath);
19026#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019027 return (0);
19028}
19029
19030/**
19031 * xmlSchemaXPathEvaluate:
19032 * @vctxt: the WXS validation context
19033 * @nodeType: the nodeType of the current node
19034 *
19035 * Evaluates all active XPath state objects.
19036 *
19037 * Returns the number of IC "field" state objects which resolved to
19038 * this node, 0 if none resolved and -1 on internal errors.
19039 */
19040static int
19041xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019042 xmlElementType nodeType)
19043{
19044 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019045 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019046
19047 if (vctxt->xpathStates == NULL)
19048 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019049
19050 if (nodeType == XML_ATTRIBUTE_NODE)
19051 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019052#if DEBUG_IDC
19053 {
19054 xmlChar *str = NULL;
19055 xmlGenericError(xmlGenericErrorContext,
19056 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019057 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
19058 vctxt->nodeInfo->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019059 FREE_AND_NULL(str)
19060 }
19061#endif
19062 /*
19063 * Process all active XPath state objects.
19064 */
19065 first = vctxt->xpathStates;
19066 sto = first;
19067 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019068#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019069 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019070 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
19071 sto->matcher->aidc->def->name, sto->sel->xpath);
19072 else
19073 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
19074 sto->matcher->aidc->def->name, sto->sel->xpath);
19075#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019076 if (nodeType == XML_ELEMENT_NODE)
19077 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
19078 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
19079 else
19080 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
19081 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
19082
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019083 if (res == -1) {
19084 xmlSchemaVErr(vctxt, vctxt->node,
19085 XML_SCHEMAV_INTERNAL,
19086 "Internal error: xmlSchemaXPathEvaluate, "
19087 "failed to evaluate a node.\n",
19088 NULL, NULL);
19089 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019090 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019091 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019092 goto next_sto;
19093 /*
19094 * Full match.
19095 */
19096#if DEBUG_IDC
19097 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019098 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019099#endif
19100 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019101 * Register a match in the state object history.
19102 */
19103 if (sto->history == NULL) {
19104 sto->history = (int *) xmlMalloc(5 * sizeof(int));
19105 if (sto->history == NULL) {
19106 xmlSchemaVErrMemory(NULL,
19107 "allocating the state object history", NULL);
19108 return(-1);
19109 }
19110 sto->sizeHistory = 10;
19111 } else if (sto->sizeHistory <= sto->nbHistory) {
19112 sto->sizeHistory *= 2;
19113 sto->history = (int *) xmlRealloc(sto->history,
19114 sto->sizeHistory * sizeof(int));
19115 if (sto->history == NULL) {
19116 xmlSchemaVErrMemory(NULL,
19117 "re-allocating the state object history", NULL);
19118 return(-1);
19119 }
19120 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019121 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019122
19123#ifdef DEBUG_IDC
19124 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
19125 vctxt->depth);
19126#endif
19127
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019128 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
19129 xmlSchemaIDCSelectPtr sel;
19130 /*
19131 * Activate state objects for the IDC fields of
19132 * the IDC selector.
19133 */
19134#if DEBUG_IDC
19135 xmlGenericError(xmlGenericErrorContext, "IDC: "
19136 "activating field states\n");
19137#endif
19138 sel = sto->matcher->aidc->def->fields;
19139 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019140 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
19141 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
19142 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019143 sel = sel->next;
19144 }
19145 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19146 /*
19147 * An IDC key node was found.
19148 */
19149#if DEBUG_IDC
19150 xmlGenericError(xmlGenericErrorContext,
19151 "IDC: key found\n");
19152#endif
19153 /*
19154 * Notify that the character value of this node is
19155 * needed.
19156 */
19157 if (resolved == 0)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019158 vctxt->nodeInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019159 resolved++;
19160 }
19161next_sto:
19162 if (sto->next == NULL) {
19163 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019164 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019165 */
19166 head = first;
19167 sto = vctxt->xpathStates;
19168 } else
19169 sto = sto->next;
19170 }
19171 return (resolved);
19172}
19173
19174/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019175 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019176 * @vctxt: the WXS validation context
19177 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019178 * @compValue: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019179 *
19180 * Processes and pops the history items of the IDC state objects.
19181 * IDC key-sequences are validated/created on IDC bindings.
19182 *
19183 * Returns 0 on success and -1 on internal errors.
19184 */
19185static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019186xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019187 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019188{
19189 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019190 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019191 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019192 xmlSchemaTypePtr type = vctxt->nodeInfo->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019193
19194 if (vctxt->xpathStates == NULL)
19195 return (0);
19196 sto = vctxt->xpathStates;
19197
19198#if DEBUG_IDC
19199 {
19200 xmlChar *str = NULL;
19201 xmlGenericError(xmlGenericErrorContext,
19202 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019203 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
19204 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019205 FREE_AND_NULL(str)
19206 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019207#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019208 /*
19209 * Evaluate the state objects.
19210 */
19211 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019212 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019213#if DEBUG_IDC
19214 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19215 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019216#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019217 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019218 goto deregister_check;
19219
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019220 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019221
19222 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019223 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019224 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019225 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019226 sto = sto->next;
19227 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019228 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019229 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19230 if (! IS_SIMPLE_TYPE(type)) {
19231 /*
19232 * Not qualified if the field resolves to a node of non
19233 * simple type.
19234 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019235 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019236 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019237 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019238 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19239 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019240 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019241
19242 sto->nbHistory--;
19243 goto deregister_check;
19244 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019245 if ((key == NULL) && (vctxt->nodeInfo->value == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019246 /*
19247 * Failed to provide the normalized value; maby
19248 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019249 */
19250 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019251 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019252 vctxt->nodeInfo,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019253 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19254 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019255 "was either invalid or something strange happend",
19256 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019257 /*
19258 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019259 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019260 "Internal error: xmlSchemaXPathProcessHistory, "
19261 "computed value not available.\n",
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019262 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019263 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019264 sto->nbHistory--;
19265 goto deregister_check;
19266 } else {
19267 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19268 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019269 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019270
19271 /*
19272 * The key will be anchored on the matcher's list of
19273 * key-sequences. The position in this list is determined
19274 * by the target node's depth relative to the matcher's
19275 * depth of creation (i.e. the depth of the scope element).
19276 */
19277 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019278 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019279
19280 /*
19281 * Create/grow the array of key-sequences.
19282 */
19283 if (matcher->keySeqs == NULL) {
19284 if (pos > 9)
19285 matcher->sizeKeySeqs = pos * 2;
19286 else
19287 matcher->sizeKeySeqs = 10;
19288 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19289 xmlMalloc(matcher->sizeKeySeqs *
19290 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19291 if (matcher->keySeqs == NULL) {
19292 xmlSchemaVErrMemory(NULL,
19293 "allocating an array of key-sequences",
19294 NULL);
19295 return(-1);
19296 }
19297 memset(matcher->keySeqs, 0,
19298 matcher->sizeKeySeqs *
19299 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19300 } else if (pos >= matcher->sizeKeySeqs) {
19301 int i = matcher->sizeKeySeqs;
19302
19303 matcher->sizeKeySeqs *= 2;
19304 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19305 xmlRealloc(matcher->keySeqs,
19306 matcher->sizeKeySeqs *
19307 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019308 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019309 xmlSchemaVErrMemory(NULL,
19310 "reallocating an array of key-sequences",
19311 NULL);
19312 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019313 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019314 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019315 * The array needs to be NULLed.
19316 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019317 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019318 for (; i < matcher->sizeKeySeqs; i++)
19319 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019320 }
19321
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019322 /*
19323 * Get/create the key-sequence.
19324 */
19325 keySeq = matcher->keySeqs[pos];
19326 if (keySeq == NULL) {
19327 goto create_sequence;
19328 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019329 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019330 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019331 * cvc-identity-constraint:
19332 * 3 For each node in the ·target node set· all
19333 * of the {fields}, with that node as the context
19334 * node, evaluate to either an empty node-set or
19335 * a node-set with exactly one member, which must
19336 * have a simple type.
19337 *
19338 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019339 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019340 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019341 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019342 vctxt->nodeInfo,
19343 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019344 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019345 "with more than one member",
19346 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019347 sto->nbHistory--;
19348 goto deregister_check;
19349 } else {
19350 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019351 }
19352 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019353
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019354create_sequence:
19355 /*
19356 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019357 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019358 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19359 matcher->aidc->def->nbFields *
19360 sizeof(xmlSchemaPSVIIDCKeyPtr));
19361 if (keySeq == NULL) {
19362 xmlSchemaVErrMemory(NULL,
19363 "allocating an IDC key-sequence", NULL);
19364 return(-1);
19365 }
19366 memset(keySeq, 0, matcher->aidc->def->nbFields *
19367 sizeof(xmlSchemaPSVIIDCKeyPtr));
19368 matcher->keySeqs[pos] = keySeq;
19369create_key:
19370 /*
19371 * Created a key once per node only.
19372 */
19373 if (key == NULL) {
19374 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19375 sizeof(xmlSchemaPSVIIDCKey));
19376 if (key == NULL) {
19377 xmlSchemaVErrMemory(NULL,
19378 "allocating a IDC key", NULL);
19379 xmlFree(keySeq);
19380 matcher->keySeqs[pos] = NULL;
19381 return(-1);
19382 }
19383 /*
19384 * Consume the compiled value.
19385 */
19386 key->type = type;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019387 key->compValue = vctxt->nodeInfo->value;
19388 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019389 /*
19390 * Store the key in a global list.
19391 */
19392 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19393 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019394 return (-1);
19395 }
19396 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019397 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019398 }
19399 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019400
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019401 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19402 xmlSchemaPSVIIDCBindingPtr bind;
19403 xmlSchemaPSVIIDCNodePtr ntItem;
19404 xmlSchemaIDCMatcherPtr matcher;
19405 xmlSchemaIDCPtr idc;
19406 int pos, i, j, nbKeys;
19407 /*
19408 * Here we have the following scenario:
19409 * An IDC 'selector' state object resolved to a target node,
19410 * during the time this target node was in the
19411 * ancestor-or-self axis, the 'field' state object(s) looked
19412 * out for matching nodes to create a key-sequence for this
19413 * target node. Now we are back to this target node and need
19414 * to put the key-sequence, together with the target node
19415 * itself, into the node-table of the corresponding IDC
19416 * binding.
19417 */
19418 matcher = sto->matcher;
19419 idc = matcher->aidc->def;
19420 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019421 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019422 /*
19423 * Check if the matcher has any key-sequences at all, plus
19424 * if it has a key-sequence for the current target node.
19425 */
19426 if ((matcher->keySeqs == NULL) ||
19427 (matcher->sizeKeySeqs <= pos)) {
19428 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19429 goto selector_key_error;
19430 else
19431 goto selector_leave;
19432 }
19433
19434 keySeq = &(matcher->keySeqs[pos]);
19435 if (*keySeq == NULL) {
19436 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19437 goto selector_key_error;
19438 else
19439 goto selector_leave;
19440 }
19441
19442 for (i = 0; i < nbKeys; i++) {
19443 if ((*keySeq)[i] == NULL) {
19444 /*
19445 * Not qualified, if not all fields did resolve.
19446 */
19447 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19448 /*
19449 * All fields of a "key" IDC must resolve.
19450 */
19451 goto selector_key_error;
19452 }
19453 goto selector_leave;
19454 }
19455 }
19456 /*
19457 * All fields did resolve.
19458 */
19459
19460 /*
19461 * 4.1 If the {identity-constraint category} is unique(/key),
19462 * then no two members of the ·qualified node set· have
19463 * ·key-sequences· whose members are pairwise equal, as
19464 * defined by Equal in [XML Schemas: Datatypes].
19465 *
19466 * Get the IDC binding from the matcher and check for
19467 * duplicate key-sequences.
19468 */
19469 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19470 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19471 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019472 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019473
19474 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019475 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019476 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019477 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019478 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019479 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019480 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019481 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019482 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019483 bkey = bkeySeq[j];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019484 res = xmlSchemaAreValuesEqual(vctxt, ckey->type,
19485 ckey->compValue, bkey->type, bkey->compValue);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019486 if (res == -1) {
19487 return (-1);
19488 } else if (res == 0)
19489 break;
19490 }
19491 if (res == 1) {
19492 /*
19493 * Duplicate found.
19494 */
19495 break;
19496 }
19497 i++;
19498 } while (i < bind->nbNodes);
19499 if (i != bind->nbNodes) {
19500 /*
19501 * TODO: Try to report the key-sequence.
19502 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019503 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019504 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019505 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019506 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019507 "Duplicate key-sequence found", NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019508
19509 goto selector_leave;
19510 }
19511 }
19512 /*
19513 * Add a node-table item to the IDC binding.
19514 */
19515 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19516 sizeof(xmlSchemaPSVIIDCNode));
19517 if (ntItem == NULL) {
19518 xmlSchemaVErrMemory(NULL,
19519 "allocating an IDC node-table item", NULL);
19520 xmlFree(*keySeq);
19521 *keySeq = NULL;
19522 return(-1);
19523 }
19524 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19525
19526 /*
19527 * Store the node-table item on global list.
19528 */
19529 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19530 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19531 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019532 xmlFree(*keySeq);
19533 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019534 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019535 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019536 }
19537 /*
19538 * Init the node-table item. Consume the key-sequence.
19539 */
19540 ntItem->node = vctxt->node;
19541 ntItem->keys = *keySeq;
19542 *keySeq = NULL;
19543 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19544 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19545 /*
19546 * Free the item, since keyref items won't be
19547 * put on a global list.
19548 */
19549 xmlFree(ntItem->keys);
19550 xmlFree(ntItem);
19551 }
19552 return (-1);
19553 }
19554
19555 goto selector_leave;
19556selector_key_error:
19557 /*
19558 * 4.2.1 (KEY) The ·target node set· and the
19559 * ·qualified node set· are equal, that is, every
19560 * member of the ·target node set· is also a member
19561 * of the ·qualified node set· and vice versa.
19562 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019563 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019564 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019565 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019566 (xmlSchemaTypePtr) idc,
19567 "All 'key' fields must evaluate to a node",
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019568 NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019569selector_leave:
19570 /*
19571 * Free the key-sequence if not added to the IDC table.
19572 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019573 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019574 xmlFree(*keySeq);
19575 *keySeq = NULL;
19576 }
19577 } /* if selector */
19578
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019579 sto->nbHistory--;
19580
19581deregister_check:
19582 /*
19583 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019584 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019585 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019586#if DEBUG_IDC
19587 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19588 sto->sel->xpath);
19589#endif
19590 if (vctxt->xpathStates != sto) {
19591 xmlSchemaVErr(vctxt, vctxt->node,
19592 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019593 "Internal error: xmlSchemaXPathProcessHistory, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019594 "The state object to be removed is not the first "
19595 "in the list.\n",
19596 NULL, NULL);
19597 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019598 nextsto = sto->next;
19599 /*
19600 * Unlink from the list of active XPath state objects.
19601 */
19602 vctxt->xpathStates = sto->next;
19603 sto->next = vctxt->xpathStatePool;
19604 /*
19605 * Link it to the pool of reusable state objects.
19606 */
19607 vctxt->xpathStatePool = sto;
19608 sto = nextsto;
19609 } else
19610 sto = sto->next;
19611 } /* while (sto != NULL) */
19612 return (0);
19613}
19614
19615/**
19616 * xmlSchemaIDCRegisterMatchers:
19617 * @vctxt: the WXS validation context
19618 * @elemDecl: the element declaration
19619 *
19620 * Creates helper objects to evaluate IDC selectors/fields
19621 * successively.
19622 *
19623 * Returns 0 if OK and -1 on internal errors.
19624 */
19625static int
19626xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19627 xmlSchemaElementPtr elemDecl)
19628{
19629 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19630 xmlSchemaIDCPtr idc, refIdc;
19631 xmlSchemaIDCAugPtr aidc;
19632
19633 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19634 if (idc == NULL)
19635 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019636
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019637#if DEBUG_IDC
19638 {
19639 xmlChar *str = NULL;
19640 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019641 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019642 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
19643 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019644 FREE_AND_NULL(str)
19645 }
19646#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019647 if (vctxt->nodeInfo->idcMatchers != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019648 xmlSchemaVErr(vctxt, vctxt->node,
19649 XML_SCHEMAV_INTERNAL,
19650 "Internal error: xmlSchemaIDCRegisterMatchers: "
19651 "The chain of IDC matchers is expected to be empty.\n",
19652 NULL, NULL);
19653 return (-1);
19654 }
19655 do {
19656 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19657 /*
19658 * Since IDCs bubbles are expensive we need to know the
19659 * depth at which the bubbles should stop; this will be
19660 * the depth of the top-most keyref IDC. If no keyref
19661 * references a key/unique IDC, the bubbleDepth will
19662 * be -1, indicating that no bubbles are needed.
19663 */
19664 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19665 if (refIdc != NULL) {
19666 /*
19667 * Lookup the augmented IDC.
19668 */
19669 aidc = vctxt->aidcs;
19670 while (aidc != NULL) {
19671 if (aidc->def == refIdc)
19672 break;
19673 aidc = aidc->next;
19674 }
19675 if (aidc == NULL) {
19676 xmlSchemaVErr(vctxt, vctxt->node,
19677 XML_SCHEMAV_INTERNAL,
19678 "Internal error: xmlSchemaIDCRegisterMatchers: "
19679 "Could not find an augmented IDC item for an IDC "
19680 "definition.\n",
19681 NULL, NULL);
19682 return (-1);
19683 }
19684 if ((aidc->bubbleDepth == -1) ||
19685 (vctxt->depth < aidc->bubbleDepth))
19686 aidc->bubbleDepth = vctxt->depth;
19687 }
19688 }
19689 /*
19690 * Lookup the augmented IDC item for the IDC definition.
19691 */
19692 aidc = vctxt->aidcs;
19693 while (aidc != NULL) {
19694 if (aidc->def == idc)
19695 break;
19696 aidc = aidc->next;
19697 }
19698 if (aidc == NULL) {
19699 xmlSchemaVErr(vctxt, vctxt->node,
19700 XML_SCHEMAV_INTERNAL,
19701 "Internal error: xmlSchemaIDCRegisterMatchers: "
19702 "Could not find an augmented IDC item for an IDC definition.\n",
19703 NULL, NULL);
19704 return (-1);
19705 }
19706 /*
19707 * Create an IDC matcher for every IDC definition.
19708 */
19709 matcher = (xmlSchemaIDCMatcherPtr)
19710 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
19711 if (matcher == NULL) {
19712 xmlSchemaVErrMemory(vctxt,
19713 "allocating an IDC matcher", NULL);
19714 return (-1);
19715 }
19716 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
19717 if (last == NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019718 vctxt->nodeInfo->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019719 else
19720 last->next = matcher;
19721 last = matcher;
19722
19723 matcher->type = IDC_MATCHER;
19724 matcher->depth = vctxt->depth;
19725 matcher->aidc = aidc;
19726#if DEBUG_IDC
19727 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
19728#endif
19729 /*
19730 * Init the automaton state object.
19731 */
19732 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019733 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019734 return (-1);
19735
19736 idc = idc->next;
19737 } while (idc != NULL);
19738 return (0);
19739}
19740
19741/**
19742 * xmlSchemaBubbleIDCNodeTables:
19743 * @depth: the current tree depth
19744 *
19745 * Merges IDC bindings of an element at @depth into the corresponding IDC
19746 * bindings of its parent element. If a duplicate note-table entry is found,
19747 * both, the parent node-table entry and child entry are discarded from the
19748 * node-table of the parent.
19749 *
19750 * Returns 0 if OK and -1 on internal errors.
19751 */
19752static int
19753xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
19754{
19755 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019756 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
19757 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019758 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
19759 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019760 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019761 int duplTop;
19762
19763 /*
19764 * The node table has the following sections:
19765 *
19766 * O --> old node-table entries (first)
19767 * O
19768 * + --> new node-table entries
19769 * +
19770 * % --> new duplicate node-table entries
19771 * %
19772 * # --> old duplicate node-table entries
19773 * # (last)
19774 *
19775 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019776 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019777 if (bind == NULL) {
19778 /* Fine, no table, no bubbles. */
19779 return (0);
19780 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019781
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019782 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
19783 /*
19784 * Walk all bindings; create new or add to existing bindings.
19785 * Remove duplicate key-sequences.
19786 */
19787start_binding:
19788 while (bind != NULL) {
19789 /*
19790 * Skip keyref IDCs.
19791 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019792 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19793 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019794 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019795 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019796 /*
19797 * Check if the key/unique IDC table needs to be bubbled.
19798 */
19799 aidc = vctxt->aidcs;
19800 do {
19801 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019802 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019803 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019804 bind = bind->next;
19805 goto start_binding;
19806 }
19807 break;
19808 }
19809 aidc = aidc->next;
19810 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019811
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019812 if (parTable != NULL)
19813 parBind = *parTable;
19814 while (parBind != NULL) {
19815 /*
19816 * Search a matching parent binding for the
19817 * IDC definition.
19818 */
19819 if (parBind->definition == bind->definition) {
19820
19821 /*
19822 * Compare every node-table entry of the child node,
19823 * i.e. the key-sequence within, ...
19824 */
19825 oldNum = parBind->nbNodes; /* Skip newly added items. */
19826 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019827 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019828
19829 for (i = 0; i < bind->nbNodes; i++) {
19830 node = bind->nodeTable[i];
19831 if (node == NULL)
19832 continue;
19833 /*
19834 * ...with every key-sequence of the parent node, already
19835 * evaluated to be a duplicate key-sequence.
19836 */
19837 if (parBind->nbDupls != 0) {
19838 j = bind->nbNodes + newDupls;
19839 while (j < duplTop) {
19840 parNode = parBind->nodeTable[j];
19841 for (k = 0; k < bind->definition->nbFields; k++) {
19842 key = node->keys[k];
19843 parKey = parNode->keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019844 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019845 key->compValue,
19846 parKey->type, parKey->compValue);
19847 if (ret == -1) {
19848 /* TODO: Internal error */
19849 return(-1);
19850 } else if (ret == 0)
19851 break;
19852
19853 }
19854 if (ret == 1)
19855 /* Duplicate found. */
19856 break;
19857 j++;
19858 }
19859 if (j != duplTop) {
19860 /* Duplicate found. */
19861 continue;
19862 }
19863 }
19864 /*
19865 * ... and with every key-sequence of the parent node.
19866 */
19867 j = 0;
19868 while (j < oldNum) {
19869 parNode = parBind->nodeTable[j];
19870 /*
19871 * Compare key by key.
19872 */
19873 for (k = 0; k < parBind->definition->nbFields; k++) {
19874 key = node->keys[k];
19875 parKey = parNode->keys[k];
19876
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019877 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019878 key->compValue,
19879 parKey->type, parKey->compValue);
19880 if (ret == -1) {
19881 /* TODO: Internal error */
19882 } else if (ret == 0)
19883 break;
19884
19885 }
19886 if (ret == 1)
19887 /*
19888 * The key-sequences are equal.
19889 */
19890 break;
19891 j++;
19892 }
19893 if (j != oldNum) {
19894 /*
19895 * Handle duplicates.
19896 */
19897 newDupls++;
19898 oldNum--;
19899 parBind->nbNodes--;
19900 /*
19901 * Move last old item to pos of duplicate.
19902 */
19903 parBind->nodeTable[j] =
19904 parBind->nodeTable[oldNum];
19905
19906 if (parBind->nbNodes != oldNum) {
19907 /*
19908 * If new items exist, move last new item to
19909 * last of old items.
19910 */
19911 parBind->nodeTable[oldNum] =
19912 parBind->nodeTable[parBind->nbNodes];
19913 }
19914 /*
19915 * Move duplicate to last pos of new/old items.
19916 */
19917 parBind->nodeTable[parBind->nbNodes] = parNode;
19918
19919 } else {
19920 /*
19921 * Add the node-table entry (node and key-sequence) of
19922 * the child node to the node table of the parent node.
19923 */
19924 if (parBind->nodeTable == NULL) {
19925 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019926 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019927 if (parBind->nodeTable == NULL) {
19928 xmlSchemaVErrMemory(NULL,
19929 "allocating IDC list of node-table items", NULL);
19930 return(-1);
19931 }
19932 parBind->sizeNodes = 1;
19933 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019934 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019935 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19936 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
19937 sizeof(xmlSchemaPSVIIDCNodePtr));
19938 if (parBind->nodeTable == NULL) {
19939 xmlSchemaVErrMemory(NULL,
19940 "re-allocating IDC list of node-table items", NULL);
19941 return(-1);
19942 }
19943 }
19944
19945 /*
19946 * Move first old duplicate to last position
19947 * of old duplicates +1.
19948 */
19949 if (parBind->nbDupls != 0) {
19950 parBind->nodeTable[duplTop] =
19951 parBind->nodeTable[parBind->nbNodes + newDupls];
19952 }
19953 /*
19954 * Move first new duplicate to last position of
19955 * new duplicates +1.
19956 */
19957 if (newDupls != 0) {
19958 parBind->nodeTable[parBind->nbNodes + newDupls] =
19959 parBind->nodeTable[parBind->nbNodes];
19960 }
19961 /*
19962 * Append the new node-table entry to the 'new node-table
19963 * entries' section.
19964 */
19965 parBind->nodeTable[parBind->nbNodes] = node;
19966 parBind->nbNodes++;
19967 duplTop++;
19968 }
19969 }
19970 parBind->nbDupls += newDupls;
19971 break;
19972 }
19973 if (parBind->next == NULL)
19974 lastParBind = parBind;
19975 parBind = parBind->next;
19976 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019977 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019978 /*
19979 * No binding for the IDC was found: create a new one and
19980 * copy all node-tables.
19981 */
19982 parBind = xmlSchemaIDCNewBinding(bind->definition);
19983 if (parBind == NULL)
19984 return(-1);
19985
19986 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19987 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
19988 if (parBind->nodeTable == NULL) {
19989 xmlSchemaVErrMemory(NULL,
19990 "allocating an array of IDC node-table items", NULL);
19991 xmlSchemaIDCFreeBinding(parBind);
19992 return(-1);
19993 }
19994 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019995 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019996 memcpy(parBind->nodeTable, bind->nodeTable,
19997 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019998 if (*parTable == NULL)
19999 *parTable = parBind;
20000 else
20001 lastParBind->next = parBind;
20002 }
20003 bind = bind->next;
20004 }
20005 return (0);
20006}
20007
20008/**
20009 * xmlSchemaCheckCVCIDCKeyRef:
20010 * @vctxt: the WXS validation context
20011 * @elemDecl: the element declaration
20012 *
20013 * Check the cvc-idc-keyref constraints.
20014 */
20015static int
20016xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
20017{
20018 xmlSchemaPSVIIDCBindingPtr refbind, bind;
20019
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020020 refbind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020021 /*
20022 * Find a keyref.
20023 */
20024 while (refbind != NULL) {
20025 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20026 int i, j, k, res;
20027 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
20028 xmlSchemaPSVIIDCKeyPtr refKey, key;
20029
20030 /*
20031 * Find the referred key/unique.
20032 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020033 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020034 do {
20035 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
20036 bind->definition)
20037 break;
20038 bind = bind->next;
20039 } while (bind != NULL);
20040
20041 /*
20042 * Search for a matching key-sequences.
20043 */
20044 for (i = 0; i < refbind->nbNodes; i++) {
20045 res = 0;
20046 if (bind != NULL) {
20047 refKeys = refbind->nodeTable[i]->keys;
20048 for (j = 0; j < bind->nbNodes; j++) {
20049 keys = bind->nodeTable[j]->keys;
20050 for (k = 0; k < bind->definition->nbFields; k++) {
20051 refKey = refKeys[k];
20052 key = keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020053 res = xmlSchemaAreValuesEqual(vctxt,
20054 key->type, key->compValue,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020055 refKey->type, refKey->compValue);
20056 if (res == 0)
20057 break;
20058 else if (res == -1) {
20059 return (-1);
20060 }
20061 }
20062 if (res == 1) {
20063 /*
20064 * Match found.
20065 */
20066 break;
20067 }
20068 }
20069 }
20070 if (res == 0) {
20071 /* TODO: Report the key-sequence. */
20072 xmlSchemaVCustomErr(vctxt,
20073 XML_SCHEMAV_CVC_IDC,
20074 refbind->nodeTable[i]->node,
20075 (xmlSchemaTypePtr) refbind->definition,
20076 "No matching key-sequence found", NULL);
20077 }
20078 }
20079 }
20080 refbind = refbind->next;
20081 }
20082 return (0);
20083}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020084
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020085/**
20086 * xmlSchemaBeginElement:
20087 * @vctxt: the WXS validation context
20088 *
20089 * Just a temporary workaround to simulate streaming validation
20090 * a bit.
20091 */
20092static void
20093xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
20094{
20095 vctxt->depth++;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020096 vctxt->nodeInfo = xmlSchemaGetFreshElemInfo(vctxt, vctxt->depth);
20097 vctxt->nodeInfo->node = vctxt->node;
20098 vctxt->nodeInfo->localName = vctxt->node->name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020099 if (vctxt->node->ns != NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020100 vctxt->nodeInfo->namespaceName = vctxt->node->ns->href;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020101 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020102 vctxt->nodeInfo->namespaceName = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020103}
20104
20105/**
20106 * xmlSchemaEndElement:
20107 * @vctxt: the WXS validation context
20108 *
20109 * Just a temporary workaround to simulate streaming validation
20110 * a bit.
20111 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020112static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020113xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
20114{
20115 if (vctxt->depth < 0) {
20116 /* TODO: raise error? */
20117 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020118 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020119 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020120 /*
20121 * Evaluate the history of changes of active state objects.
20122 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020123 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
20124 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020125
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020126 if (vctxt->nodeInfo->value != NULL) {
20127 xmlSchemaFreeValue(vctxt->nodeInfo->value);
20128 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020129 }
20130 /*
20131 * TODO: 6 The element information item must be ·valid· with respect to each of
20132 * the {identity-constraint definitions} as per Identity-constraint
20133 * Satisfied (§3.11.4).
20134 */
20135 /*
20136 * Validate IDC keyrefs.
20137 */
20138 xmlSchemaCheckCVCIDCKeyRef(vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020139
20140 /*
20141 * Merge/free the IDC table.
20142 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020143 if (vctxt->nodeInfo->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020144#ifdef DEBUG_IDC
20145 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020146 vctxt->nodeInfo->namespaceName,
20147 vctxt->nodeInfo->localName,
20148 vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020149#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020150 if (vctxt->depth > 0) {
20151 /*
20152 * Merge the IDC node table with the table of the parent node.
20153 */
20154 xmlSchemaBubbleIDCNodeTables(vctxt);
20155 }
20156 /*
20157 * TODO: Don't free the PSVI IDC tables if they are
20158 * requested for the PSVI.
20159 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020160 xmlSchemaIDCFreeIDCTable(vctxt->nodeInfo->idcTable);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020161 vctxt->nodeInfo->idcTable = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020162 }
20163
20164 /*
20165 * Cleanup IDC matchers.
20166 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020167 if (vctxt->nodeInfo->idcMatchers != NULL) {
20168 xmlSchemaIDCFreeMatcherList(vctxt->nodeInfo->idcMatchers);
20169 vctxt->nodeInfo->idcMatchers = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020170 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020171
20172 /*
20173 * Skip further processing if we are on the validation root.
20174 */
20175 if (vctxt->depth == 0) {
20176 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020177 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020178 }
20179
20180 /*
20181 * Reset the bubbleDepth if needed.
20182 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020183 if (vctxt->aidcs != NULL) {
20184 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
20185 do {
20186 if (aidc->bubbleDepth == vctxt->depth) {
20187 /*
20188 * A bubbleDepth of a key/unique IDC matches the current
20189 * depth, this means that we are leaving the scope of the
20190 * top-most keyref IDC.
20191 */
20192 aidc->bubbleDepth = -1;
20193 }
20194 aidc = aidc->next;
20195 } while (aidc != NULL);
20196 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020197 vctxt->depth--;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020198 /*
20199 * Clear the current elemInfo.
20200 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020201 if (vctxt->nodeInfo->value != NULL) {
20202 xmlSchemaFreeValue(vctxt->nodeInfo->value);
20203 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020204 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020205 vctxt->nodeInfo = vctxt->elemInfos[vctxt->depth];
20206 vctxt->node = vctxt->nodeInfo->node;
20207
20208 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020209}
20210
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020211/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020212 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000020213 * @ctxt: a schema validation context
20214 * @node: the top node.
20215 *
20216 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020217 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000020218 *
20219 * Returns 0 if the element is schemas valid, a positive error code
20220 * number otherwise and -1 in case of internal or API error.
20221 */
20222static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020223xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
20224 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020225{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020226 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020227 int ret = 0;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020228 xmlSchemaTypePtr actualType = NULL, localType = NULL, type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020229 xmlAttrPtr attr;
20230 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020231 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000020232
20233 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020234 * This one is called by xmlSchemaValidateElementByWildcardInternal,
20235 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020236 * Note that @elemDecl will be the declaration and never the
20237 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020238 */
Daniel Veillard3646d642004-06-02 19:19:14 +000020239
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020240 if (ctxt == NULL) {
20241 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
20242 "Internal error: xmlSchemaValidateElementByDeclaration, "
20243 "bad arguments.\n",
20244 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020245 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020246 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020247
20248 elem = ctxt->node;
20249
20250 /*
20251 * cvc-elt (3.3.4) : 1
20252 */
20253 if (elemDecl == NULL) {
20254 xmlSchemaVCustomErr(ctxt,
20255 XML_SCHEMAV_CVC_ELT_1,
20256 elem, NULL,
20257 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020258 /*
20259 * Evaluate IDCs even if an error occured.
20260 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020261 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020262 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020263 return (ctxt->err);
20264 }
20265 /*
20266 * cvc-elt (3.3.4) : 2
20267 */
20268 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
20269 xmlSchemaVCustomErr(ctxt,
20270 XML_SCHEMAV_CVC_ELT_2,
20271 elem, NULL,
20272 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020273 /*
20274 * Evaluate IDCs even if an error occured.
20275 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020276 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020277 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020278 return (ctxt->err);
20279 }
20280
20281 /*
20282 * cvc-elt (3.3.4) : 3
20283 * Handle 'xsi:nil'.
20284 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020285
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020286 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020287 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020288 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
20289 ctxt->node = (xmlNodePtr) attr;
20290 ctxt->cur = attr->children;
20291 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
20292 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
20293 BAD_CAST attrValue, 1, 1, 1, 1);
20294 ctxt->node = elem;
20295 ctxt->type = (xmlSchemaTypePtr) elemDecl;
20296 if (ret < 0) {
20297 xmlSchemaVCustomErr(ctxt,
20298 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020299 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020300 "Internal error: xmlSchemaValidateElementByDeclaration, "
20301 "validating the attribute 'xsi:nil'", NULL);
20302 if (attrValue != NULL)
20303 xmlFree(attrValue);
20304 return (-1);
20305 }
20306 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020307 /*
20308 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020309 */
20310 xmlSchemaVCustomErr(ctxt,
20311 XML_SCHEMAV_CVC_ELT_3_1,
20312 elem, NULL,
20313 "The element is not 'nillable'", NULL);
20314 } else {
20315 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020316 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020317 ret = 0;
20318 /*
20319 * cvc-elt (3.3.4) : 3.2.1
20320 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020321 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
20322 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020323 xmlSchemaVCustomErr(ctxt,
20324 XML_SCHEMAV_CVC_ELT_3_2_1,
20325 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020326 elem, (xmlSchemaTypePtr) elemDecl,
20327 "The 'nilled' element must have no character or "
20328 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020329 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
20330 }
20331 /*
20332 * cvc-elt (3.3.4) : 3.2.2
20333 */
20334 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
20335 (elemDecl->value != NULL)) {
20336 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
20337 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020338 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020339 "There is a fixed value constraint defined for "
20340 "the 'nilled' element", NULL);
20341 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
20342 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020343 if (ret == 0)
20344 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020345 }
20346 }
20347 if (attrValue != NULL)
20348 xmlFree(attrValue);
20349 }
20350
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020351 type = elemDecl->subtypes;
20352 actualType = type;
20353
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020354 /*
20355 * cvc-elt (3.3.4) : 4
20356 * Handle 'xsi:type'.
20357 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020358
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020359 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
20360 if (attr != NULL) {
20361 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020362
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020363 /*
20364 * TODO: We should report a *warning* that the type was overriden
20365 * by the instance.
20366 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020367
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020368 /*
20369 * cvc-elt (3.3.4) : 4.1
20370 */
20371 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
20372 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
20373 &nsName, &local);
20374 if (ret < 0) {
20375 xmlSchemaVCustomErr(ctxt,
20376 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020377 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020378 "Internal error: xmlSchemaValidateElementByDeclaration, "
20379 "validating the attribute 'xsi:type'", NULL);;
20380 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020381 FREE_AND_NULL(nsName)
20382 FREE_AND_NULL(local)
20383 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020384 } else if (ret == 1) {
20385 xmlSchemaVSimpleTypeErr(ctxt,
20386 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
20387 (xmlNodePtr) attr, attrValue,
20388 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
20389 } else if (ret == 2) {
20390 xmlSchemaVCustomErr(ctxt,
20391 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
20392 (xmlNodePtr) attr,
20393 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20394 "The QName value '%s' has no "
20395 "corresponding namespace declaration in scope",
20396 attrValue);
20397 } else {
20398 /*
20399 * cvc-elt (3.3.4) : 4.2
20400 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020401 localType = xmlSchemaGetType(ctxt->schema, local, nsName);
20402 if (localType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020403 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020404
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020405 xmlSchemaVCustomErr(ctxt,
20406 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020407 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020408 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020409 "The value '%s' of the xsi:type attribute does not "
20410 "resolve to a type definition",
20411 xmlSchemaFormatQName(&strA, nsName, local));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020412 FREE_AND_NULL(strA);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020413 } else {
20414 int set = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020415 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020416 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
20417 * "The ·local type definition· must be validly
20418 * derived from the {type definition} given the union of
20419 * the {disallowed substitutions} and the {type definition}'s
20420 * {prohibited substitutions}, as defined in
20421 * Type Derivation OK (Complex) (§3.4.6)
20422 * (if it is a complex type definition),
20423 * or given {disallowed substitutions} as defined in Type
20424 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
20425 * definition)."
20426 *
20427 * {disallowed substitutions}: the "block" on the element decl.
20428 * {prohibited substitutions}: the "block" on the type def.
20429 */
20430 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
20431 (type->flags & XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
20432 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
20433
20434 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
20435 (type->flags & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
20436 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
20437
20438 if (! xmlSchemaCheckCOSDerivedOK(ctxt->schema, localType,
20439 type, set)) {
20440 xmlChar *strA = NULL, *strB = NULL;
20441
20442 xmlSchemaVCustomErrExt(ctxt,
20443 /* TODO: Error code */
20444 XML_SCHEMAV_CVC_ELT_4_2, elem, localType,
20445 "The xsi:type definition '%s' is not validly derived from "
20446 "the type definition '%s'",
20447 xmlSchemaFormatQName(&strA,
20448 localType->targetNamespace,
20449 localType->name),
20450 xmlSchemaFormatQName(&strB,
20451 elemDecl->subtypes->targetNamespace,
20452 elemDecl->subtypes->name), NULL);
20453 FREE_AND_NULL(strA)
20454 FREE_AND_NULL(strB)
20455 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020456 }
20457 }
20458 FREE_AND_NULL(attrValue)
20459 FREE_AND_NULL(nsName)
20460 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020461 }
20462 /* TODO: Change the handling of missing types according to
20463 * the spec.
20464 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000020465 if (localType != NULL)
20466 actualType = localType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020467 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000020468 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020469 XML_SCHEMAV_CVC_TYPE_1,
20470 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000020471 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020472 /*
20473 * Evaluate IDCs even if an error occured.
20474 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020475 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020476 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020477 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020478 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020479
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020480 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020481 * Remember the actual-type definition.
20482 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020483 ctxt->nodeInfo->typeDef = actualType;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020484
20485 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020486 * TODO: Since this should be already checked by the content model automaton,
20487 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
20488 * has been changed to XML_SCHEMAV_INTERNAL.
20489 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020490 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000020491 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020492 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020493 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020494 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020495 "Element %s: missing child %s\n",
20496 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020497 }
20498 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020499 }
20500 */
Daniel Veillard4255d502002-04-16 15:50:10 +000020501 /*
20502 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020503 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020504 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000020505 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020506 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020507 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020508 "Element %s: missing child %s found %s\n",
20509 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020510 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000020511 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020512 */
20513 if (elemHasContent == -1)
20514 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020515
20516 /*
20517 * IDC: Register identity-constraint XPath matchers.
20518 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020519 if (elemDecl->idcs != NULL)
20520 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
20521 /*
20522 * Evaluate IDCs.
20523 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020524 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020525 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020526 /*
20527 * cvc-elt (3.3.4) : 5
20528 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020529 */
Daniel Veillard4255d502002-04-16 15:50:10 +000020530 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020531 * cvc-elt (3.3.4) : 5.1
20532 * If the declaration has a {value constraint},
20533 * the item has neither element nor character [children] and
20534 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020535 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020536 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
20537 /*
20538 * cvc-elt (3.3.4) : 5.1.1
20539 * If the ·actual type definition· is a ·local type definition·
20540 * then the canonical lexical representation of the {value constraint}
20541 * value must be a valid default for the ·actual type definition· as
20542 * defined in Element Default Valid (Immediate) (§3.3.6).
20543 */
20544 /*
20545 * NOTE: 'local' above means types aquired by xsi:type.
20546 */
20547 ret = 0;
20548 if (actualType != elemDecl->subtypes) {
20549 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
20550 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020551 elemDecl->value, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020552 if (ret < 0) {
20553 xmlSchemaVCustomErr(ctxt,
20554 XML_SCHEMAV_INTERNAL,
20555 elem, actualType,
20556 "Internal error: xmlSchemaValidateElementByDeclaration, "
20557 "validating a default value", NULL);
20558 return (-1);
20559 }
20560 }
20561 /*
20562 * cvc-elt (3.3.4) : 5.1.2
20563 * The element information item with the canonical lexical
20564 * representation of the {value constraint} value used as its
20565 * ·normalized value· must be ·valid· with respect to the
20566 * ·actual type definition· as defined by Element Locally Valid (Type)
20567 * (§3.3.4).
20568 */
20569 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020570 * Disable validation of the simple content, if it was already
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020571 * done above.
20572 */
20573 if (ret == 0) {
20574 if (actualType != elemDecl->subtypes)
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020575 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020576 else
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020577 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020578 ctxt->node = elem;
20579 if (ret < 0) {
20580 xmlSchemaVCustomErr(ctxt,
20581 XML_SCHEMAV_INTERNAL,
20582 elem, actualType,
20583 "Internal error: xmlSchemaValidateElementByDeclaration, "
20584 "validating against the type", NULL);
20585 return (-1);
20586 }
20587 /*
20588 * PSVI: Create a text node on the instance element.
20589 */
20590 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
20591 xmlNodePtr textChild;
20592
20593 textChild = xmlNewText(elemDecl->value);
20594 if (textChild == NULL) {
20595 xmlSchemaVCustomErr(ctxt,
20596 XML_SCHEMAV_INTERNAL,
20597 elem, actualType,
20598 "Internal error: xmlSchemaValidateElementByDeclaration, "
20599 "could not create a default text node for the instance",
20600 NULL);
20601 } else
20602 xmlAddChild(elem, textChild);
20603 }
20604 }
20605
20606 } else {
20607 /*
20608 * 5.2.1 The element information item must be ·valid· with respect
20609 * to the ·actual type definition· as defined by Element Locally
20610 * Valid (Type) (§3.3.4).
20611 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020612 ret = xmlSchemaValidateElementByType(ctxt, actualType, nilled, 1);
20613 /*
20614 * Consume the computed value for IDCs, ect. Note that default
20615 * values are not supported yet.
20616 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020617 if (ctxt->value != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020618 ctxt->nodeInfo->value = ctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020619 ctxt->value = NULL;
20620 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020621 ctxt->node = elem;
20622 if (ret < 0) {
20623 xmlSchemaVCustomErr(ctxt,
20624 XML_SCHEMAV_INTERNAL,
20625 elem, actualType,
20626 "Internal error: xmlSchemaValidateElementByDeclaration, "
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000020627 "calling validation by type", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020628 return (-1);
20629 }
20630 /*
20631 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
20632 * not applied, all of the following must be true:
20633 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020634 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
20635 /*
20636 * 5.2.2.1 The element information item must have no element
20637 * information item [children].
20638 *
20639 * TODO REDUNDANT: If the actual type exists, the above call to
20640 * xmlSchemaValidateElementByType will already check for element
20641 * nodes.
20642 */
20643 if (xmlSchemaHasElemContent(elem)) {
20644 xmlSchemaVCustomErr(ctxt,
20645 XML_SCHEMAV_CVC_ELT_5_2_2_1,
20646 elem, (xmlSchemaTypePtr) elemDecl,
20647 "Elements in the content are not allowed if it is "
20648 "constrained by a fixed value", NULL);
20649 } else {
20650 /*
20651 * 5.2.2.2 The appropriate case among the following must
20652 * be true:
20653 */
20654
20655 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
20656 xmlChar *value;
20657 /*
20658 * 5.2.2.2.1 If the {content type} of the ·actual type
20659 * definition· is mixed, then the *initial value* of the
20660 * item must match the canonical lexical representation
20661 * of the {value constraint} value.
20662 *
20663 * ... the *initial value* of an element information
20664 * item is the string composed of, in order, the
20665 * [character code] of each character information item in
20666 * the [children] of that element information item.
20667 */
20668 value = xmlNodeListGetString(elem->doc, elem->children, 1);
20669 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
20670 /*
20671 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020672 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020673 */
20674 xmlSchemaVCustomErr(ctxt,
20675 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
20676 elem, (xmlSchemaTypePtr) elemDecl,
20677 "The value does not match the cononical "
20678 "lexical representation of the fixed constraint",
20679 NULL);
20680 }
20681 if (value != NULL)
20682 xmlFree(value);
20683 } else if ((actualType->contentType ==
20684 XML_SCHEMA_CONTENT_SIMPLE) ||
20685 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
20686 xmlChar *value;
20687
20688 /*
20689 * 5.2.2.2.2 If the {content type} of the ·actual type
20690 * definition· is a simple type definition, then the
20691 * *actual value* of the item must match the canonical
20692 * lexical representation of the {value constraint} value.
20693 */
20694 /*
20695 * TODO: *actual value* is the normalized value, impl. this.
20696 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020697 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020698 *
20699 */
20700 value = xmlNodeListGetString(elem->doc, elem->children, 1);
20701 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
20702 xmlSchemaVCustomErr(ctxt,
20703 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
20704 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020705 "The normalized value does not match the canonical "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020706 "lexical representation of the fixed constraint",
20707 NULL);
20708 }
20709 if (value != NULL)
20710 xmlFree(value);
20711
20712 }
20713 /*
20714 * TODO: What if the content type is not 'mixed' or simple?
20715 */
20716
20717 }
20718
20719 }
20720 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020721 /*
20722 * TODO: 7 If the element information item is the ·validation root·, it must be
20723 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
20724 */
20725
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020726 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000020727}
20728
Daniel Veillard4255d502002-04-16 15:50:10 +000020729/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020730 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000020731 * @ctxt: a schema validation context
20732 * @node: the top node.
20733 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020734 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
20735 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000020736 *
20737 * Returns 0 if the element is valid, a positive error code
20738 * number otherwise and -1 in case of an internal error.
20739 */
20740static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020741xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
20742 xmlSchemaWildcardPtr wild,
20743 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000020744{
20745 const xmlChar *uri;
20746 int ret = 0;
20747 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020748
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020749 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020750 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
20751 if (ret == -1) {
20752 xmlSchemaVCustomErr(ctxt,
20753 XML_SCHEMAV_INTERNAL,
20754 ctxt->node, NULL,
20755 "Internal error: xmlSchemaValidateElement, "
20756 "assembling schema by xsi", NULL);
20757 return (-1);
20758 }
20759 /*
20760 * NOTE: We won't react on schema parser errors here.
20761 * TODO: But a warning would be nice.
20762 */
20763 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000020764 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
20765 xmlSchemaElementPtr decl = NULL;
20766
20767 if (node->ns != NULL)
20768 decl = xmlHashLookup3(ctxt->schema->elemDecl,
20769 node->name, node->ns->href, NULL);
20770 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020771 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
20772 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000020773 if (decl != NULL) {
20774 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020775 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000020776 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020777 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000020778 "Internal error: xmlSchemaValidateAnyInternal, "
20779 "validating an element in the context of a wildcard.",
20780 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000020781 }
20782 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000020783 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
20784 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020785 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020786 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020787 /*
20788 * Evaluate IDCs even if a validation error occured.
20789 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020790 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020791 return(-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020792
Daniel Veillardc0826a72004-08-10 14:17:33 +000020793 return (ctxt->err);
20794 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020795 /*
20796 * Evaluate IDCs; we need to know if an IDC field resolves to
20797 * such a node. This node has no type definition and will
20798 * definitely result in an IDC validation error if an IDC field
20799 * resolves.
20800 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020801 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020802 return(-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000020803 }
20804 if (node->children != NULL) {
20805 child = node->children;
20806 do {
20807 if (child->type == XML_ELEMENT_NODE) {
20808 if (child->ns != NULL)
20809 uri = child->ns->href;
20810 else
20811 uri = NULL;
20812 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020813 /* TODO: error code. */
20814 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000020815 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020816 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000020817 return (ctxt->err);
20818 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020819
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020820 ctxt->node = child;
20821 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020822
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020823 /*
20824 * Recurse over the children.
20825 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020826 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
20827 wild, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020828 if (ret == -1)
20829 return (-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020830
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020831 if (xmlSchemaEndElement(ctxt) == -1)
20832 return (-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020833
Daniel Veillardc0826a72004-08-10 14:17:33 +000020834 if (ret != 0)
20835 return (ret);
20836 }
20837 child = child->next;
20838 } while (child != NULL);
20839 }
20840 return (0);
20841}
20842
20843/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020844 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000020845 * @ctxt: a schema validation context
20846 *
20847 * Returns 0 if the element is valid, a positive error code
20848 * number otherwise and -1 in case of an internal or API error.
20849 */
20850static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020851xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020852 xmlSchemaWildcardPtr wild)
Daniel Veillardc0826a72004-08-10 14:17:33 +000020853{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020854
20855 if ((wild == NULL) || (wild->type != XML_SCHEMA_TYPE_ANY) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020856 (ctxt->node == NULL)) {
20857 xmlSchemaVCustomErr(ctxt,
20858 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
20859 "Internal error: xmlSchemaValidateElementByWildcard, "
20860 "bad arguments", NULL);
20861 return (-1);
20862 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020863 if (wild->negNsSet != NULL) {
20864 /*
20865 * Workaround for negated namespaces.
20866 */
20867 if (ctxt->node->ns != NULL) {
20868 if (xmlSchemaMatchesWildcardNs(wild, ctxt->node->ns->href) == 0) {
20869 ctxt->flags |= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD;
20870 return (XML_SCHEMAV_ELEMENT_CONTENT);
20871 }
20872 } else if (xmlSchemaMatchesWildcardNs(wild, NULL) == 0) {
20873 ctxt->flags |= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD;
20874 return (XML_SCHEMAV_ELEMENT_CONTENT);
20875 }
20876 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020877 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020878 wild, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000020879}
20880
20881/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020882 * xmlSchemaValidateElementByAnyType:
William M. Brack2f2a6632004-08-20 23:09:47 +000020883 * @ctxt: a schema validation context
20884 * @node: the current element
20885 *
20886 * This one validates the content of an element of the type
20887 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
20888 * thus elements in the subtree will be validated, if a corresponding
20889 * declaration in the schema exists.
20890 *
20891 * Returns 0 if the element and its subtree is valid, a positive error code
20892 * otherwise and -1 in case of an internal or API error.
20893 */
20894static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020895xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
20896 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000020897{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020898 xmlSchemaTypePtr oldtype;
20899 xmlNodePtr top, cur;
20900 xmlSchemaElementPtr decl;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020901 int skipContent, ret, insub = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020902
20903 if ((type == NULL) || (ctxt->node == NULL))
20904 return (-1);
20905
20906 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000020907 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020908
20909 oldtype = ctxt->type;
20910 top = ctxt->node;
20911 /*
20912 * STREAM: Child nodes are processed.
20913 */
20914 cur = ctxt->node->children;
20915 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000020916 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020917 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000020918 /*
20919 * The process contents of the wildcard is "lax", thus
20920 * we need to validate the element if a declaration
20921 * exists.
20922 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020923 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000020924 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020925 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000020926 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020927 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
20928 ctxt->node = cur;
20929
20930 if (insub) {
20931 /*
20932 * BEGIN element.
20933 */
20934 xmlSchemaBeginElement(ctxt);
20935 } else
20936 insub = 1;
20937
20938 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020939 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
20940 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000020941 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020942 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000020943 "Internal error: xmlSchemaValidateAnyTypeContent, "
20944 "validating an element in the context of a wildcard.",
20945 NULL, NULL);
20946 return (ret);
20947 } else if (ret > 0)
20948 return (ret);
20949 skipContent = 1;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020950 } else {
20951 /*
20952 * IDCs.
20953 */
20954 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
20955 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000020956 }
20957 }
20958 /*
20959 * Browse the full subtree, deep first.
20960 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020961 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000020962 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020963 cur = cur->children;
20964 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000020965 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020966 cur = cur->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020967 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000020968 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020969 while (cur != top) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020970 if (cur->type == XML_ELEMENT_NODE) {
20971 /*
20972 * END element.
20973 */
20974 xmlSchemaEndElement(ctxt);
20975 }
20976 if (cur->parent != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020977 cur = cur->parent;
20978 if ((cur != top) && (cur->next != NULL)) {
20979 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000020980 break;
20981 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020982 if (cur->parent == NULL) {
20983 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000020984 break;
20985 }
20986 }
20987 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020988 if (cur == top)
20989 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000020990 } else
20991 break;
20992 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020993 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000020994 return (0);
20995}
20996
20997/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020998 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000020999 * @ctxt: a schema validation context
21000 * @node: the top node.
21001 *
21002 * Validate the content of an element expected to be a complex type type
21003 * xmlschema-1.html#cvc-complex-type
21004 * Validation Rule: Element Locally Valid (Complex Type)
21005 *
21006 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000021007 * number otherwise and -1 in case of internal or API error.
21008 * Note on reported errors: Although it might be nice to report
21009 * the name of the simple/complex type, used to validate the content
21010 * of a node, it is quite unnecessary: for global defined types
21011 * the local name of the element is equal to the NCName of the type,
21012 * for local defined types it makes no sense to output the internal
21013 * computed name of the type. TODO: Instead, one should attach the
21014 * struct of the type involved to the error handler - this allows
21015 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000021016 */
21017static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021018xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021019 xmlSchemaTypePtr type,
21020 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021021{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021022 xmlSchemaTypePtr oldtype;
21023 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000021024 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000021025 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021026 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000021027
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021028 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
21029 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000021030
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021031 oldtype = ctxt->type;
21032 ctxt->type = type;
21033 elem = ctxt->node;
21034
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021035 /*
21036 * Verify the attributes
21037 */
21038 /*
21039 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021040 */
21041 /* NOTE: removed, since a check for abstract is
21042 * done in the cvc-type constraint.
21043 *
21044 *
21045 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
21046 * xmlSchemaVComplexTypeErr(ctxt,
21047 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
21048 * elem, type,
21049 * "The type definition is abstract");
21050 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
21051 *}
21052 */
21053
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021054 attrs = ctxt->attr;
21055 attrTop = ctxt->attrTop;
21056 /*
21057 * STREAM: Attribute nodes are processed.
21058 */
21059 xmlSchemaRegisterAttributes(ctxt, elem->properties);
21060 xmlSchemaValidateAttributes(ctxt, elem, type);
21061 if (ctxt->attr != NULL)
21062 xmlSchemaFreeAttributeStates(ctxt->attr);
21063 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021064 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021065
21066 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021067 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021068 * model was defined. Somehow ->contModel is always not NULL
21069 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021070 * TODO: Check if the obove still occurs.
21071 */
Daniel Veillard4255d502002-04-16 15:50:10 +000021072 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000021073 case XML_SCHEMA_CONTENT_EMPTY: {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021074 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021075 * 1 If the {content type} is empty, then the element information
21076 * item has no character or element information item [children].
21077 */
21078 /*
21079 * TODO: Is the entity stuff correct?
21080 */
21081 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
21082 xmlSchemaVComplexTypeErr(ctxt,
21083 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
21084 elem, type,
21085 "Character or element content is not allowed, "
21086 "because the content type is empty");
21087 }
21088 break;
21089 }
21090 case XML_SCHEMA_CONTENT_MIXED:
21091 /*
21092 * Some speedups for anyType or types derived directly from it.
21093 */
21094 if (IS_ANYTYPE(type)) {
21095 /*
21096 * Corresponds to <element name="foo" [type="xsd:anyType"]/>.
21097 */
21098 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
21099 /* TODO: Handle -1. */
21100 break;
21101 }
21102 if (IS_ANYTYPE(type->baseType) &&
21103 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
21104 (type->subtypes == type->baseType->subtypes)) {
21105 /*
21106 * Corresponds to an <extension> of anyType.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021107 */
21108 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
21109 /* TODO: Handle -1. */
21110 break;
21111 }
21112 /* No break on purpose. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021113 case XML_SCHEMA_CONTENT_ELEMENTS: {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021114 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021115 xmlChar *values[10];
21116 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021117 /*
21118 * SPEC (2.4) If the {content type} is element-only or mixed,
21119 * then the sequence of the element information item's
21120 * element information item [children], if any, taken in
21121 * order, is ·valid· with respect to the {content type}'s
21122 * particle, as defined in Element Sequence Locally Valid
21123 * (Particle) (§3.9.4).
21124 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021125 /*
21126 * Content model check initialization.
21127 */
21128 if (type->contModel != NULL) {
21129 oldregexp = ctxt->regexp;
21130 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
21131 (xmlRegExecCallbacks)
21132 xmlSchemaValidateCallback, ctxt);
21133#ifdef DEBUG_AUTOMATA
21134 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
21135#endif
21136 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021137 /*
21138 * STREAM: Children are processed.
21139 */
21140 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000021141 while (child != NULL) {
21142 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000021143 if (child->ns != NULL)
21144 nsUri = child->ns->href;
21145 else
21146 nsUri = NULL;
21147 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021148 child->name, nsUri, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021149 if (ctxt->err == XML_SCHEMAV_INTERNAL)
21150 return (-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021151 if (ctxt->flags & XML_SCHEMA_VALID_INVALID_NEG_WILDCARD) {
21152 ctxt->flags ^= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD;
21153 ret = -1;
21154 }
21155 /*
21156 * URGENT TODO: Could we anchor an error report
21157 * here to notify of invalid elements?
21158 * TODO: Perhaps it would be better to report
21159 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021160 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021161#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000021162 if (ret < 0)
21163 xmlGenericError(xmlGenericErrorContext,
21164 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000021165 else
21166 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000021167 " --> %s\n", child->name);
21168#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021169 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021170 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
21171 &values[0], &terminal);
21172 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021173 XML_SCHEMAV_ELEMENT_CONTENT,
21174 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021175 "This element is not expected",
21176 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021177 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021178 /*
21179 * Note that this will skip further validation of the
21180 * content.
21181 */
21182 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021183 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000021184 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
21185 /*
21186 * TODO: Ask Daniel if this are all character nodes.
21187 */
21188 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
21189 (child->type == XML_ENTITY_NODE) ||
21190 (child->type == XML_ENTITY_REF_NODE) ||
21191 (child->type == XML_CDATA_SECTION_NODE))) {
21192 /*
21193 * 2.3 If the {content type} is element-only, then the
21194 * element information item has no character information
21195 * item [children] other than those whose [character
21196 * code] is defined as a white space in [XML 1.0 (Second
21197 * Edition)].
21198 */
William M. Brack2f2a6632004-08-20 23:09:47 +000021199 xmlSchemaVComplexTypeErr(ctxt,
21200 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021201 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000021202 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021203 "because the content type is element-only");
21204 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000021205 break;
21206 }
21207 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021208 }
21209 /*
21210 * Content model check finalization.
21211 */
21212 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021213 if (ret == 0) {
21214 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021215 &values[0], &terminal);
Daniel Veillard0e460da2005-03-30 22:47:10 +000021216 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021217 * If a next value still exists, It does not have to
Daniel Veillard0e460da2005-03-30 22:47:10 +000021218 * mean that there's an element missing, since it
21219 * might be an optional element. So double check it.
21220 */
21221 ret = xmlRegExecPushString(ctxt->regexp,
21222 NULL, NULL);
21223 if (ret <= 0) {
21224 ret = 1;
21225 xmlSchemaVComplexTypeElemErr(ctxt,
21226 XML_SCHEMAV_ELEMENT_CONTENT,
21227 elem, type, "Missing child element(s)",
21228 nbval, nbneg, values);
21229 } else
21230 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021231#ifdef DEBUG_AUTOMATA
Daniel Veillard0e460da2005-03-30 22:47:10 +000021232 xmlGenericError(xmlGenericErrorContext,
21233 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021234#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021235#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021236 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021237 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021238 "Element %s content check succeeded\n",
21239 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021240#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021241 }
21242 xmlRegFreeExecCtxt(ctxt->regexp);
21243 ctxt->regexp = oldregexp;
21244 }
21245 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000021246 break;
21247 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021248 case XML_SCHEMA_CONTENT_BASIC:
21249 /*
21250 * If the simple content was already validated
21251 * (e.g. a default value), the content need not
21252 * to be validated again.
21253 */
21254 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000021255 xmlChar *value = NULL;
21256 /*
21257 * We hit a complexType with a simpleContent resolving
21258 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000021259 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000021260 /*
21261 * 2.2 If the {content type} is a simple type definition,
21262 * then the element information item has no element
21263 * information item [children], and the ·normalized value·
21264 * of the element information item is ·valid· with respect
21265 * to that simple type definition as defined by String
21266 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021267 */
21268 /*
21269 * STREAM: Children are processed.
21270 */
21271 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000021272 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021273 /*
21274 * TODO: Could the entity stuff produce elements
21275 * as well?
21276 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000021277 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021278 xmlSchemaVComplexTypeErr(ctxt,
21279 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021280 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000021281 "Element content is not allowed, because "
21282 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000021283 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
21284 break;
21285 }
21286 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021287 }
21288 ctxt->node = elem;
21289 ctxt->cur = elem->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021290 if (ret != 0) {
21291 FREE_AND_NULL(value)
21292 break;
21293 }
21294 /*
21295 * Validate the character content against a simple type.
21296 */
21297 if (elem->children == NULL)
21298 value = NULL;
21299 else
21300 value = xmlNodeGetContent(elem);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021301 /*
21302 * NOTE: This call won't check the correct types of the
21303 * content nodes, since this should be done here.
21304 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021305 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
21306 type->contentTypeDef, value, 1, 1, 1, 0);
21307 if (ret > 0) {
21308 /*
21309 * NOTE: Although an error will be reported by
21310 * xmlSchemaValidateSimpleTypeValue, the spec wants
21311 * a specific complex type error to be reported
21312 * additionally.
21313 */
21314 xmlSchemaVComplexTypeErr(ctxt,
21315 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
21316 elem, type,
21317 "The character content is not valid");
21318 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
21319 } else if (ret < 0) {
21320 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
21321 "Internal error: xmlSchemaValidateComplexType, "
21322 "Element '%s': Error while validating character "
21323 "content against complex type '%s'.\n",
21324 elem->name, type->name);
21325 if (value != NULL)
21326 xmlFree(value);
21327 ctxt->type = oldtype;
21328 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021329 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000021330 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021331 xmlFree(value);
21332
Daniel Veillard01fa6152004-06-29 17:04:39 +000021333 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021334 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021335 default:
21336 TODO xmlGenericError(xmlGenericErrorContext,
21337 "unimplemented content type %d\n",
21338 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000021339 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021340 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021341 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000021342}
21343
21344/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021345 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000021346 * @ctxt: a schema validation context
21347 * @elem: an element
21348 * @type: the list of type declarations
21349 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021350 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000021351 *
21352 * Returns 0 if the element is schemas valid, a positive error code
21353 * number otherwise and -1 in case of internal or API error.
21354 */
21355static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021356xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021357 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021358 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021359 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021360{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021361 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000021362
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021363
21364 if ((ctxt == NULL) || (type == NULL)) {
21365 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
21366 "Internal error: xmlSchemaValidateElementByType, "
21367 "bad arguments", NULL);
21368 return (-1);
21369 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021370 /*
21371 * This one is called by "xmlSchemaValidateElementByDeclaration".
21372 * It will forward to the proper validation
21373 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021374 */
21375 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021376 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021377 XML_SCHEMAV_CVC_TYPE_1,
21378 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021379 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021380 return (XML_SCHEMAV_CVC_TYPE_1);
21381 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021382
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021383 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021384 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021385 XML_SCHEMAV_CVC_TYPE_2,
21386 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021387 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021388 return (XML_SCHEMAV_CVC_TYPE_2);
21389 }
21390
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021391 switch (type->type) {
21392 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021393 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
21394 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021395 break;
21396 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021397 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021398 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021399 break;
21400 case XML_SCHEMA_TYPE_BASIC:
21401 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
21402 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
21403 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021404 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021405 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021406 break;
21407 default:
21408 ret = -1;
21409 break;
21410 }
21411 if (ret == -1)
21412 return (-1);
21413 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021414 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000021415}
21416
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021417static int
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021418xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021419 xmlSchemaTypePtr type,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021420 const xmlChar *value,
21421 xmlSchemaValPtr *val)
21422{
21423 xmlSchemaTypePtr prim;
21424
21425 if (val == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021426 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021427 XML_SCHEMAV_INTERNAL,
21428 "Internal error: xmlSchemaPostCreateVal, "
21429 "bad arguments", NULL, NULL);
21430 return (-1);
21431 }
21432 /*
21433 * Only string or anySimpleType values are expected to be post-created.
21434 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021435 prim = xmlSchemaGetPrimitiveType(type);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021436 if ((prim->builtInType == XML_SCHEMAS_STRING) ||
21437 (prim->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21438 {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021439 if (value == NULL)
21440 /* TODO: Can this happen at all? */
21441 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
21442 xmlStrdup(BAD_CAST ""));
21443 else
21444 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING, value);
21445 if ((*val) == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021446 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021447 XML_SCHEMAV_INTERNAL,
21448 "Internal error: xmlSchemaPostCreateVal, "
21449 "failed to create the value", NULL, NULL);
21450 return (-1);
21451 }
21452 return (0);
21453 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021454 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021455 XML_SCHEMAV_INTERNAL,
21456 "Internal error: xmlSchemaPostCreateVal, "
21457 "the given type is not supported", NULL, NULL);
21458 return (-1);
21459}
21460
21461static int
21462xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021463 xmlSchemaAttrStatePtr state)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021464{
21465 xmlChar *value;
21466 const xmlChar *defValue;
21467 xmlSchemaValPtr defVal;
21468 int fixed;
21469 int ret;
21470
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021471 if (vctxt->attrInfo->typeDef == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021472 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
21473 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
21474 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021475 vctxt->node = vctxt->attrInfo->node;
21476 vctxt->cur = vctxt->node->children;
21477 /* STREAM */
21478 value = xmlNodeListGetString(vctxt->node->doc, vctxt->cur, 1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021479
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021480 /*
21481 * NOTE: This call also checks the content nodes for correct type.
21482 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021483 ret = xmlSchemaValidateSimpleTypeValue(vctxt, vctxt->attrInfo->typeDef,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021484 value, 1, 1, 1, 1);
21485
21486 /*
21487 * Handle 'fixed' attributes.
21488 */
21489 if (ret > 0) {
21490 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21491 /*
21492 * NOTE: Fixed value constraints will be not
21493 * applied if the value was invalid, because:
21494 * 1. The validation process does not return a precomputed
21495 * value.
21496 * 2. An invalid value implies a violation of a fixed
21497 * value constraint.
21498 */
21499 } else if (ret == 0) {
21500 state->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021501 if (xmlSchemaGetEffectiveValueConstraint(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021502 (xmlSchemaAttributePtr) vctxt->attrInfo->decl,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021503 &fixed, &defValue, &defVal) && (fixed == 1)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000021504
21505 int ws = xmlSchemaGetWhiteSpaceFacetValue(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021506 vctxt->nodeInfo->typeDef);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021507 /*
21508 * cvc-au : Attribute Locally Valid (Use)
21509 * For an attribute information item to be·valid·
21510 * with respect to an attribute use its ·normalized
21511 * value· must match the canonical lexical representation
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021512 * of the attribute use's {value constraint} value, if it
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021513 * is present and fixed.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021514 *
21515 * TODO: Use somehow the *normalized* value and the *canonical*
21516 * fixed value. This here compares the canonical values of both.
21517 * The normalized value of, for example, a float type can differ
21518 * from its canonical representation. This all means that a fixed
21519 * value can only be OK, if it's present in the canonical form in
21520 * the instance.
21521 * NOTE: Since the value for string and anySimpleType is not always
21522 * precomputed during validation, we need to do it now.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021523 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021524 if (vctxt->value == NULL) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000021525 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021526 * Post-create the value.
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000021527 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021528 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
21529 value, &(vctxt->value)) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021530 ret = -1;
21531 goto exit;
21532 }
21533 value = NULL;
21534 }
21535 if (defVal == NULL) {
21536 xmlChar *str;
21537
21538 /*
21539 * Post-create the default/fixed value.
21540 */
21541 if (defValue == NULL)
21542 str = xmlStrdup(BAD_CAST "");
21543 else
21544 str = xmlStrdup(defValue);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021545 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
21546 str, &defVal) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021547 ret = -1;
21548 FREE_AND_NULL(str)
21549 goto exit;
21550 }
21551 ((xmlSchemaAttributePtr) vctxt->attrInfo->decl)->defVal = defVal;
21552 }
21553 if (xmlSchemaCompareValuesWhtsp(vctxt->value,
21554 (xmlSchemaWhitespaceValueType) ws,
21555 defVal,
21556 (xmlSchemaWhitespaceValueType) ws) != 0)
21557 {
21558 state->state = XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021559 }
21560 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021561 }
21562exit:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021563 if (value != NULL) {
21564 xmlFree(value);
21565 }
21566 return (ret);
21567}
21568
Daniel Veillard4255d502002-04-16 15:50:10 +000021569/**
21570 * xmlSchemaValidateAttributes:
21571 * @ctxt: a schema validation context
21572 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000021573 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000021574 *
21575 * Validate the attributes of an element.
21576 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000021577 * 1. Existent, invalid attributes are reported in the form
21578 * "prefix:localName".
21579 * Reason: readability - it is easier to find the actual XML
21580 * representation of the attributes QName.
21581 * 2. Missing attributes are reported in the form
21582 * {"URI", "localName"}.
21583 * This is necessary, since the the prefix need not to be declared
21584 * at all, and thus is not computable.
21585 *
Daniel Veillard4255d502002-04-16 15:50:10 +000021586 * Returns 0 if the element is schemas valid, a positive error code
21587 * number otherwise and -1 in case of internal or API error.
21588 */
21589static int
Daniel Veillard3646d642004-06-02 19:19:14 +000021590xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021591{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021592 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000021593 int ret;
21594 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021595 const xmlChar *defValue;
21596 xmlSchemaValPtr defVal;
21597 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021598 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000021599 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000021600 int found;
William M. Brack803812b2004-06-03 02:11:24 +000021601 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021602 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021603 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000021604#ifdef DEBUG_ATTR_VALIDATION
21605 int redundant = 0;
21606#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000021607
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021608
Daniel Veillardc0826a72004-08-10 14:17:33 +000021609 /*
21610 * Allow all attributes if the type is anyType.
21611 */
21612 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
21613 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021614
21615 oldnode = ctxt->node;
21616 if (type != NULL)
21617 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000021618 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000021619 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000021620 attrDecl = attrUse->attr;
21621#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021622 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000021623 printf("attr use - use: %d\n", attrDecl->occurs);
21624#endif
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021625 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
Daniel Veillard3646d642004-06-02 19:19:14 +000021626
21627 if (curState->decl == attrUse->attr) {
21628#ifdef DEBUG_ATTR_VALIDATION
21629 redundant = 1;
21630#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021631 }
Daniel Veillard3646d642004-06-02 19:19:14 +000021632 attr = curState->attr;
21633#ifdef DEBUG_ATTR_VALIDATION
21634 printf("attr - name: %s\n", attr->name);
21635 if (attr->ns != NULL)
21636 printf("attr - ns: %s\n", attr->ns->href);
21637 else
21638 printf("attr - ns: none\n");
21639#endif
21640 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021641 if (attr == NULL)
21642 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000021643 if (attrDecl->ref != NULL) {
21644 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021645 continue;
21646 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000021647 if ((attrDecl->refNs == NULL) ||
21648 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021649 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000021650 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021651 continue;
21652 }
21653 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000021654 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021655 continue;
21656 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000021657 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021658 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000021659 if (attr->ns == NULL) {
21660 /*
William M. Bracke7091952004-05-11 15:09:58 +000021661 * accept an unqualified attribute only if the target
21662 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000021663 */
Daniel Veillard3646d642004-06-02 19:19:14 +000021664 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000021665 /*
21666 * This check was removed, since the target namespace
21667 * was evaluated during parsing and already took
21668 * "attributeFormDefault" into account.
21669 */
21670 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000021671 continue;
21672 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000021673 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000021674 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000021675 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000021676 attr->ns->href))
21677 continue;
21678 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021679 }
Daniel Veillard3646d642004-06-02 19:19:14 +000021680#ifdef DEBUG_ATTR_VALIDATION
21681 printf("found\n");
21682#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021683 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000021684 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021685 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
21686 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021687 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021688 */
Daniel Veillard3646d642004-06-02 19:19:14 +000021689 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021690 if (!found) {
21691 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21692 xmlSchemaAttrStatePtr tmp;
21693
Daniel Veillard3646d642004-06-02 19:19:14 +000021694#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021695 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000021696#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021697 /*
21698 * Add a new dummy attribute state.
21699 */
21700 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
21701 if (tmp == NULL) {
21702 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
21703 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021704 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021705 }
21706 tmp->attr = NULL;
21707 tmp->state = XML_SCHEMAS_ATTR_MISSING;
21708 tmp->decl = attrDecl;
21709 tmp->next = NULL;
21710
21711 if (reqAttrStates == NULL) {
21712 reqAttrStates = tmp;
21713 reqAttrStatesTop = tmp;
21714 } else {
21715 reqAttrStatesTop->next = tmp;
21716 reqAttrStatesTop = tmp;
21717 }
21718 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21719 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
21720 &fixed, &defValue, &defVal))) {
21721 xmlSchemaAttrStatePtr tmp;
21722 /*
21723 * Handle non existent default/fixed attributes.
21724 */
21725 tmp = (xmlSchemaAttrStatePtr)
21726 xmlMalloc(sizeof(xmlSchemaAttrState));
21727 if (tmp == NULL) {
21728 xmlSchemaVErrMemory(ctxt,
21729 "registering schema specified attributes", NULL);
21730 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021731 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021732 }
21733 tmp->attr = NULL;
21734 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
21735 tmp->decl = attrDecl;
21736 tmp->value = defValue;
21737 tmp->next = NULL;
Kasimier T. Buchcika62f75f2005-03-21 22:01:47 +000021738 if (defAttrStatesTop == NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021739 defAttrStates = tmp;
Kasimier T. Buchcika62f75f2005-03-21 22:01:47 +000021740 else
21741 defAttrStatesTop->next = tmp;
21742 defAttrStatesTop = tmp;
21743 }
Daniel Veillard3646d642004-06-02 19:19:14 +000021744 }
21745 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000021746 }
Daniel Veillard3646d642004-06-02 19:19:14 +000021747 /*
21748 * Add required attributes to the attribute states of the context.
21749 */
21750 if (reqAttrStates != NULL) {
21751 if (ctxt->attr == NULL) {
21752 ctxt->attr = reqAttrStates;
21753 } else {
21754 ctxt->attrTop->next = reqAttrStates;
21755 }
21756 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000021757 }
Daniel Veillard3646d642004-06-02 19:19:14 +000021758 /*
21759 * Process wildcards.
21760 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021761
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021762 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000021763#ifdef DEBUG_ATTR_VALIDATION
21764 xmlSchemaWildcardNsPtr ns;
21765 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000021766 if (type->attributeWildcard->processContents ==
21767 XML_SCHEMAS_ANY_LAX)
21768 printf("processContents: lax\n");
21769 else if (type->attributeWildcard->processContents ==
21770 XML_SCHEMAS_ANY_STRICT)
21771 printf("processContents: strict\n");
21772 else
21773 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000021774 if (type->attributeWildcard->any)
21775 printf("type: any\n");
21776 else if (type->attributeWildcard->negNsSet != NULL) {
21777 printf("type: negated\n");
21778 if (type->attributeWildcard->negNsSet->value == NULL)
21779 printf("ns: (absent)\n");
21780 else
21781 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
21782 } else if (type->attributeWildcard->nsSet != NULL) {
21783 printf("type: set\n");
21784 ns = type->attributeWildcard->nsSet;
21785 while (ns != NULL) {
21786 if (ns->value == NULL)
21787 printf("ns: (absent)\n");
21788 else
21789 printf("ns: %s\n", ns->value);
21790 ns = ns->next;
21791 }
21792 } else
21793 printf("empty\n");
21794
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000021795
21796#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000021797 curState = ctxt->attr;
21798 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000021799 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
21800 if (curState->attr->ns != NULL)
21801 nsURI = curState->attr->ns->href;
21802 else
21803 nsURI = NULL;
21804 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
21805 nsURI)) {
21806 /*
21807 * Handle processContents.
21808 */
21809 if ((type->attributeWildcard->processContents ==
21810 XML_SCHEMAS_ANY_LAX) ||
21811 (type->attributeWildcard->processContents ==
21812 XML_SCHEMAS_ANY_STRICT)) {
21813
21814 attr = curState->attr;
21815 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021816 attr->name, nsURI);
21817 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000021818 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000021819 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021820 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
21821 /* TODO
21822 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
21823 */
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000021824 } else if (type->attributeWildcard->processContents ==
21825 XML_SCHEMAS_ANY_LAX) {
21826 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021827 } else
21828 curState->state = XML_SCHEMAS_ATTR_WILD_NO_DECL;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000021829 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000021830 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021831 }
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000021832 }
Daniel Veillard3646d642004-06-02 19:19:14 +000021833 curState = curState->next;
21834 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021835 }
21836
Daniel Veillardc0826a72004-08-10 14:17:33 +000021837 if (ctxt->attr != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021838 int valueNeeded;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021839
21840 /*
21841 * Validate the value of the attribute.
21842 */
21843 if (ctxt->value != NULL) {
21844 xmlSchemaFreeValue(ctxt->value);
21845 ctxt->value = NULL;
21846 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000021847 curState = ctxt->attr;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021848 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021849 valueNeeded = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021850 switch (curState->state) {
21851 case XML_SCHEMAS_ATTR_VALIDATE_VALUE:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021852
21853 /*
21854 * Create an attribute info if needed.
21855 */
21856 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021857 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
21858 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021859 if (ctxt->attrInfo == NULL) {
21860 xmlSchemaVErrMemory(ctxt,
21861 "allocating an attribute info", NULL);
21862 goto fatal_exit;
21863 }
21864 }
21865 /*
21866 * Init the attribute info.
21867 */
21868 ctxt->attrInfo->flags = 0;
21869 ctxt->attrInfo->node = (xmlNodePtr) curState->attr;
21870 ctxt->attrInfo->decl = (xmlSchemaTypePtr) curState->decl;
21871 ctxt->attrInfo->value = NULL;
21872 if (curState->decl != NULL)
21873 ctxt->attrInfo->typeDef = curState->decl->subtypes;
21874 else
21875 ctxt->attrInfo->typeDef = NULL;
21876 if (curState->attr->ns != NULL)
21877 ctxt->attrInfo->namespaceName =
21878 curState->attr->ns->href;
21879 else
21880 ctxt->attrInfo->namespaceName = NULL;
21881 ctxt->attrInfo->localName = curState->attr->name;
21882
21883 ctxt->nodeInfo = ctxt->attrInfo;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021884 /*
21885 * Evaluate IDCs.
21886 */
21887 if (ctxt->xpathStates != NULL) {
21888 ret = xmlSchemaXPathEvaluate(ctxt,
21889 XML_ATTRIBUTE_NODE);
21890 if (ret == -1)
21891 goto fatal_exit;
21892 }
21893
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021894 ret = xmlSchemaCheckAttrLocallyValid(ctxt, curState);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021895 if (ret == -1)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021896 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021897 if ((ret != 0) && (ctxt->value != NULL)) {
21898 xmlSchemaFreeValue(ctxt->value);
21899 ctxt->value = NULL;
21900 }
21901 /* No break on purpose. */
21902 case XML_SCHEMAS_ATTR_CHECKED:
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021903 if (ctxt->xpathStates != NULL) {
21904 /*
21905 * Evaluate IDCs.
21906 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021907 if (ctxt->value != NULL) {
21908 ctxt->attrInfo->value = ctxt->value;
21909 ctxt->value = NULL;
21910 }
21911 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
21912 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021913 }
21914 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021915 default:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021916 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021917 }
21918 curState = curState->next;
21919 }
21920
21921 /*
21922 * Report missing and illegal attributes.
21923 */
21924 curState = ctxt->attr;
21925 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000021926 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
21927 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021928 if (curState->decl != NULL) {
21929 if (curState->decl->ref != NULL)
21930 attrDecl = curState->decl->refDecl;
21931 else
21932 attrDecl = curState->decl;
21933 } else
21934 attrDecl = NULL;
21935 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
21936 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
21937 } else if (curState->state ==
21938 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
21939 xmlSchemaVCustomErr(ctxt,
21940 XML_SCHEMAV_CVC_ATTRIBUTE_2,
21941 (xmlNodePtr) attr,
21942 (xmlSchemaTypePtr) attrDecl,
21943 "The type definition is absent",
21944 NULL);
21945 } else if (curState->state ==
21946 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
21947 xmlSchemaVCustomErr(ctxt,
21948 XML_SCHEMAV_CVC_AU,
21949 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
21950 "The value does not match the fixed value "
21951 "constraint", NULL);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021952 } else if (curState->state == XML_SCHEMAS_ATTR_WILD_NO_DECL) {
21953 xmlSchemaVWildcardErr(ctxt,
21954 XML_SCHEMAV_CVC_WILDCARD,
21955 (xmlNodePtr) attr,
21956 type->attributeWildcard,
21957 "No global attribute declaration found, but "
21958 "stipulated by the strict processContents of "
21959 "the wildcard");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021960 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021961 /* TODO: "prohibited" won't ever be touched here!.
21962 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
21963 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021964 /*
21965 * TODO: One might report different error messages
21966 * for the following errors.
21967 */
21968 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021969 xmlSchemaVIllegalAttrErr(ctxt,
21970 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
21971 } else {
21972 xmlSchemaVIllegalAttrErr(ctxt,
21973 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
21974 }
21975 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000021976 }
21977 curState = curState->next;
21978 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021979 }
21980
21981 /*
21982 * Add missing default/fixed attributes.
21983 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000021984 if (defAttrStates != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021985 curState = defAttrStates;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000021986
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021987 while (curState != NULL) {
21988 attrDecl = curState->decl;
21989 if (attrDecl->ref != NULL)
21990 attrDecl = attrDecl->refDecl;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000021991 /*
21992 * Evaluate IDCs on default attributes.
21993 */
21994 if (ctxt->xpathStates != NULL) {
21995 /*
21996 * Create an attribute info if needed.
21997 */
21998 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021999 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
22000 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022001 if (ctxt->attrInfo == NULL) {
22002 xmlSchemaVErrMemory(ctxt,
22003 "allocating an attribute info", NULL);
22004 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022005 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022006 ctxt->attrInfo->value = NULL;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022007 }
22008 /*
22009 * Init the attribute info.
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000022010 * TODO: Hmm, maby a bit oversized this all.
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022011 */
22012 ctxt->attrInfo->flags = 0;
22013 ctxt->attrInfo->decl = (xmlSchemaTypePtr) attrDecl;
22014 ctxt->attrInfo->node = NULL;
22015 ctxt->attrInfo->typeDef = attrDecl->subtypes;
22016 ctxt->attrInfo->namespaceName = attrDecl->targetNamespace;
22017 ctxt->attrInfo->localName = attrDecl->name;
22018
22019 ctxt->nodeInfo = ctxt->attrInfo;
22020
22021 ret = xmlSchemaXPathEvaluate(ctxt,
22022 XML_ATTRIBUTE_NODE);
22023 if (ret == -1)
22024 goto fatal_exit;
22025 if (ctxt->attrInfo->value != NULL) {
22026 xmlSchemaFreeValue(ctxt->attrInfo->value);
22027 ctxt->attrInfo->value = NULL;
22028 }
22029 if (ret > 0) {
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000022030 /*
22031 * IDCs will consume the precomputed default value,
22032 * so we need to clone it somehow.
22033 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022034 /*
22035 * string or anySimpleType does not create a precomputed value
22036 * by default, so it will be created here on demand.
22037 * TODO: default/fixed attributes are a bit unoptimized:
22038 * the string value will be hold by ->defValue and inside
22039 * the precomputed value.
22040 */
22041 if (attrDecl->defVal == NULL) {
22042 xmlChar *str = xmlStrdup(attrDecl->defValue);
22043
22044 if (xmlSchemaPostCreateVal(ctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022045 ctxt->attrInfo->typeDef,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022046 str,
22047 &(attrDecl->defVal)) == -1) {
22048 FREE_AND_NULL(str)
22049 goto fatal_exit;
22050 }
22051 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022052 ctxt->attrInfo->value = xmlSchemaCopyValue(attrDecl->defVal);
22053 /* TODO: error on NULL return. */
22054 }
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000022055
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022056 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
22057 goto fatal_exit;
22058 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022059
22060 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
22061 /*
22062 * PSVI: Add a new attribute node to the current element.
22063 */
22064 if (attrDecl->targetNamespace == NULL) {
22065 xmlNewProp(elem, attrDecl->name, curState->value);
22066 } else {
22067 xmlNsPtr ns;
22068
22069 ns = xmlSearchNsByHref(elem->doc, elem,
22070 attrDecl->targetNamespace);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022071 if (ns == NULL) {
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000022072 xmlChar prefix[12];
22073 int counter = 1;
22074
22075 attr = curState->attr;
22076 /*
22077 * Create a namespace declaration on the validation
22078 * root node if no namespace declaration is in scope.
22079 */
22080 snprintf((char *) prefix, sizeof(prefix), "p");
22081 /*
22082 * This is somehow not performant, since the ancestor
22083 * axis beyond @elem will be searched as well.
22084 */
22085 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
22086 while (ns != NULL) {
22087 if (counter > 1000) {
22088 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
22089 XML_SCHEMAV_INTERNAL,
22090 "Internal error: xmlSchemaValidateAttributes, "
22091 "could not compute a ns prefix for "
22092 "default/fixed attribute '%s'.\n",
22093 attrDecl->name, NULL);
22094
22095 break;
22096 }
22097 snprintf((char *) prefix,
22098 sizeof(prefix), "p%d", counter++);
22099 ns = xmlSearchNs(elem->doc, elem,
22100 BAD_CAST prefix);
22101 }
22102 if (ns == NULL) {
22103 ns = xmlNewNs(ctxt->validationRoot,
22104 attrDecl->targetNamespace, BAD_CAST prefix);
22105 xmlNewNsProp(elem, ns, attrDecl->name,
22106 curState->value);
22107 }
22108 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022109 xmlNewNsProp(elem, ns, attrDecl->name,
22110 curState->value);
22111 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022112 }
22113 }
22114 curState = curState->next;
22115 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000022116 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022117 ret = ctxt->err;
22118 goto exit;
22119
22120fatal_exit:
22121 ret = -1;
22122
22123exit:
22124
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022125 if (defAttrStates != NULL)
22126 xmlSchemaFreeAttributeStates(defAttrStates);
22127
Daniel Veillard3646d642004-06-02 19:19:14 +000022128#ifdef DEBUG_ATTR_VALIDATION
22129 if (redundant)
22130 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022131 "xmlSchemaValidateAttributes: redundant call by "
22132 "type: %s\n", type->name);
Daniel Veillard3646d642004-06-02 19:19:14 +000022133#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022134 ctxt->nodeInfo = ctxt->elemInfos[ctxt->depth];
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022135 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022136 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000022137}
22138
22139/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022140 * xmlSchemaStartValidation:
Daniel Veillard4255d502002-04-16 15:50:10 +000022141 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000022142 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022143 * The starting point of the validation, called by
22144 * xmlSchemaValidateDocument and xmlSchemaValidateOneElement.
Daniel Veillard4255d502002-04-16 15:50:10 +000022145 *
22146 * Returns 0 if the element is schemas valid, a positive error code
22147 * number otherwise and -1 in case of internal or API error.
22148 */
22149static int
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022150xmlSchemaStartValidation(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022151{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022152 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022153 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022154
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022155 ctxt->err = 0;
22156 ctxt->nberrors = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022157 if (ctxt->schema == NULL) {
22158 /*
22159 * No schema was specified at time of creation of the validation
22160 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
22161 * of the instance to build a schema.
22162 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022163 if (ctxt->pctxt == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022164 if (xmlSchemaCreatePCtxtOnVCtxt(ctxt) == -1)
22165 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022166 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
22167 if (ctxt->schema == NULL)
22168 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022169 ctxt->xsiAssemble = 1;
22170 } else
22171 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022172 /*
22173 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000022174 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022175 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022176 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
22177 if (ret == -1) {
22178 xmlSchemaVCustomErr(ctxt,
22179 XML_SCHEMAV_INTERNAL,
22180 ctxt->node, NULL,
22181 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022182 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022183 }
22184 /*
22185 * NOTE: We won't react on schema parser errors here.
22186 * TODO: But a warning would be nice.
22187 */
22188 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022189 if (ret != -1) {
22190 if (ctxt->node->ns != NULL)
22191 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
22192 ctxt->node->ns->href);
22193 else
22194 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
22195
22196 if (elemDecl == NULL) {
22197 xmlSchemaVCustomErr(ctxt,
22198 XML_SCHEMAV_CVC_ELT_1,
22199 ctxt->node, NULL,
22200 "No matching global declaration available", NULL);
22201 ret = XML_SCHEMAV_CVC_ELT_1;
22202 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022203 /*
22204 * Augment the IDC definitions.
22205 */
22206 if (ctxt->schema->idcDef != NULL) {
22207 xmlHashScan(ctxt->schema->idcDef,
22208 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
22209 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022210 ctxt->depth = -1;
22211 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022212 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022213 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022214 if (ret < 0) {
22215 xmlSchemaVCustomErr(ctxt,
22216 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
22217 "Internal error: xmlSchemaValidateElement, "
22218 "calling validation by declaration", NULL);
22219 }
22220 }
22221 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022222
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022223 if (ctxt->xsiAssemble) {
22224 if (ctxt->schema != NULL) {
22225 xmlSchemaFree(ctxt->schema);
22226 ctxt->schema = NULL;
22227 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022228 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022229 xmlSchemaClearValidCtxt(ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022230 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000022231}
22232
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022233
Daniel Veillard4255d502002-04-16 15:50:10 +000022234/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022235 * xmlSchemaValidateOneElement:
22236 * @ctxt: a schema validation context
22237 * @elem: an element node
22238 *
22239 * Validate a branch of a tree, starting with the given @elem.
22240 *
22241 * Returns 0 if the element and its subtree is valid, a positive error
22242 * code number otherwise and -1 in case of an internal or API error.
22243 */
22244int
22245xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
22246{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022247 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022248 return (-1);
22249
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022250 if (ctxt->schema == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022251 xmlSchemaVErr(ctxt, NULL,
22252 XML_SCHEMAV_INTERNAL,
22253 "API error: xmlSchemaValidateOneElement, "
22254 "no schema specified.\n", NULL, NULL);
22255 return (-1);
22256 }
22257
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022258 ctxt->doc = elem->doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022259 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022260 ctxt->validationRoot = elem;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022261 return (xmlSchemaStartValidation(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000022262}
22263
22264/************************************************************************
22265 * *
22266 * SAX Validation code *
22267 * *
22268 ************************************************************************/
22269
22270/************************************************************************
22271 * *
22272 * Validation interfaces *
22273 * *
22274 ************************************************************************/
22275
22276/**
22277 * xmlSchemaNewValidCtxt:
22278 * @schema: a precompiled XML Schemas
22279 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022280 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000022281 *
22282 * Returns the validation context or NULL in case of error
22283 */
22284xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022285xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
22286{
Daniel Veillard4255d502002-04-16 15:50:10 +000022287 xmlSchemaValidCtxtPtr ret;
22288
22289 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
22290 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022291 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000022292 return (NULL);
22293 }
22294 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000022295 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000022296 return (ret);
22297}
22298
22299/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022300 * xmlSchemaClearValidCtxt:
22301 * @ctxt: the schema validation context
22302 *
22303 * Free the resources associated to the schema validation context;
22304 * leaves some fields alive intended for reuse of the context.
22305 */
22306static void
22307xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
22308{
22309 if (vctxt == NULL)
22310 return;
22311
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022312 vctxt->flags = 0;
22313
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022314 vctxt->validationRoot = NULL;
22315 if (vctxt->attr != NULL) {
22316 xmlSchemaFreeAttributeStates(vctxt->attr);
22317 vctxt->attr = NULL;
22318 }
22319 if (vctxt->value != NULL) {
22320 xmlSchemaFreeValue(vctxt->value);
22321 vctxt->value = NULL;
22322 }
22323 /*
22324 * Augmented IDC information.
22325 */
22326 if (vctxt->aidcs != NULL) {
22327 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
22328 do {
22329 next = cur->next;
22330 xmlFree(cur);
22331 cur = next;
22332 } while (cur != NULL);
22333 vctxt->aidcs = NULL;
22334 }
22335 if (vctxt->idcNodes != NULL) {
22336 int i;
22337 xmlSchemaPSVIIDCNodePtr item;
22338
22339 for (i = 0; i < vctxt->nbIdcNodes; i++) {
22340 item = vctxt->idcNodes[i];
22341 xmlFree(item->keys);
22342 xmlFree(item);
22343 }
22344 xmlFree(vctxt->idcNodes);
22345 vctxt->idcNodes = NULL;
22346 }
22347 /*
22348 * Note that we won't delete the XPath state pool here.
22349 */
22350 if (vctxt->xpathStates != NULL) {
22351 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
22352 vctxt->xpathStates = NULL;
22353 }
22354 if (vctxt->attrInfo != NULL) {
22355 if (vctxt->attrInfo->value != NULL) {
22356 xmlSchemaFreeValue(vctxt->attrInfo->value);
22357 }
22358 memset(vctxt->attrInfo, 0, sizeof(xmlSchemaNodeInfo));
22359 }
22360 if (vctxt->elemInfos != NULL) {
22361 int i;
22362 xmlSchemaNodeInfoPtr info;
22363
22364 for (i = 0; i < vctxt->sizeElemInfos; i++) {
22365 info = vctxt->elemInfos[i];
22366 if (info == NULL)
22367 break;
22368 if (info->value != NULL) {
22369 xmlSchemaFreeValue(info->value);
22370 info->value = NULL;
22371 }
22372 if (info->idcMatchers != NULL) {
22373 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
22374 info->idcMatchers = NULL;
22375 }
22376 if (info->idcTable != NULL) {
22377 xmlSchemaIDCFreeIDCTable(info->idcTable);
22378 info->idcTable = NULL;
22379 }
22380 }
22381 }
22382}
22383
22384/**
Daniel Veillard4255d502002-04-16 15:50:10 +000022385 * xmlSchemaFreeValidCtxt:
22386 * @ctxt: the schema validation context
22387 *
22388 * Free the resources associated to the schema validation context
22389 */
22390void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022391xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
22392{
Daniel Veillard4255d502002-04-16 15:50:10 +000022393 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022394 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000022395 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000022396 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000022397 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022398 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022399 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022400 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022401 if (ctxt->idcNodes != NULL) {
22402 int i;
22403 xmlSchemaPSVIIDCNodePtr item;
22404
22405 for (i = 0; i < ctxt->nbIdcNodes; i++) {
22406 item = ctxt->idcNodes[i];
22407 xmlFree(item->keys);
22408 xmlFree(item);
22409 }
22410 xmlFree(ctxt->idcNodes);
22411 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022412 if (ctxt->idcKeys != NULL) {
22413 int i;
22414 for (i = 0; i < ctxt->nbIdcKeys; i++)
22415 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
22416 xmlFree(ctxt->idcKeys);
22417 }
22418
22419 if (ctxt->xpathStates != NULL)
22420 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
22421 if (ctxt->xpathStatePool != NULL)
22422 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
22423
22424 /*
22425 * Augmented IDC information.
22426 */
22427 if (ctxt->aidcs != NULL) {
22428 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
22429 do {
22430 next = cur->next;
22431 xmlFree(cur);
22432 cur = next;
22433 } while (cur != NULL);
22434 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022435 if (ctxt->attrInfo != NULL) {
22436 if (ctxt->attrInfo->value != NULL)
22437 xmlSchemaFreeValue(ctxt->attrInfo->value);
22438 xmlFree(ctxt->attrInfo);
22439 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022440 if (ctxt->elemInfos != NULL) {
22441 int i;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022442 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022443
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022444 for (i = 0; i < ctxt->sizeElemInfos; i++) {
22445 info = ctxt->elemInfos[i];
22446 if (info == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022447 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022448 if (info->value != NULL)
22449 xmlSchemaFreeValue(info->value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022450 if (info->idcMatchers != NULL)
22451 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022452 if (info->idcTable != NULL)
22453 xmlSchemaIDCFreeIDCTable(info->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022454 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022455 * TODO: Don't know if those will have to be freed if in streaming
22456 * mode.
22457 *
22458 * xmlFree(info->localName);
22459 * if (info->namespaceName != NULL)
22460 * xmlFree(info->namespaceName);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022461 */
22462 xmlFree(info);
22463 }
22464 xmlFree(ctxt->elemInfos);
22465 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022466 xmlFree(ctxt);
22467}
22468
22469/**
22470 * xmlSchemaSetValidErrors:
22471 * @ctxt: a schema validation context
22472 * @err: the error function
22473 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000022474 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000022475 *
William M. Brack2f2a6632004-08-20 23:09:47 +000022476 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000022477 */
22478void
22479xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022480 xmlSchemaValidityErrorFunc err,
22481 xmlSchemaValidityWarningFunc warn, void *ctx)
22482{
Daniel Veillard4255d502002-04-16 15:50:10 +000022483 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022484 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000022485 ctxt->error = err;
22486 ctxt->warning = warn;
22487 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022488 if (ctxt->pctxt != NULL)
22489 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000022490}
22491
22492/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000022493 * xmlSchemaGetValidErrors:
22494 * @ctxt: a XML-Schema validation context
22495 * @err: the error function result
22496 * @warn: the warning function result
22497 * @ctx: the functions context result
22498 *
22499 * Get the error and warning callback informations
22500 *
22501 * Returns -1 in case of error and 0 otherwise
22502 */
22503int
22504xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
22505 xmlSchemaValidityErrorFunc * err,
22506 xmlSchemaValidityWarningFunc * warn, void **ctx)
22507{
22508 if (ctxt == NULL)
22509 return (-1);
22510 if (err != NULL)
22511 *err = ctxt->error;
22512 if (warn != NULL)
22513 *warn = ctxt->warning;
22514 if (ctx != NULL)
22515 *ctx = ctxt->userData;
22516 return (0);
22517}
22518
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022519
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022520/**
Daniel Veillard6927b102004-10-27 17:29:04 +000022521 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022522 * @ctxt: a schema validation context
22523 * @options: a combination of xmlSchemaValidOption
22524 *
22525 * Sets the options to be used during the validation.
22526 *
22527 * Returns 0 in case of success, -1 in case of an
22528 * API error.
22529 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022530int
22531xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
22532 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022533
22534{
22535 int i;
22536
22537 if (ctxt == NULL)
22538 return (-1);
22539 /*
22540 * WARNING: Change the start value if adding to the
22541 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022542 * TODO: Is there an other, more easy to maintain,
22543 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022544 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022545 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022546 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022547 xmlSchemaVErr(ctxt, NULL,
22548 XML_SCHEMAV_INTERNAL,
22549 "Internal error: xmlSchemaSetValidOptions, "
22550 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022551 return (-1);
22552 }
22553 }
22554 ctxt->options = options;
22555 return (0);
22556}
22557
22558/**
Daniel Veillard6927b102004-10-27 17:29:04 +000022559 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022560 * @ctxt: a schema validation context
22561 *
William M. Brack21e4ef22005-01-02 09:53:13 +000022562 * Get the validation context options.
22563 *
22564 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022565 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022566int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022567xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
22568
22569{
22570 if (ctxt == NULL)
22571 return (-1);
22572 else
22573 return (ctxt->options);
22574}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022575
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022576
Daniel Veillard259f0df2004-08-18 09:13:18 +000022577/**
Daniel Veillard4255d502002-04-16 15:50:10 +000022578 * xmlSchemaValidateDoc:
22579 * @ctxt: a schema validation context
22580 * @doc: a parsed document tree
22581 *
22582 * Validate a document tree in memory.
22583 *
22584 * Returns 0 if the document is schemas valid, a positive error code
22585 * number otherwise and -1 in case of internal or API error.
22586 */
22587int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022588xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
22589{
Daniel Veillard4255d502002-04-16 15:50:10 +000022590 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022591 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022592
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022593 ctxt->doc = doc;
22594 ctxt->node = xmlDocGetRootElement(doc);
22595 if (ctxt->node == NULL) {
22596 xmlSchemaVCustomErr(ctxt,
22597 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
22598 (xmlNodePtr) doc, NULL,
22599 "The document has no document element", NULL);
22600 return (ctxt->err);
22601 }
22602 ctxt->validationRoot = ctxt->node;
22603 xmlSchemaStartValidation(ctxt);
22604
22605 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000022606}
22607
22608/**
22609 * xmlSchemaValidateStream:
22610 * @ctxt: a schema validation context
22611 * @input: the input to use for reading the data
22612 * @enc: an optional encoding information
22613 * @sax: a SAX handler for the resulting events
22614 * @user_data: the context to provide to the SAX handler.
22615 *
22616 * Validate a document tree in memory.
22617 *
22618 * Returns 0 if the document is schemas valid, a positive error code
22619 * number otherwise and -1 in case of internal or API error.
22620 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022621int
Daniel Veillard4255d502002-04-16 15:50:10 +000022622xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022623 xmlParserInputBufferPtr input, xmlCharEncoding enc,
22624 xmlSAXHandlerPtr sax, void *user_data)
22625{
Daniel Veillard4255d502002-04-16 15:50:10 +000022626 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022627 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022628 ctxt->input = input;
22629 ctxt->enc = enc;
22630 ctxt->sax = sax;
22631 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022632 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022633}
22634
Daniel Veillard5d4644e2005-04-01 13:11:58 +000022635#define bottom_xmlschemas
22636#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000022637#endif /* LIBXML_SCHEMAS_ENABLED */