blob: 34bd48d818d05a02130c6b270ce8ae34642a9420 [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
141#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
142
143#define IS_MODEL_GROUP(item) \
144 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
145 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
146 (item->type == XML_SCHEMA_TYPE_ALL))
147
148#if 0
149#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
150#endif
151
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +0000152/*
Daniel Veillardc0826a72004-08-10 14:17:33 +0000153#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
154#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
155#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +0000156*/
Daniel Veillardc0826a72004-08-10 14:17:33 +0000157
Daniel Veillard4255d502002-04-16 15:50:10 +0000158#define XML_SCHEMAS_PARSE_ERROR 1
159
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000160#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
161
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000162
163/*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000164* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
165* locate schemata to be imported
166* using the namespace name; otherwise
167* the location URI will be used */
168
169/*
170* xmlSchemaParserOption:
171*
172* This is the set of XML Schema parser options.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000173*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000174typedef enum {
175 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000176 * locate schemata to be imported
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000177 * using the namespace name; otherwise
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000178 * the location URI will be used *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000179} xmlSchemaParserOption;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000180*/
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000181
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000182typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000183typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000184
185typedef struct _xmlSchemaItemList xmlSchemaItemList;
186typedef xmlSchemaItemList *xmlSchemaItemListPtr;
187
188struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000189 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000190 int nbItems; /* used for dynamic addition of schemata */
191 int sizeItems; /* used for dynamic addition of schemata */
192};
193
Daniel Veillard4255d502002-04-16 15:50:10 +0000194struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000195 void *userData; /* user specific data block */
196 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
197 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000198 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000199 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000200 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000201
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000202 xmlSchemaPtr topschema; /* The main schema */
203 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
204
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000205 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000206 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000207 int counter;
208
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000209 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000210 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000211 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000212
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000213 const char *buffer;
214 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000215
Daniel Veillard4255d502002-04-16 15:50:10 +0000216 /*
217 * Used to build complex element content models
218 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000219 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000220 xmlAutomataStatePtr start;
221 xmlAutomataStatePtr end;
222 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000223
224 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000225 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000226 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
227 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000228 xmlSchemaAssemblePtr assemble;
229 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000230 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000231 const xmlChar **localImports; /* list of locally imported namespaces */
232 int sizeLocalImports;
233 int nbLocalImports;
Daniel Veillard4255d502002-04-16 15:50:10 +0000234};
235
236
237#define XML_SCHEMAS_ATTR_UNKNOWN 1
238#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000239#define XML_SCHEMAS_ATTR_PROHIBITED 3
240#define XML_SCHEMAS_ATTR_MISSING 4
241#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
242#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000243#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
244#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000245#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
246#define XML_SCHEMAS_ATTR_WILD_NO_DECL 10
Daniel Veillard4255d502002-04-16 15:50:10 +0000247
248typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
249typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
250struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000251 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000252 xmlAttrPtr attr;
253 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000254 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000255 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000256};
257
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000258/**
259 * xmlSchemaBasicItem:
260 *
261 * The abstract base type for schema components.
262 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000263typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
264typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
265struct _xmlSchemaBasicItem {
266 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000267};
268
269/**
270 * xmlSchemaAnnotItem:
271 *
272 * The abstract base type for annotated schema components.
273 * (Extends xmlSchemaBasicItem)
274 */
275typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
276typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
277struct _xmlSchemaAnnotItem {
278 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000279 xmlSchemaAnnotPtr annot;
280};
281
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000282/**
283 * xmlSchemaTreeItem:
284 *
285 * The abstract base type for tree-like structured schema components.
286 * (Extends xmlSchemaAnnotItem)
287 */
288typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
289typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
290struct _xmlSchemaTreeItem {
291 xmlSchemaTypeType type;
292 xmlSchemaAnnotPtr annot;
293 xmlSchemaTreeItemPtr next;
294 xmlSchemaTreeItemPtr children;
295};
296
297/**
298 * xmlSchemaQNameRef:
299 *
300 * A component reference item (not a schema component)
301 * (Extends xmlSchemaBasicItem)
302 */
303typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
304typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
305struct _xmlSchemaQNameRef {
306 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000307 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000308 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000309 const xmlChar *name;
310 const xmlChar *targetNamespace;
311};
312
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000313/**
314 * xmlSchemaParticle:
315 *
316 * A particle component.
317 * (Extends xmlSchemaTreeItem)
318 */
319typedef struct _xmlSchemaParticle xmlSchemaParticle;
320typedef xmlSchemaParticle *xmlSchemaParticlePtr;
321struct _xmlSchemaParticle {
322 xmlSchemaTypeType type;
323 xmlSchemaAnnotPtr annot;
324 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
325 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
326 int minOccurs;
327 int maxOccurs;
328 xmlNodePtr node;
329};
330
331/**
332 * xmlSchemaModelGroup:
333 *
334 * A model group component.
335 * (Extends xmlSchemaTreeItem)
336 */
337typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
338typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
339struct _xmlSchemaModelGroup {
340 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
341 xmlSchemaAnnotPtr annot;
342 xmlSchemaTreeItemPtr next; /* not used */
343 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
344 xmlNodePtr node;
345};
346
347/**
348 * xmlSchemaModelGroupDef:
349 *
350 * A model group definition component.
351 * (Extends xmlSchemaTreeItem)
352 */
353typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
354typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
355struct _xmlSchemaModelGroupDef {
356 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
357 xmlSchemaAnnotPtr annot;
358 xmlSchemaTreeItemPtr next; /* not used */
359 xmlSchemaTreeItemPtr children; /* the "model group" */
360 const xmlChar *name;
361 const xmlChar *targetNamespace;
362 xmlNodePtr node;
363};
364
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000365typedef struct _xmlSchemaIDC xmlSchemaIDC;
366typedef xmlSchemaIDC *xmlSchemaIDCPtr;
367
368/**
369 * xmlSchemaIDCSelect:
370 *
371 * The identity-constraint "field" and "selector" item, holding the
372 * XPath expression.
373 */
374typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
375typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
376struct _xmlSchemaIDCSelect {
377 xmlSchemaIDCSelectPtr next;
378 xmlSchemaIDCPtr idc;
379 int index; /* an index position if significant for IDC key-sequences */
380 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000381 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000382};
383
384/**
385 * xmlSchemaIDC:
386 *
387 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000388 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000389 */
390
391struct _xmlSchemaIDC {
392 xmlSchemaTypeType type;
393 xmlSchemaAnnotPtr annot;
394 xmlSchemaIDCPtr next;
395 xmlNodePtr node;
396 const xmlChar *name;
397 const xmlChar *targetNamespace;
398 xmlSchemaIDCSelectPtr selector;
399 xmlSchemaIDCSelectPtr fields;
400 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000401 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000402};
403
404/**
405 * xmlSchemaIDCAug:
406 *
407 * The augmented IDC information used for validation.
408 */
409typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
410typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
411struct _xmlSchemaIDCAug {
412 xmlSchemaIDCAugPtr next; /* next in a list */
413 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000414 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000415 tables need to be bubbled upwards */
416};
417
418/**
419 * xmlSchemaPSVIIDCKeySequence:
420 *
421 * The key sequence of a node table item.
422 */
423typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
424typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
425struct _xmlSchemaPSVIIDCKey {
426 xmlSchemaTypePtr type;
427 xmlSchemaValPtr compValue;
428};
429
430/**
431 * xmlSchemaPSVIIDCNode:
432 *
433 * The node table item of a node table.
434 */
435typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
436typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
437struct _xmlSchemaPSVIIDCNode {
438 xmlNodePtr node;
439 xmlSchemaPSVIIDCKeyPtr *keys;
440};
441
442/**
443 * xmlSchemaPSVIIDCBinding:
444 *
445 * The identity-constraint binding item of the [identity-constraint table].
446 */
447typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
448typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
449struct _xmlSchemaPSVIIDCBinding {
450 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
451 xmlSchemaIDCPtr definition; /* the IDC definition */
452 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
453 int nbNodes; /* number of entries in the node table */
454 int sizeNodes; /* size of the node table */
455 int nbDupls; /* number of already identified duplicates in the node
456 table */
457 /* int nbKeys; number of keys in each key-sequence */
458};
459
460#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
461#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
462
463#define XPATH_STATE_OBJ_MATCHES -2
464#define XPATH_STATE_OBJ_BLOCKED -3
465
466typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
467typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
468
469/**
470 * xmlSchemaIDCStateObj:
471 *
472 * The state object used to evaluate XPath expressions.
473 */
474typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
475typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
476struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000477 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000478 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000479 int depth; /* depth of creation */
480 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000481 int nbHistory;
482 int sizeHistory;
483 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
484 matcher */
485 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000486 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000487};
488
489#define IDC_MATCHER 0
490
491/**
492 * xmlSchemaIDCMatcher:
493 *
494 * Used to IDC selectors (and fields) successively.
495 */
496struct _xmlSchemaIDCMatcher {
497 int type;
498 int depth; /* the tree depth at creation time */
499 xmlSchemaIDCMatcherPtr next; /* next in the list */
500 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
501 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
502 elements */
503 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000504 int targetDepth;
505};
506
507/*
508* Element info flags.
509*/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000510#define XML_SCHEMA_ELEM_INFO_VALUE_NEEDED 1
511/* #define XML_SCHEMA_ELEM_INFO_ATTR 2 */
512/* #define XML_SCHEMA_ELEM_INFO_ELEM 4 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000513
514/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000515 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000516 *
517 * Holds information of an element node.
518 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000519typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
520typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
521struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000522 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000523 int flags; /* combination of node info flags */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000524 xmlNodePtr node;
525 const xmlChar *localName;
526 const xmlChar *namespaceName;
527 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +0000528 xmlSchemaTypePtr decl; /* the element/attribute declaration */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000529 xmlSchemaValPtr value; /* the pre-computed value if any */
530 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
531 for the scope element*/
532 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
533 element */
534};
535
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000536#define XML_SCHEMA_VALID_INVALID_NEG_WILDCARD 1<<0
537
Daniel Veillard4255d502002-04-16 15:50:10 +0000538/**
539 * xmlSchemaValidCtxt:
540 *
541 * A Schemas validation context
542 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000543struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000544 void *userData; /* user specific data block */
545 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000546 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000547 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000548
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000549 xmlSchemaPtr schema; /* The schema in use */
550 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000551 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000552 xmlCharEncoding enc;
553 xmlSAXHandlerPtr sax;
554 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000555
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000556 xmlDocPtr myDoc;
557 int err;
558 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000559
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000560 xmlNodePtr node;
561 xmlNodePtr cur;
562 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000563
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000564 xmlRegExecCtxtPtr regexp;
565 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000566
Daniel Veillard3646d642004-06-02 19:19:14 +0000567 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000568 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000569 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000570 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000571 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000572 xmlNodePtr validationRoot;
573 xmlSchemaParserCtxtPtr pctxt;
574 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000575
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000576 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000577 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000578 int sizeElemInfos;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000579 xmlSchemaNodeInfoPtr nodeInfo; /* the current element information */
580 xmlSchemaNodeInfoPtr attrInfo; /* node infor for the current attribute */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000581
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000582 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
583
584 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
585 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
586
587 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
588 int nbIdcNodes;
589 int sizeIdcNodes;
590
591 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
592 int nbIdcKeys;
593 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000594
595 int flags;
Daniel Veillard4255d502002-04-16 15:50:10 +0000596};
597
Daniel Veillard1d913862003-11-21 00:28:39 +0000598/*
599 * These are the entries in the schemas importSchemas hash table
600 */
601typedef struct _xmlSchemaImport xmlSchemaImport;
602typedef xmlSchemaImport *xmlSchemaImportPtr;
603struct _xmlSchemaImport {
604 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000605 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000606 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000607 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000608};
Daniel Veillard4255d502002-04-16 15:50:10 +0000609
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000610/*
611 * These are the entries associated to includes in a schemas
612 */
613typedef struct _xmlSchemaInclude xmlSchemaInclude;
614typedef xmlSchemaInclude *xmlSchemaIncludePtr;
615struct _xmlSchemaInclude {
616 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000617 const xmlChar *schemaLocation;
618 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000619 const xmlChar *origTargetNamespace;
620 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000621};
622
Daniel Veillard4255d502002-04-16 15:50:10 +0000623/************************************************************************
624 * *
625 * Some predeclarations *
626 * *
627 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000628
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000629static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
630 xmlSchemaPtr schema,
631 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000632static void
633xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
634 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000635static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000636xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
637static int
638xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000639 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000640 const xmlChar *value,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000641 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000642 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000643 int normalize,
644 int checkNodes);
645static int
646xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
647 xmlSchemaElementPtr elemDecl);
648static int
649xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000650 xmlSchemaWildcardPtr wild);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000651static int
652xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000653static int
654xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
655 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000656static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000657xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
658 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000659static void
660xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000661static int
662xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
663 xmlSchemaTypePtr type,
664 const xmlChar *value,
665 xmlSchemaValPtr *val);
666static xmlSchemaTypePtr
667xmlSchemaGetSimpleContentType(xmlSchemaTypePtr complexType);
668static int
669xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000670static xmlSchemaTreeItemPtr
671xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
672 xmlNodePtr node, xmlSchemaTypeType type,
673 int withParticle);
674static const xmlChar *
675xmlSchemaCompTypeToString(xmlSchemaTypeType type);
676static xmlSchemaTypeLinkPtr
677xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
William M. Brack87640d52004-04-17 14:58:15 +0000678
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000679/************************************************************************
680 * *
681 * Datatype error handlers *
682 * *
683 ************************************************************************/
684
685/**
686 * xmlSchemaPErrMemory:
687 * @node: a context node
688 * @extra: extra informations
689 *
690 * Handle an out of memory condition
691 */
692static void
693xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
694 const char *extra, xmlNodePtr node)
695{
696 if (ctxt != NULL)
697 ctxt->nberrors++;
698 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
699 extra);
700}
701
702/**
703 * xmlSchemaPErr:
704 * @ctxt: the parsing context
705 * @node: the context node
706 * @error: the error code
707 * @msg: the error message
708 * @str1: extra data
709 * @str2: extra data
710 *
711 * Handle a parser error
712 */
713static void
714xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
715 const char *msg, const xmlChar * str1, const xmlChar * str2)
716{
717 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000718 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000719 void *data = NULL;
720
721 if (ctxt != NULL) {
722 ctxt->nberrors++;
723 channel = ctxt->error;
724 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000725 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000726 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000727 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000728 error, XML_ERR_ERROR, NULL, 0,
729 (const char *) str1, (const char *) str2, NULL, 0, 0,
730 msg, str1, str2);
731}
732
733/**
734 * xmlSchemaPErr2:
735 * @ctxt: the parsing context
736 * @node: the context node
737 * @node: the current child
738 * @error: the error code
739 * @msg: the error message
740 * @str1: extra data
741 * @str2: extra data
742 *
743 * Handle a parser error
744 */
745static void
746xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
747 xmlNodePtr child, int error,
748 const char *msg, const xmlChar * str1, const xmlChar * str2)
749{
750 if (child != NULL)
751 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
752 else
753 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
754}
755
Daniel Veillard01fa6152004-06-29 17:04:39 +0000756
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000757/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000758 * xmlSchemaPErrExt:
759 * @ctxt: the parsing context
760 * @node: the context node
761 * @error: the error code
762 * @strData1: extra data
763 * @strData2: extra data
764 * @strData3: extra data
765 * @msg: the message
766 * @str1: extra parameter for the message display
767 * @str2: extra parameter for the message display
768 * @str3: extra parameter for the message display
769 * @str4: extra parameter for the message display
770 * @str5: extra parameter for the message display
771 *
772 * Handle a parser error
773 */
774static void
775xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
776 const xmlChar * strData1, const xmlChar * strData2,
777 const xmlChar * strData3, const char *msg, const xmlChar * str1,
778 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
779 const xmlChar * str5)
780{
781
782 xmlGenericErrorFunc channel = NULL;
783 xmlStructuredErrorFunc schannel = NULL;
784 void *data = NULL;
785
786 if (ctxt != NULL) {
787 ctxt->nberrors++;
788 channel = ctxt->error;
789 data = ctxt->userData;
790 schannel = ctxt->serror;
791 }
792 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
793 error, XML_ERR_ERROR, NULL, 0,
794 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000795 (const char *) strData3, 0, 0, msg, str1, str2,
796 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000797}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000798
Daniel Veillard3646d642004-06-02 19:19:14 +0000799
800/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000801 * xmlSchemaVTypeErrMemory:
802 * @node: a context node
803 * @extra: extra informations
804 *
805 * Handle an out of memory condition
806 */
807static void
808xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
809 const char *extra, xmlNodePtr node)
810{
811 if (ctxt != NULL) {
812 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000813 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000814 }
815 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
816 extra);
817}
818
819/**
820 * xmlSchemaVErr3:
821 * @ctxt: the validation context
822 * @node: the context node
823 * @error: the error code
824 * @msg: the error message
825 * @str1: extra data
826 * @str2: extra data
827 * @str3: extra data
828 *
829 * Handle a validation error
830 */
831static void
832xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
833 const char *msg, const xmlChar *str1, const xmlChar *str2,
834 const xmlChar *str3)
835{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000836 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000837 xmlGenericErrorFunc channel = NULL;
838 void *data = NULL;
839
840 if (ctxt != NULL) {
841 ctxt->nberrors++;
842 ctxt->err = error;
843 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000844 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000845 data = ctxt->userData;
846 }
847 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000848 /* Removed, since the old schema error codes have been
849 * substituted for the global error codes.
850 *
851 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
852 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000853 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000854 error, XML_ERR_ERROR, NULL, 0,
855 (const char *) str1, (const char *) str2,
856 (const char *) str3, 0, 0,
857 msg, str1, str2, str3);
858}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000859
860/**
861 * xmlSchemaVErrExt:
862 * @ctxt: the validation context
863 * @node: the context node
864 * @error: the error code
865 * @msg: the message
866 * @str1: extra parameter for the message display
867 * @str2: extra parameter for the message display
868 * @str3: extra parameter for the message display
869 * @str4: extra parameter for the message display
870 * @str5: extra parameter for the message display
871 *
872 * Handle a validation error
873 */
874static void
875xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
876 const char *msg, const xmlChar * str1,
877 const xmlChar * str2, const xmlChar * str3,
878 const xmlChar * str4, const xmlChar * str5)
879{
880 xmlStructuredErrorFunc schannel = NULL;
881 xmlGenericErrorFunc channel = NULL;
882 void *data = NULL;
883
884 if (ctxt != NULL) {
885 ctxt->nberrors++;
886 ctxt->err = error;
887 channel = ctxt->error;
888 schannel = ctxt->serror;
889 data = ctxt->userData;
890 }
891 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000892 /* Removed, since the old schema error codes have been
893 * substituted for the global error codes.
894 *
895 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
896 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000897 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
898 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
899 msg, str1, str2, str3, str4, str5);
900}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000901/**
902 * xmlSchemaVErr:
903 * @ctxt: the validation context
904 * @node: the context node
905 * @error: the error code
906 * @msg: the error message
907 * @str1: extra data
908 * @str2: extra data
909 *
910 * Handle a validation error
911 */
912static void
913xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
914 const char *msg, const xmlChar * str1, const xmlChar * str2)
915{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000916 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000917 xmlGenericErrorFunc channel = NULL;
918 void *data = NULL;
919
920 if (ctxt != NULL) {
921 ctxt->nberrors++;
922 ctxt->err = error;
923 channel = ctxt->error;
924 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000925 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000926 }
927 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000928 /* Removed, since the old schema error codes have been
929 * substituted for the global error codes.
930 *
931 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
932 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000933 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000934 error, XML_ERR_ERROR, NULL, 0,
935 (const char *) str1, (const char *) str2, NULL, 0, 0,
936 msg, str1, str2);
937}
Daniel Veillard4255d502002-04-16 15:50:10 +0000938
Daniel Veillardc0826a72004-08-10 14:17:33 +0000939/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000940 * xmlSchemaGetComponentNode:
941 * @item: a schema component
942 *
943 * Returns node associated with the schema component.
944 * NOTE that such a node need not be available; plus, a component's
945 * node need not to reflect the component directly, since there is no
946 * one-to-one relationship between the XML Schema representation and
947 * the component representation.
948 */
949static xmlNodePtr
950xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
951{
952 switch (item->type) {
953 case XML_SCHEMA_TYPE_ELEMENT:
954 return (((xmlSchemaElementPtr) item)->node);
955 case XML_SCHEMA_TYPE_ATTRIBUTE:
956 return (((xmlSchemaAttributePtr) item)->node);
957 case XML_SCHEMA_TYPE_COMPLEX:
958 case XML_SCHEMA_TYPE_SIMPLE:
959 return (((xmlSchemaTypePtr) item)->node);
960 case XML_SCHEMA_TYPE_ANY:
961 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
962 return (((xmlSchemaWildcardPtr) item)->node);
963 case XML_SCHEMA_TYPE_PARTICLE:
964 return (((xmlSchemaParticlePtr) item)->node);
965 case XML_SCHEMA_TYPE_SEQUENCE:
966 case XML_SCHEMA_TYPE_CHOICE:
967 case XML_SCHEMA_TYPE_ALL:
968 return (((xmlSchemaModelGroupPtr) item)->node);
969 case XML_SCHEMA_TYPE_GROUP:
970 return (((xmlSchemaModelGroupDefPtr) item)->node);
971 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
972 return (((xmlSchemaAttributeGroupPtr) item)->node);
973 case XML_SCHEMA_TYPE_IDC_UNIQUE:
974 case XML_SCHEMA_TYPE_IDC_KEY:
975 case XML_SCHEMA_TYPE_IDC_KEYREF:
976 return (((xmlSchemaIDCPtr) item)->node);
977 default:
978 return (NULL);
979 }
980}
981
982#if 0
983/**
984 * xmlSchemaGetNextComponent:
985 * @item: a schema component
986 *
987 * Returns the next sibling of the schema component.
988 */
989static xmlSchemaBasicItemPtr
990xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
991{
992 switch (item->type) {
993 case XML_SCHEMA_TYPE_ELEMENT:
994 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
995 case XML_SCHEMA_TYPE_ATTRIBUTE:
996 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
997 case XML_SCHEMA_TYPE_COMPLEX:
998 case XML_SCHEMA_TYPE_SIMPLE:
999 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1000 case XML_SCHEMA_TYPE_ANY:
1001 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1002 return (NULL);
1003 case XML_SCHEMA_TYPE_PARTICLE:
1004 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1005 case XML_SCHEMA_TYPE_SEQUENCE:
1006 case XML_SCHEMA_TYPE_CHOICE:
1007 case XML_SCHEMA_TYPE_ALL:
1008 return (NULL);
1009 case XML_SCHEMA_TYPE_GROUP:
1010 return (NULL);
1011 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1012 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1013 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1014 case XML_SCHEMA_TYPE_IDC_KEY:
1015 case XML_SCHEMA_TYPE_IDC_KEYREF:
1016 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1017 default:
1018 return (NULL);
1019 }
1020}
1021#endif
1022
1023/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001024 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001025 * @attr: the attribute declaration/use
1026 *
1027 * Returns the name of the attribute; if the attribute
1028 * is a reference, the name of the referenced global type will be returned.
1029 */
1030static const xmlChar *
1031xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
1032{
1033 if (attr->ref != NULL)
1034 return(attr->ref);
1035 else
1036 return(attr->name);
1037}
1038
1039/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001040 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001041 * @type: the type (element or attribute)
1042 *
1043 * Returns the target namespace URI of the type; if the type is a reference,
1044 * the target namespace of the referenced type will be returned.
1045 */
1046static const xmlChar *
1047xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
1048{
1049 if (attr->ref != NULL)
1050 return (attr->refNs);
1051 else
1052 return(attr->targetNamespace);
1053}
1054
1055/**
1056 * xmlSchemaFormatNsUriLocal:
1057 * @buf: the string buffer
1058 * @uri: the namespace URI
1059 * @local: the local name
1060 *
1061 * Returns a representation of the given URI used
1062 * for error reports.
1063 *
1064 * Returns an empty string, if @ns is NULL, a formatted
1065 * string otherwise.
1066 */
1067static const xmlChar*
1068xmlSchemaFormatNsUriLocal(xmlChar **buf,
1069 const xmlChar *uri, const xmlChar *local)
1070{
1071 if (*buf != NULL)
1072 xmlFree(*buf);
1073 if (uri == NULL) {
1074 *buf = xmlStrdup(BAD_CAST "{'");
1075 *buf = xmlStrcat(*buf, local);
1076 } else {
1077 *buf = xmlStrdup(BAD_CAST "{'");
1078 *buf = xmlStrcat(*buf, uri);
1079 *buf = xmlStrcat(*buf, BAD_CAST "', '");
1080 *buf = xmlStrcat(*buf, local);
1081 }
1082 *buf = xmlStrcat(*buf, BAD_CAST "'}");
1083 return ((const xmlChar *) *buf);
1084}
1085
1086/**
1087 * xmlSchemaFormatNsPrefixLocal:
1088 * @buf: the string buffer
1089 * @ns: the namespace
1090 * @local: the local name
1091 *
1092 * Returns a representation of the given URI used
1093 * for error reports.
1094 *
1095 * Returns an empty string, if @ns is NULL, a formatted
1096 * string otherwise.
1097 */
1098static const xmlChar*
1099xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
1100 xmlNsPtr ns, const xmlChar *local)
1101{
1102 if (*buf != NULL) {
1103 xmlFree(*buf);
1104 *buf = NULL;
1105 }
1106 if ((ns == NULL) || (ns->prefix == NULL))
1107 return(local);
1108 else {
1109 *buf = xmlStrdup(ns->prefix);
1110 *buf = xmlStrcat(*buf, BAD_CAST ":");
1111 *buf = xmlStrcat(*buf, local);
1112 }
1113 return ((const xmlChar *) *buf);
1114}
1115
1116/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001117 * xmlSchemaFormatQName:
1118 * @buf: the string buffer
1119 * @namespaceName: the namespace name
1120 * @localName: the local name
1121 *
1122 * Returns the given QName in the format "{namespaceName}localName" or
1123 * just "localName" if @namespaceName is NULL.
1124 *
1125 * Returns the localName if @namespaceName is NULL, a formatted
1126 * string otherwise.
1127 */
1128static const xmlChar*
1129xmlSchemaFormatQName(xmlChar **buf,
1130 const xmlChar *namespaceName,
1131 const xmlChar *localName)
1132{
1133 FREE_AND_NULL(*buf)
1134 if (namespaceName == NULL)
1135 return(localName);
1136
1137 *buf = xmlStrdup(BAD_CAST "{");
1138 *buf = xmlStrcat(*buf, namespaceName);
1139 *buf = xmlStrcat(*buf, BAD_CAST "}");
1140 *buf = xmlStrcat(*buf, localName);
1141
1142 return ((const xmlChar *) *buf);
1143}
1144
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001145static const xmlChar *
1146xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1147{
1148 switch (item->type) {
1149 case XML_SCHEMA_TYPE_ELEMENT:
1150 return (((xmlSchemaElementPtr) item)->name);
1151 case XML_SCHEMA_TYPE_ATTRIBUTE:
1152 return (((xmlSchemaAttributePtr) item)->name);
1153 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1154 return (((xmlSchemaAttributeGroupPtr) item)->name);
1155 case XML_SCHEMA_TYPE_SIMPLE:
1156 case XML_SCHEMA_TYPE_COMPLEX:
1157 return (((xmlSchemaTypePtr) item)->name);
1158 case XML_SCHEMA_TYPE_GROUP:
1159 return (((xmlSchemaModelGroupDefPtr) item)->name);
1160 case XML_SCHEMA_TYPE_IDC_KEY:
1161 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1162 case XML_SCHEMA_TYPE_IDC_KEYREF:
1163 return (((xmlSchemaIDCPtr) item)->name);
1164 default:
1165 /*
1166 * Other components cannot have names.
1167 */
1168 break;
1169 }
1170 return (NULL);
1171}
1172
1173static const xmlChar *
1174xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1175{
1176 switch (item->type) {
1177 case XML_SCHEMA_TYPE_ELEMENT:
1178 return (((xmlSchemaElementPtr) item)->targetNamespace);
1179 case XML_SCHEMA_TYPE_ATTRIBUTE:
1180 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1181 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1182 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1183 case XML_SCHEMA_TYPE_SIMPLE:
1184 case XML_SCHEMA_TYPE_COMPLEX:
1185 return (((xmlSchemaTypePtr) item)->targetNamespace);
1186 case XML_SCHEMA_TYPE_GROUP:
1187 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1188 case XML_SCHEMA_TYPE_IDC_KEY:
1189 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1190 case XML_SCHEMA_TYPE_IDC_KEYREF:
1191 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1192 default:
1193 /*
1194 * Other components cannot have names.
1195 */
1196 break;
1197 }
1198 return (NULL);
1199}
1200
1201static const xmlChar*
1202xmlSchemaGetComponentQName(xmlChar **buf,
1203 void *item)
1204{
1205 return (xmlSchemaFormatQName(buf,
1206 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1207 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1208}
1209
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001210/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001211 * xmlSchemaWildcardPCToString:
1212 * @pc: the type of processContents
1213 *
1214 * Returns a string representation of the type of
1215 * processContents.
1216 */
1217static const xmlChar *
1218xmlSchemaWildcardPCToString(int pc)
1219{
1220 switch (pc) {
1221 case XML_SCHEMAS_ANY_SKIP:
1222 return (BAD_CAST "skip");
1223 case XML_SCHEMAS_ANY_LAX:
1224 return (BAD_CAST "lax");
1225 case XML_SCHEMAS_ANY_STRICT:
1226 return (BAD_CAST "strict");
1227 default:
1228 return (BAD_CAST "invalid process contents");
1229 }
1230}
1231
1232/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001233 * xmlSchemaFormatItemForReport:
1234 * @buf: the string buffer
1235 * @itemDes: the designation of the item
1236 * @itemName: the name of the item
1237 * @item: the item as an object
1238 * @itemNode: the node of the item
1239 * @local: the local name
1240 * @parsing: if the function is used during the parse
1241 *
1242 * Returns a representation of the given item used
1243 * for error reports.
1244 *
1245 * The following order is used to build the resulting
1246 * designation if the arguments are not NULL:
1247 * 1a. If itemDes not NULL -> itemDes
1248 * 1b. If (itemDes not NULL) and (itemName not NULL)
1249 * -> itemDes + itemName
1250 * 2. If the preceding was NULL and (item not NULL) -> item
1251 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1252 *
1253 * If the itemNode is an attribute node, the name of the attribute
1254 * will be appended to the result.
1255 *
1256 * Returns the formatted string and sets @buf to the resulting value.
1257 */
1258static xmlChar*
1259xmlSchemaFormatItemForReport(xmlChar **buf,
1260 const xmlChar *itemDes,
1261 xmlSchemaTypePtr item,
1262 xmlNodePtr itemNode,
1263 int parsing)
1264{
1265 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00001266 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001267
1268 if (*buf != NULL) {
1269 xmlFree(*buf);
1270 *buf = NULL;
1271 }
1272
William M. Brack2f2a6632004-08-20 23:09:47 +00001273 if (itemDes != NULL) {
1274 *buf = xmlStrdup(itemDes);
1275 } else if (item != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001276 switch (item->type) {
1277 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001278 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
1279 *buf = xmlStrdup(BAD_CAST "'anyType'");
1280 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
1281 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
1282 else {
1283 /* *buf = xmlStrdup(BAD_CAST "bi "); */
1284 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
1285 *buf = xmlStrdup(BAD_CAST "'");
1286 *buf = xmlStrcat(*buf, item->name);
1287 *buf = xmlStrcat(*buf, BAD_CAST "'");
1288 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001289 break;
1290 case XML_SCHEMA_TYPE_SIMPLE:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001291 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1292 *buf = xmlStrdup(xmlSchemaElemDesST);
1293 *buf = xmlStrcat(*buf, BAD_CAST " '");
1294 *buf = xmlStrcat(*buf, item->name);
1295 *buf = xmlStrcat(*buf, BAD_CAST "'");
1296 } else {
1297 *buf = xmlStrdup(xmlSchemaElemDesST);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001298 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001299 break;
1300 case XML_SCHEMA_TYPE_COMPLEX:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001301 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1302 *buf = xmlStrdup(xmlSchemaElemDesCT);
1303 *buf = xmlStrcat(*buf, BAD_CAST " '");
1304 *buf = xmlStrcat(*buf, item->name);
1305 *buf = xmlStrcat(*buf, BAD_CAST "'");
1306 } else {
1307 *buf = xmlStrdup(xmlSchemaElemDesCT);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001308 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001309 break;
1310 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1311 xmlSchemaAttributePtr attr;
1312
1313 attr = (xmlSchemaAttributePtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001314 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001315 (attr->ref == NULL)) {
1316 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1317 *buf = xmlStrcat(*buf, BAD_CAST " '");
1318 *buf = xmlStrcat(*buf, attr->name);
1319 *buf = xmlStrcat(*buf, BAD_CAST "'");
1320 } else {
1321 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1322 *buf = xmlStrcat(*buf, BAD_CAST " '");
1323 *buf = xmlStrcat(*buf, attr->refPrefix);
1324 *buf = xmlStrcat(*buf, BAD_CAST ":");
1325 *buf = xmlStrcat(*buf, attr->ref);
1326 *buf = xmlStrcat(*buf, BAD_CAST "'");
1327 }
1328 }
1329 break;
1330 case XML_SCHEMA_TYPE_ELEMENT: {
1331 xmlSchemaElementPtr elem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001332
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001333 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001334 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001335 (elem->ref == NULL)) {
1336 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1337 *buf = xmlStrcat(*buf, BAD_CAST " '");
1338 *buf = xmlStrcat(*buf, elem->name);
1339 *buf = xmlStrcat(*buf, BAD_CAST "'");
1340 } else {
1341 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
1342 *buf = xmlStrcat(*buf, BAD_CAST " '");
1343 *buf = xmlStrcat(*buf, elem->refPrefix);
1344 *buf = xmlStrcat(*buf, BAD_CAST ":");
1345 *buf = xmlStrcat(*buf, elem->ref);
1346 *buf = xmlStrcat(*buf, BAD_CAST "'");
1347 }
1348 }
1349 break;
1350 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1351 case XML_SCHEMA_TYPE_IDC_KEY:
1352 case XML_SCHEMA_TYPE_IDC_KEYREF:
1353 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1354 *buf = xmlStrdup(BAD_CAST "unique '");
1355 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1356 *buf = xmlStrdup(BAD_CAST "key '");
1357 else
1358 *buf = xmlStrdup(BAD_CAST "keyRef '");
1359 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1360 *buf = xmlStrcat(*buf, BAD_CAST "'");
1361 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001362 case XML_SCHEMA_TYPE_ANY:
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001363 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001364 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1365 ((xmlSchemaWildcardPtr) item)->processContents));
1366 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1367 break;
1368 case XML_SCHEMA_FACET_MININCLUSIVE:
1369 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1370 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1371 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1372 case XML_SCHEMA_FACET_TOTALDIGITS:
1373 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1374 case XML_SCHEMA_FACET_PATTERN:
1375 case XML_SCHEMA_FACET_ENUMERATION:
1376 case XML_SCHEMA_FACET_WHITESPACE:
1377 case XML_SCHEMA_FACET_LENGTH:
1378 case XML_SCHEMA_FACET_MAXLENGTH:
1379 case XML_SCHEMA_FACET_MINLENGTH:
1380 *buf = xmlStrdup(BAD_CAST "facet '");
1381 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1382 *buf = xmlStrcat(*buf, BAD_CAST "'");
1383 break;
1384 case XML_SCHEMA_TYPE_NOTATION:
1385 *buf = xmlStrdup(BAD_CAST "notation");
1386 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001387 case XML_SCHEMA_TYPE_GROUP: {
1388 xmlChar *s = NULL;
1389
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001390 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1391 *buf = xmlStrcat(*buf, BAD_CAST " '");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001392 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&s,
1393 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1394 ((xmlSchemaModelGroupDefPtr) item)->name));
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001395 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001396 FREE_AND_NULL(s)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001397 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001398 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001399 case XML_SCHEMA_TYPE_SEQUENCE:
1400 case XML_SCHEMA_TYPE_CHOICE:
1401 case XML_SCHEMA_TYPE_ALL:
1402 case XML_SCHEMA_TYPE_PARTICLE:
1403 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1404 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001405 default:
William M. Brack2f2a6632004-08-20 23:09:47 +00001406 named = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001407 }
William M. Brack2f2a6632004-08-20 23:09:47 +00001408 } else
1409 named = 0;
1410
1411 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00001412 xmlNodePtr elem;
1413
1414 if (itemNode->type == XML_ATTRIBUTE_NODE)
1415 elem = itemNode->parent;
1416 else
1417 elem = itemNode;
1418 *buf = xmlStrdup(BAD_CAST "Element '");
1419 if (parsing)
1420 *buf = xmlStrcat(*buf, elem->name);
1421 else
1422 *buf = xmlStrcat(*buf,
1423 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
1424 *buf = xmlStrcat(*buf, BAD_CAST "'");
1425 }
1426 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1427 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1428 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
1429 itemNode->ns, itemNode->name));
1430 *buf = xmlStrcat(*buf, BAD_CAST "'");
1431 }
1432 FREE_AND_NULL(str);
1433
1434 return (*buf);
1435}
1436
1437/**
1438 * xmlSchemaPFormatItemDes:
1439 * @buf: the string buffer
1440 * @item: the item as a schema object
1441 * @itemNode: the item as a node
1442 *
1443 * If the pointer to @buf is not NULL and @but holds no value,
1444 * the value is set to a item designation using
1445 * xmlSchemaFormatItemForReport. This one avoids adding
1446 * an attribute designation postfix.
1447 *
1448 * Returns a string of all enumeration elements.
1449 */
1450static void
1451xmlSchemaPRequestItemDes(xmlChar **buf,
1452 xmlSchemaTypePtr item,
1453 xmlNodePtr itemNode)
1454{
1455 if ((buf == 0) || (*buf != NULL))
1456 return;
1457 if (itemNode->type == XML_ATTRIBUTE_NODE)
1458 itemNode = itemNode->parent;
1459 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
1460}
1461
1462/**
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001463 * xmlSchemaGetCanonValueWhtsp:
1464 * @val: the precomputed value
1465 * @retValue: the returned value
1466 * @ws: the whitespace type of the value
1467 *
1468 * Get a the cononical representation of the value.
1469 * The caller has to free the returned retValue.
1470 *
1471 * Returns 0 if the value could be built and -1 in case of
1472 * API errors or if the value type is not supported yet.
1473 */
1474static int
1475xmlSchemaGetCanonValueWhtsp(const xmlChar *value,
1476 xmlSchemaValPtr val,
1477 xmlSchemaWhitespaceValueType ws,
1478 const xmlChar **retValue)
1479{
1480 xmlSchemaValType valType;
1481
1482 if ((retValue == NULL) || (value == NULL) || (val == NULL))
1483 return (-1);
1484 *retValue = NULL;
1485 valType = xmlSchemaGetValType(val);
1486 switch (valType) {
1487 case XML_SCHEMAS_STRING:
1488 if (value == NULL)
1489 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001490 else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1491 *retValue = xmlSchemaCollapseString(value);
1492 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1493 *retValue = xmlSchemaWhiteSpaceReplace(value);
1494 if ((*retValue) == NULL)
1495 *retValue = BAD_CAST xmlStrdup(value);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001496 break;
1497 case XML_SCHEMAS_NORMSTRING:
1498 if (value == NULL)
1499 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
1500 else {
1501 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1502 *retValue = xmlSchemaCollapseString(value);
1503 else
1504 *retValue = xmlSchemaWhiteSpaceReplace(value);
1505 if ((*retValue) == NULL)
1506 *retValue = BAD_CAST xmlStrdup(value);
1507 }
1508 break;
1509 default:
1510 return (xmlSchemaGetCanonValue(val, retValue));
1511 }
1512 return (0);
1513}
1514
1515/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001516 * xmlSchemaFormatFacetEnumSet:
1517 * @buf: the string buffer
1518 * @type: the type holding the enumeration facets
1519 *
1520 * Builds a string consisting of all enumeration elements.
1521 *
1522 * Returns a string of all enumeration elements.
1523 */
1524static const xmlChar *
1525xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
1526{
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001527 xmlSchemaFacetPtr facet;
1528 xmlSchemaWhitespaceValueType ws;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001529 const xmlChar *value = NULL;
1530 int res, found = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001531
1532 if (*buf != NULL)
1533 xmlFree(*buf);
1534 *buf = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001535
1536 do {
1537 /*
1538 * Use the whitespace type of the base type.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001539 */
1540 ws = (xmlSchemaWhitespaceValueType)
1541 xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001542 for (facet = type->facets; facet != NULL; facet = facet->next) {
1543 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1544 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001545 found = 1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001546 res = xmlSchemaGetCanonValueWhtsp(facet->value, facet->val,
1547 ws, &value);
1548 if (res == -1) {
1549 xmlSchemaVErr(NULL, NULL,
1550 XML_SCHEMAV_INTERNAL,
1551 "Internal error: xmlSchemaFormatFacetEnumSet, failed to "
1552 "compute the canonical lexical representation.\n",
1553 NULL, NULL);
1554 if (*buf != NULL)
1555 xmlFree(*buf);
1556 *buf = NULL;
1557 return (NULL);
1558 }
1559 if (*buf == NULL) {
1560 *buf = xmlStrdup(BAD_CAST "'");
1561 *buf = xmlStrcat(*buf, value);
1562 *buf = xmlStrcat(*buf, BAD_CAST "'");
1563 } else {
1564 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1565 *buf = xmlStrcat(*buf, value);
1566 *buf = xmlStrcat(*buf, BAD_CAST "'");
1567 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001568 if (value != NULL) {
1569 xmlFree((xmlChar *)value);
1570 value = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001571 }
1572 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001573 type = type->baseType;
1574 } while ((! found) && (type != NULL) &&
1575 (type->type != XML_SCHEMA_TYPE_BASIC));
1576
Daniel Veillardc0826a72004-08-10 14:17:33 +00001577 return ((const xmlChar *) *buf);
1578}
1579
1580/**
1581 * xmlSchemaVFacetErr:
1582 * @ctxt: the schema validation context
1583 * @error: the error code
1584 * @node: the node to be validated
1585 * @value: the value of the node
1586 * @type: the type holding the facet
1587 * @facet: the facet
1588 * @message: the error message of NULL
1589 * @str1: extra data
1590 * @str2: extra data
1591 * @str3: extra data
1592 *
1593 * Reports a facet validation error.
1594 * TODO: Should this report the value of an element as well?
1595 */
1596static void
1597xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
1598 xmlParserErrors error,
1599 xmlNodePtr node,
1600 const xmlChar *value,
1601 unsigned long length,
1602 xmlSchemaTypePtr type,
1603 xmlSchemaFacetPtr facet,
1604 const char *message,
1605 const xmlChar *str1,
1606 const xmlChar *str2,
1607 const xmlChar *str3)
1608{
1609 xmlChar *str = NULL, *msg = NULL;
1610 xmlSchemaTypeType facetType;
1611
1612 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1613 msg = xmlStrcat(msg, BAD_CAST " [");
1614 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1615 msg = xmlStrcat(msg, BAD_CAST ", facet '");
1616 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1617 facetType = XML_SCHEMA_FACET_ENUMERATION;
1618 /*
1619 * If enumerations are validated, one must not expect the
1620 * facet to be given.
1621 */
1622 } else
1623 facetType = facet->type;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001624 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001625 msg = xmlStrcat(msg, BAD_CAST "']: ");
1626 if (message == NULL) {
1627 /*
1628 * Use a default message.
1629 */
1630 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1631 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1632 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1633
1634 char len[25], actLen[25];
1635
1636 /* FIXME, TODO: What is the max expected string length of the
1637 * this value?
1638 */
1639 if (node->type == XML_ATTRIBUTE_NODE)
1640 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1641 else
1642 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1643
1644 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1645 snprintf(actLen, 24, "%lu", length);
1646
1647 if (facetType == XML_SCHEMA_FACET_LENGTH)
1648 msg = xmlStrcat(msg,
1649 BAD_CAST "this differs from the allowed length of '%s'.\n");
1650 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
1651 msg = xmlStrcat(msg,
1652 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
1653 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
1654 msg = xmlStrcat(msg,
1655 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
1656
1657 if (node->type == XML_ATTRIBUTE_NODE)
1658 xmlSchemaVErrExt(ctxt, node, error,
1659 (const char *) msg,
1660 value, (const xmlChar *) actLen, (const xmlChar *) len,
1661 NULL, NULL);
1662 else
1663 xmlSchemaVErr(ctxt, node, error,
1664 (const char *) msg,
1665 (const xmlChar *) actLen, (const xmlChar *) len);
1666
1667 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
1668 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
1669 "of the set {%s}.\n");
1670 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1671 xmlSchemaFormatFacetEnumSet(&str, type));
1672 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1673 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1674 "by the pattern '%s'.\n");
1675 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001676 facet->value);
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001677 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
1678 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
1679 "minimum value allowed ('%s').\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001680 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001681 facet->value);
1682 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
1683 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
1684 "maximum value allowed ('%s').\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001685 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001686 facet->value);
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001687#if 0
1688 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
1689 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
1690 "minimum exclusive value allowed ('%s').\n");
1691 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1692 facet->value);
1693 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
1694 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
1695 "maximum exclusive value allowed ('%s').\n");
1696 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1697 facet->value);
1698#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +00001699 } else if (node->type == XML_ATTRIBUTE_NODE) {
1700 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1701 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1702 } else {
1703 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1704 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1705 }
1706 } else {
1707 msg = xmlStrcat(msg, (const xmlChar *) message);
1708 msg = xmlStrcat(msg, BAD_CAST ".\n");
1709 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1710 }
1711 FREE_AND_NULL(str)
1712 xmlFree(msg);
1713}
1714
1715/**
1716 * xmlSchemaVSimpleTypeErr:
1717 * @ctxt: the schema validation context
1718 * @error: the error code
1719 * @type: the type used for validation
1720 * @node: the node containing the validated value
1721 * @value: the validated value
1722 *
1723 * Reports a simple type validation error.
1724 * TODO: Should this report the value of an element as well?
1725 */
1726static void
1727xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1728 xmlParserErrors error,
1729 xmlNodePtr node,
1730 const xmlChar *value,
1731 xmlSchemaTypePtr type)
1732{
1733 xmlChar *str = NULL, *msg = NULL;
1734
1735 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1736 msg = xmlStrcat(msg, BAD_CAST " [");
1737 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1738 if (node->type == XML_ATTRIBUTE_NODE) {
1739 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1740 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1741 } else {
1742 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1743 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1744 }
1745 FREE_AND_NULL(str)
1746 xmlFree(msg);
1747}
1748
1749/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001750 * xmlSchemaVComplexTypeErr:
1751 * @ctxt: the schema validation context
1752 * @error: the error code
1753 * @node: the node containing the validated value
1754 * @type: the complex type used for validation
1755 * @message: the error message
1756 *
1757 * Reports a complex type validation error.
1758 */
1759static void
1760xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1761 xmlParserErrors error,
1762 xmlNodePtr node,
1763 xmlSchemaTypePtr type,
1764 const char *message)
1765{
1766 xmlChar *str = NULL, *msg = NULL;
1767
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001768 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001769 /* Specify the complex type only if it is global. */
1770 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001771 msg = xmlStrcat(msg, BAD_CAST " [");
1772 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1773 msg = xmlStrcat(msg, BAD_CAST "]");
1774 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001775 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1776 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001777 (const xmlChar *) message, NULL);
1778 FREE_AND_NULL(str)
1779 xmlFree(msg);
1780}
1781
1782/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001783 * xmlSchemaVComplexTypeElemErr:
1784 * @ctxt: the schema validation context
1785 * @error: the error code
1786 * @node: the node containing the validated value
1787 * @type: the complex type used for validation
1788 * @message: the error message
1789 *
1790 * Reports a complex type validation error.
1791 */
1792static void
1793xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1794 xmlParserErrors error,
1795 xmlNodePtr node,
1796 xmlSchemaTypePtr type,
1797 const char *message,
1798 int nbval,
1799 int nbneg,
1800 xmlChar **values)
1801{
1802 xmlChar *str = NULL, *msg = NULL;
1803 xmlChar *localName, *nsName;
1804 const xmlChar *cur, *end;
1805 int i;
1806
1807 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1808 /* Specify the complex type only if it is global. */
1809 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1810 msg = xmlStrcat(msg, BAD_CAST " [");
1811 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1812 msg = xmlStrcat(msg, BAD_CAST "]");
1813 FREE_AND_NULL(str)
1814 }
1815 msg = xmlStrcat(msg, BAD_CAST ": ");
1816 msg = xmlStrcat(msg, (const xmlChar *) message);
1817 /*
1818 * Note that is does not make sense to report that we have a
1819 * wildcard here, since the wildcard might be unfolded into
1820 * multiple transitions.
1821 */
1822 if (nbval + nbneg > 0) {
1823 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001824 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001825 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001826 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001827 nsName = NULL;
1828
1829 for (i = 0; i < nbval + nbneg; i++) {
1830 cur = values[i];
1831 /*
1832 * Get the local name.
1833 */
1834 localName = NULL;
1835
1836 end = cur;
1837 if (*end == '*') {
1838 localName = xmlStrdup(BAD_CAST "*");
1839 *end++;
1840 } else {
1841 while ((*end != 0) && (*end != '|'))
1842 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001843 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001844 }
1845 if (*end != 0) {
1846 *end++;
1847 /*
1848 * Skip "*|*" if they come with negated expressions, since
1849 * they represent the same negated wildcard.
1850 */
1851 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1852 /*
1853 * Get the namespace name.
1854 */
1855 cur = end;
1856 if (*end == '*') {
1857 nsName = xmlStrdup(BAD_CAST "{*}");
1858 } else {
1859 while (*end != 0)
1860 end++;
1861
1862 if (i >= nbval)
1863 nsName = xmlStrdup(BAD_CAST "{##other:");
1864 else
1865 nsName = xmlStrdup(BAD_CAST "{");
1866
1867 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1868 nsName = xmlStrcat(nsName, BAD_CAST "}");
1869 }
1870 str = xmlStrcat(str, BAD_CAST nsName);
1871 FREE_AND_NULL(nsName)
1872 } else {
1873 FREE_AND_NULL(localName);
1874 continue;
1875 }
1876 }
1877 str = xmlStrcat(str, BAD_CAST localName);
1878 FREE_AND_NULL(localName);
1879
1880 if (i < nbval + nbneg -1)
1881 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001882 }
1883 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001884 msg = xmlStrcat(msg, BAD_CAST str);
1885 FREE_AND_NULL(str)
1886 }
1887 msg = xmlStrcat(msg, BAD_CAST ".\n");
1888 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1889 xmlFree(msg);
1890}
1891
1892/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001893 * xmlSchemaPMissingAttrErr:
1894 * @ctxt: the schema validation context
1895 * @ownerDes: the designation of the owner
1896 * @ownerName: the name of the owner
1897 * @ownerItem: the owner as a schema object
1898 * @ownerElem: the owner as an element node
1899 * @node: the parent element node of the missing attribute node
1900 * @type: the corresponding type of the attribute node
1901 *
1902 * Reports an illegal attribute.
1903 */
1904static void
1905xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1906 xmlParserErrors error,
1907 xmlChar **ownerDes,
1908 xmlSchemaTypePtr ownerItem,
1909 xmlNodePtr ownerElem,
1910 const char *name,
1911 const char *message)
1912{
1913 xmlChar *des = NULL;
1914
1915 if (ownerDes == NULL)
1916 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1917 else if (*ownerDes == NULL) {
1918 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1919 des = *ownerDes;
1920 } else
1921 des = *ownerDes;
1922 if (message != NULL)
1923 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1924 else
1925 xmlSchemaPErr(ctxt, ownerElem, error,
1926 "%s: The attribute '%s' is required but missing.\n",
1927 BAD_CAST des, BAD_CAST name);
1928 if (ownerDes == NULL)
1929 FREE_AND_NULL(des);
1930}
1931
William M. Brack2f2a6632004-08-20 23:09:47 +00001932/**
1933 * xmlSchemaCompTypeToString:
1934 * @type: the type of the schema item
1935 *
1936 * Returns the component name of a schema item.
1937 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001938static const xmlChar *
Daniel Veillardc0826a72004-08-10 14:17:33 +00001939xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1940{
1941 switch (type) {
1942 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001943 return(BAD_CAST "simple type definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001944 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001945 return(BAD_CAST "complex type definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001946 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001947 return(BAD_CAST "element declaration");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001948 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001949 return(BAD_CAST "attribute declaration");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001950 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001951 return(BAD_CAST "model group definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001952 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001953 return(BAD_CAST "attribute group definition");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001954 case XML_SCHEMA_TYPE_NOTATION:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001955 return(BAD_CAST "notation declaration");
1956 case XML_SCHEMA_TYPE_SEQUENCE:
1957 return(BAD_CAST "model group (sequence)");
1958 case XML_SCHEMA_TYPE_CHOICE:
1959 return(BAD_CAST "model group (choice)");
1960 case XML_SCHEMA_TYPE_ALL:
1961 return(BAD_CAST "model group (all)");
1962 case XML_SCHEMA_TYPE_PARTICLE:
1963 return(BAD_CAST "particle");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001964 default:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001965 return(BAD_CAST "Not a schema component");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001966 }
1967}
1968/**
1969 * xmlSchemaPResCompAttrErr:
1970 * @ctxt: the schema validation context
1971 * @error: the error code
1972 * @ownerDes: the designation of the owner
1973 * @ownerItem: the owner as a schema object
1974 * @ownerElem: the owner as an element node
1975 * @name: the name of the attribute holding the QName
1976 * @refName: the referenced local name
1977 * @refURI: the referenced namespace URI
1978 * @message: optional message
1979 *
1980 * Used to report QName attribute values that failed to resolve
1981 * to schema components.
1982 */
1983static void
1984xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1985 xmlParserErrors error,
1986 xmlChar **ownerDes,
1987 xmlSchemaTypePtr ownerItem,
1988 xmlNodePtr ownerElem,
1989 const char *name,
1990 const xmlChar *refName,
1991 const xmlChar *refURI,
1992 xmlSchemaTypeType refType,
1993 const char *refTypeStr)
1994{
1995 xmlChar *des = NULL, *strA = NULL;
1996
1997 if (ownerDes == NULL)
1998 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1999 else if (*ownerDes == NULL) {
2000 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
2001 des = *ownerDes;
2002 } else
2003 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002004 if (refTypeStr == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002005 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002006 xmlSchemaPErrExt(ctxt, ownerElem, error,
2007 NULL, NULL, NULL,
2008 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
2009 "%s.\n", BAD_CAST des, BAD_CAST name,
2010 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
2011 BAD_CAST refTypeStr, NULL);
2012 if (ownerDes == NULL)
2013 FREE_AND_NULL(des)
2014 FREE_AND_NULL(strA)
2015}
2016
William M. Brack2f2a6632004-08-20 23:09:47 +00002017/**
2018 * xmlSchemaPCustomAttrErr:
2019 * @ctxt: the schema parser context
2020 * @error: the error code
2021 * @ownerDes: the designation of the owner
2022 * @ownerItem: the owner as a schema object
2023 * @attr: the illegal attribute node
2024 *
2025 * Reports an illegal attribute during the parse.
2026 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002027static void
2028xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00002029 xmlParserErrors error,
2030 xmlChar **ownerDes,
2031 xmlSchemaTypePtr ownerItem,
2032 xmlAttrPtr attr,
2033 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002034{
2035 xmlChar *des = NULL;
2036
2037 if (ownerDes == NULL)
2038 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2039 else if (*ownerDes == NULL) {
2040 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2041 des = *ownerDes;
2042 } else
2043 des = *ownerDes;
2044 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2045 "%s, attribute '%s': %s.\n",
2046 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2047 if (ownerDes == NULL)
2048 FREE_AND_NULL(des);
2049}
2050
2051/**
2052 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002053 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002054 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002055 * @ownerDes: the designation of the attribute's owner
2056 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00002057 * @attr: the illegal attribute node
2058 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002059 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002060 */
2061static void
2062xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2063 xmlParserErrors error,
2064 xmlChar **ownerDes,
2065 xmlSchemaTypePtr ownerItem,
2066 xmlAttrPtr attr)
2067{
2068 xmlChar *des = NULL, *strA = NULL;
2069
2070 if (ownerDes == NULL)
2071 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2072 else if (*ownerDes == NULL) {
2073 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2074 des = *ownerDes;
2075 } else
2076 des = *ownerDes;
2077 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2078 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2079 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2080 if (ownerDes == NULL)
2081 FREE_AND_NULL(des);
2082 FREE_AND_NULL(strA);
2083}
2084
William M. Brack2f2a6632004-08-20 23:09:47 +00002085/**
2086 * xmlSchemaPAquireDes:
2087 * @des: the first designation
2088 * @itemDes: the second designation
2089 * @item: the schema item
2090 * @itemElem: the node of the schema item
2091 *
2092 * Creates a designation for an item.
2093 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002094static void
2095xmlSchemaPAquireDes(xmlChar **des,
2096 xmlChar **itemDes,
2097 xmlSchemaTypePtr item,
2098 xmlNodePtr itemElem)
2099{
2100 if (itemDes == NULL)
2101 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
2102 else if (*itemDes == NULL) {
2103 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
2104 *des = *itemDes;
2105 } else
2106 *des = *itemDes;
2107}
2108
William M. Brack2f2a6632004-08-20 23:09:47 +00002109/**
2110 * xmlSchemaPCustomErr:
2111 * @ctxt: the schema parser context
2112 * @error: the error code
2113 * @itemDes: the designation of the schema item
2114 * @item: the schema item
2115 * @itemElem: the node of the schema item
2116 * @message: the error message
2117 * @str1: an optional param for the error message
2118 * @str2: an optional param for the error message
2119 * @str3: an optional param for the error message
2120 *
2121 * Reports an error during parsing.
2122 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002123static void
2124xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2125 xmlParserErrors error,
2126 xmlChar **itemDes,
2127 xmlSchemaTypePtr item,
2128 xmlNodePtr itemElem,
2129 const char *message,
2130 const xmlChar *str1,
2131 const xmlChar *str2,
2132 const xmlChar *str3)
2133{
2134 xmlChar *des = NULL, *msg = NULL;
2135
2136 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
2137 msg = xmlStrdup(BAD_CAST "%s: ");
2138 msg = xmlStrcat(msg, (const xmlChar *) message);
2139 msg = xmlStrcat(msg, BAD_CAST ".\n");
2140 if ((itemElem == NULL) && (item != NULL))
2141 itemElem = item->node;
2142 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2143 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2144 if (itemDes == NULL)
2145 FREE_AND_NULL(des);
2146 FREE_AND_NULL(msg);
2147}
2148
William M. Brack2f2a6632004-08-20 23:09:47 +00002149/**
2150 * xmlSchemaPCustomErr:
2151 * @ctxt: the schema parser context
2152 * @error: the error code
2153 * @itemDes: the designation of the schema item
2154 * @item: the schema item
2155 * @itemElem: the node of the schema item
2156 * @message: the error message
2157 * @str1: the optional param for the error message
2158 *
2159 * Reports an error during parsing.
2160 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002161static void
2162xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2163 xmlParserErrors error,
2164 xmlChar **itemDes,
2165 xmlSchemaTypePtr item,
2166 xmlNodePtr itemElem,
2167 const char *message,
2168 const xmlChar *str1)
2169{
2170 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2171 str1, NULL, NULL);
2172}
2173
William M. Brack2f2a6632004-08-20 23:09:47 +00002174/**
2175 * xmlSchemaPAttrUseErr:
2176 * @ctxt: the schema parser context
2177 * @error: the error code
2178 * @itemDes: the designation of the schema type
2179 * @item: the schema type
2180 * @itemElem: the node of the schema type
2181 * @attr: the invalid schema attribute
2182 * @message: the error message
2183 * @str1: the optional param for the error message
2184 *
2185 * Reports an attribute use error during parsing.
2186 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002187static void
2188xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
2189 xmlParserErrors error,
2190 xmlChar **itemDes,
2191 xmlSchemaTypePtr item,
2192 xmlNodePtr itemElem,
2193 const xmlSchemaAttributePtr attr,
2194 const char *message,
2195 const xmlChar *str1)
2196{
2197 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
2198
2199 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
2200 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
2201 xmlSchemaGetAttrName(attr));
2202 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
2203 msg = xmlStrcat(msg, (const xmlChar *) message);
2204 msg = xmlStrcat(msg, BAD_CAST ".\n");
2205 if ((itemElem == NULL) && (item != NULL))
2206 itemElem = item->node;
2207 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2208 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
2209 if (itemDes == NULL)
2210 FREE_AND_NULL(des);
2211 FREE_AND_NULL(strA);
2212 xmlFree(msg);
2213}
2214
William M. Brack2f2a6632004-08-20 23:09:47 +00002215/**
2216 * xmlSchemaPIllegalFacetAtomicErr:
2217 * @ctxt: the schema parser context
2218 * @error: the error code
2219 * @itemDes: the designation of the type
2220 * @item: the schema type
2221 * @baseItem: the base type of type
2222 * @facet: the illegal facet
2223 *
2224 * Reports an illegal facet for atomic simple types.
2225 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002226static void
2227xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
2228 xmlParserErrors error,
2229 xmlChar **itemDes,
2230 xmlSchemaTypePtr item,
2231 xmlSchemaTypePtr baseItem,
2232 xmlSchemaFacetPtr facet)
2233{
2234 xmlChar *des = NULL, *strT = NULL;
2235
2236 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2237 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2238 "%s: The facet '%s' is not allowed on types derived from the "
2239 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002240 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002241 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
2242 NULL, NULL);
2243 if (itemDes == NULL)
2244 FREE_AND_NULL(des);
2245 FREE_AND_NULL(strT);
2246}
2247
William M. Brack2f2a6632004-08-20 23:09:47 +00002248/**
2249 * xmlSchemaPIllegalFacetListUnionErr:
2250 * @ctxt: the schema parser context
2251 * @error: the error code
2252 * @itemDes: the designation of the schema item involved
2253 * @item: the schema item involved
2254 * @facet: the illegal facet
2255 *
2256 * Reports an illegal facet for <list> and <union>.
2257 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002258static void
2259xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
2260 xmlParserErrors error,
2261 xmlChar **itemDes,
2262 xmlSchemaTypePtr item,
2263 xmlSchemaFacetPtr facet)
2264{
2265 xmlChar *des = NULL, *strT = NULL;
2266
2267 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2268 xmlSchemaPErr(ctxt, item->node, error,
2269 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002270 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002271 if (itemDes == NULL)
2272 FREE_AND_NULL(des);
2273 FREE_AND_NULL(strT);
2274}
2275
2276/**
2277 * xmlSchemaPMutualExclAttrErr:
2278 * @ctxt: the schema validation context
2279 * @error: the error code
2280 * @elemDes: the designation of the parent element node
2281 * @attr: the bad attribute node
2282 * @type: the corresponding type of the attribute node
2283 *
2284 * Reports an illegal attribute.
2285 */
2286static void
2287xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2288 xmlParserErrors error,
2289 xmlChar **ownerDes,
2290 xmlSchemaTypePtr ownerItem,
2291 xmlAttrPtr attr,
2292 const char *name1,
2293 const char *name2)
2294{
2295 xmlChar *des = NULL;
2296
2297 if (ownerDes == NULL)
2298 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2299 else if (*ownerDes == NULL) {
2300 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2301 des = *ownerDes;
2302 } else
2303 des = *ownerDes;
2304 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2305 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
2306 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2307 if (ownerDes == NULL)
2308 FREE_AND_NULL(des)
2309}
2310
2311/**
2312 * xmlSchemaPSimpleTypeErr:
2313 * @ctxt: the schema validation context
2314 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002315 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002316 * @ownerDes: the designation of the owner
2317 * @ownerItem: the schema object if existent
2318 * @node: the validated node
2319 * @value: the validated value
2320 *
2321 * Reports a simple type validation error.
2322 * TODO: Should this report the value of an element as well?
2323 */
2324static void
2325xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2326 xmlParserErrors error,
2327 xmlChar **ownerDes,
2328 xmlSchemaTypePtr ownerItem,
2329 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002330 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002331 const char *typeDes,
2332 const xmlChar *value,
2333 const char *message,
2334 const xmlChar *str1,
2335 const xmlChar *str2)
2336{
William M. Brack2f2a6632004-08-20 23:09:47 +00002337 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002338
2339 if (ownerDes == NULL)
2340 xmlSchemaPRequestItemDes(&des, ownerItem, node);
2341 else if (*ownerDes == NULL) {
2342 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
2343 des = *ownerDes;
2344 } else
2345 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00002346 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002347 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002348 if (message == NULL) {
2349 /*
2350 * Use default messages.
2351 */
2352 if (node->type == XML_ATTRIBUTE_NODE) {
2353 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2354 "%s, attribute '%s' [%s]: The value '%s' is not "
2355 "valid.\n",
2356 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
2357 node->name), BAD_CAST typeDes, value, NULL);
2358 } else {
2359 xmlSchemaPErr(ctxt, node, error,
2360 "%s [%s]: The character content is not valid.\n",
2361 BAD_CAST des, BAD_CAST typeDes);
2362 }
2363 } else {
2364 xmlChar *msg;
2365
2366 msg = xmlStrdup(BAD_CAST "%s");
2367 if (node->type == XML_ATTRIBUTE_NODE)
2368 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
2369 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
2370 msg = xmlStrcat(msg, (const xmlChar *) message);
2371 msg = xmlStrcat(msg, BAD_CAST ".\n");
2372 if (node->type == XML_ATTRIBUTE_NODE) {
2373 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2374 (const char *) msg,
2375 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
2376 node->ns, node->name), BAD_CAST typeDes, str1, str2);
2377 } else {
2378 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2379 (const char *) msg,
2380 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
2381 }
2382 xmlFree(msg);
2383 }
2384 /* Cleanup. */
2385 FREE_AND_NULL(strA)
2386 FREE_AND_NULL(strT)
2387 if (ownerDes == NULL)
2388 FREE_AND_NULL(des)
2389}
2390
William M. Brack2f2a6632004-08-20 23:09:47 +00002391/**
2392 * xmlSchemaPContentErr:
2393 * @ctxt: the schema parser context
2394 * @error: the error code
2395 * @onwerDes: the designation of the holder of the content
2396 * @ownerItem: the owner item of the holder of the content
2397 * @ownerElem: the node of the holder of the content
2398 * @child: the invalid child node
2399 * @message: the optional error message
2400 * @content: the optional string describing the correct content
2401 *
2402 * Reports an error concerning the content of a schema element.
2403 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002404static void
2405xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
2406 xmlParserErrors error,
2407 xmlChar **ownerDes,
2408 xmlSchemaTypePtr ownerItem,
2409 xmlNodePtr ownerElem,
2410 xmlNodePtr child,
2411 const char *message,
2412 const char *content)
2413{
2414 xmlChar *des = NULL;
2415
2416 if (ownerDes == NULL)
2417 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
2418 else if (*ownerDes == NULL) {
2419 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
2420 des = *ownerDes;
2421 } else
2422 des = *ownerDes;
2423 if (message != NULL)
2424 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2425 "%s: %s.\n",
2426 BAD_CAST des, BAD_CAST message);
2427 else {
2428 if (content != NULL) {
2429 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2430 "%s: The content is not valid. Expected is %s.\n",
2431 BAD_CAST des, BAD_CAST content);
2432 } else {
2433 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2434 "%s: The content is not valid.\n",
2435 BAD_CAST des, NULL);
2436 }
2437 }
2438 if (ownerDes == NULL)
2439 FREE_AND_NULL(des)
2440}
2441
2442/**
2443 * xmlSchemaVIllegalAttrErr:
2444 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002445 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00002446 * @attr: the illegal attribute node
2447 *
2448 * Reports an illegal attribute.
2449 */
2450static void
2451xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002452 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002453 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002454{
2455 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002456
2457 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
2458 error,
2459 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002460 "%s: The attribute '%s' is not allowed.\n",
2461 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
2462 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2463 FREE_AND_NULL(strE)
2464 FREE_AND_NULL(strA)
2465}
2466
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002467
2468static int
2469xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2470{
2471 switch (item->type) {
2472 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002473 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002474 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2475 return(1);
2476 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002477 case XML_SCHEMA_TYPE_GROUP:
2478 return (1);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002479 case XML_SCHEMA_TYPE_ELEMENT:
2480 if ( ((xmlSchemaElementPtr) item)->flags &
2481 XML_SCHEMAS_ELEM_GLOBAL)
2482 return(1);
2483 break;
2484 case XML_SCHEMA_TYPE_ATTRIBUTE:
2485 if ( ((xmlSchemaAttributePtr) item)->flags &
2486 XML_SCHEMAS_ATTR_GLOBAL)
2487 return(1);
2488 break;
2489 /* Note that attribute groups are always global. */
2490 default:
2491 return(1);
2492 }
2493 return (0);
2494}
2495
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002496
2497static void
2498xmlSchemaStreamVCustomErr(xmlSchemaValidCtxtPtr vctxt,
2499 xmlParserErrors error,
2500 xmlSchemaNodeInfoPtr nodeInfo,
2501 xmlSchemaTypePtr type,
2502 const char *message,
2503 const xmlChar *str1,
2504 const xmlChar *str2)
2505{
2506 xmlChar *msg = NULL, *str = NULL;
2507
2508 msg = xmlStrdup(BAD_CAST "Element '");
2509
2510 if (vctxt->elemInfos[vctxt->depth] != nodeInfo) {
2511 xmlSchemaNodeInfoPtr elemInfo;
2512 /*
2513 * The node info is an attribute info.
2514 */
2515 elemInfo = vctxt->elemInfos[vctxt->depth];
2516 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2517 elemInfo->namespaceName, elemInfo->localName));
2518 msg = xmlStrcat(msg, BAD_CAST "', ");
2519 msg = xmlStrcat(msg, BAD_CAST "attribute '");
2520 }
2521 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2522 nodeInfo->namespaceName, nodeInfo->localName));
2523 msg = xmlStrcat(msg, BAD_CAST "'");
2524
2525 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2526 msg = xmlStrcat(msg, BAD_CAST " [");
2527 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str,
2528 NULL, type, NULL, 0));
2529 msg = xmlStrcat(msg, BAD_CAST "]");
2530 }
2531 msg = xmlStrcat(msg, BAD_CAST ": ");
2532
2533 msg = xmlStrcat(msg, (const xmlChar *) message);
2534 msg = xmlStrcat(msg, BAD_CAST ".\n");
2535 xmlSchemaVErr(vctxt, nodeInfo->node, error, (const char *) msg,
2536 str1, str2);
2537 FREE_AND_NULL(msg)
2538 FREE_AND_NULL(str)
2539}
2540
William M. Brack2f2a6632004-08-20 23:09:47 +00002541/**
2542 * xmlSchemaVCustomErr:
2543 * @ctxt: the schema validation context
2544 * @error: the error code
2545 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002546 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00002547 * @message: the error message
2548 * @str1: the optional param for the message
2549 *
2550 * Reports a validation error.
2551 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002552static void
2553xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
2554 xmlParserErrors error,
2555 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002556 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002557 const char *message,
2558 const xmlChar *str1)
2559{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002560 xmlChar *msg = NULL, *str = NULL;
2561
2562 if (node == NULL) {
2563 xmlSchemaVErr(ctxt, NULL,
2564 XML_SCHEMAV_INTERNAL,
2565 "Internal error: xmlSchemaVCustomErr, no node "
2566 "given.\n", NULL, NULL);
2567 return;
2568 }
2569 /* TODO: Are the HTML and DOCB doc nodes expected here? */
2570 if (node->type != XML_DOCUMENT_NODE) {
2571 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002572 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002573 msg = xmlStrcat(msg, BAD_CAST " [");
2574 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
2575 msg = xmlStrcat(msg, BAD_CAST "]");
2576 }
2577 msg = xmlStrcat(msg, BAD_CAST ": ");
2578 } else
2579 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002580 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002581 msg = xmlStrcat(msg, BAD_CAST ".\n");
2582 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
2583 FREE_AND_NULL(msg)
2584 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002585}
2586
William M. Brack2f2a6632004-08-20 23:09:47 +00002587/**
William M. Brack2f2a6632004-08-20 23:09:47 +00002588 * xmlSchemaVWildcardErr:
2589 * @ctxt: the schema validation context
2590 * @error: the error code
2591 * @node: the validated node
2592 * @wild: the wildcard used
2593 * @message: the error message
2594 *
2595 * Reports an validation-by-wildcard error.
2596 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002597static void
2598xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
2599 xmlParserErrors error,
2600 xmlNodePtr node,
2601 xmlSchemaWildcardPtr wild,
2602 const char *message)
2603{
2604 xmlChar *des = NULL, *msg = NULL;
2605
2606 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00002607 msg = xmlStrdup(BAD_CAST "%s [");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002608 msg = xmlStrcat(msg, xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002609 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002610 msg = xmlStrcat(msg, (const xmlChar *) message);
2611 msg = xmlStrcat(msg, BAD_CAST ".\n");
2612 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
2613 FREE_AND_NULL(des);
2614 FREE_AND_NULL(msg);
2615}
2616
2617/**
2618 * xmlSchemaVMissingAttrErr:
2619 * @ctxt: the schema validation context
2620 * @node: the parent element node of the missing attribute node
2621 * @type: the corresponding type of the attribute node
2622 *
2623 * Reports an illegal attribute.
2624 */
2625static void
2626xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
2627 xmlNodePtr elem,
2628 xmlSchemaAttributePtr type)
2629{
2630 const xmlChar *name, *uri;
2631 xmlChar *strE = NULL, *strA = NULL;
2632
2633 if (type->ref != NULL) {
2634 name = type->ref;
2635 uri = type->refNs;
2636 } else {
2637 name = type->name;
2638 uri = type->targetNamespace;
2639 }
2640 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002641 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
2642 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002643 "%s: The attribute %s is required but missing.\n",
2644 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
2645 xmlSchemaFormatNsUriLocal(&strA, uri, name));
2646 FREE_AND_NULL(strE)
2647 FREE_AND_NULL(strA)
2648}
2649
Daniel Veillard4255d502002-04-16 15:50:10 +00002650/************************************************************************
2651 * *
2652 * Allocation functions *
2653 * *
2654 ************************************************************************/
2655
2656/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002657 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002658 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002659 *
2660 * Allocate a new Schema structure.
2661 *
2662 * Returns the newly allocated structure or NULL in case or error
2663 */
2664static xmlSchemaPtr
2665xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2666{
2667 xmlSchemaPtr ret;
2668
2669 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2670 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002671 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002672 return (NULL);
2673 }
2674 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002675 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002676 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002677
2678 return (ret);
2679}
2680
2681/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002682 * xmlSchemaNewSchema:
2683 * @ctxt: a schema validation context
2684 *
2685 * Allocate a new Schema structure.
2686 *
2687 * Returns the newly allocated structure or NULL in case or error
2688 */
2689static xmlSchemaAssemblePtr
2690xmlSchemaNewAssemble(void)
2691{
2692 xmlSchemaAssemblePtr ret;
2693
2694 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2695 if (ret == NULL) {
2696 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2697 return (NULL);
2698 }
2699 memset(ret, 0, sizeof(xmlSchemaAssemble));
2700 ret->items = NULL;
2701 return (ret);
2702}
2703
2704/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002705 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002706 *
2707 * Allocate a new Facet structure.
2708 *
2709 * Returns the newly allocated structure or NULL in case or error
2710 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002711xmlSchemaFacetPtr
2712xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002713{
2714 xmlSchemaFacetPtr ret;
2715
2716 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2717 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002718 return (NULL);
2719 }
2720 memset(ret, 0, sizeof(xmlSchemaFacet));
2721
2722 return (ret);
2723}
2724
2725/**
2726 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002727 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002728 * @node: a node
2729 *
2730 * Allocate a new annotation structure.
2731 *
2732 * Returns the newly allocated structure or NULL in case or error
2733 */
2734static xmlSchemaAnnotPtr
2735xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2736{
2737 xmlSchemaAnnotPtr ret;
2738
2739 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2740 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002741 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002742 return (NULL);
2743 }
2744 memset(ret, 0, sizeof(xmlSchemaAnnot));
2745 ret->content = node;
2746 return (ret);
2747}
2748
2749/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002750 * xmlSchemaFreeAnnot:
2751 * @annot: a schema type structure
2752 *
2753 * Deallocate a annotation structure
2754 */
2755static void
2756xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2757{
2758 if (annot == NULL)
2759 return;
2760 xmlFree(annot);
2761}
2762
2763/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002764 * xmlSchemaFreeImport:
2765 * @import: a schema import structure
2766 *
2767 * Deallocate an import structure
2768 */
2769static void
2770xmlSchemaFreeImport(xmlSchemaImportPtr import)
2771{
2772 if (import == NULL)
2773 return;
2774
2775 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002776 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002777 xmlFree(import);
2778}
2779
2780/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002781 * xmlSchemaFreeInclude:
2782 * @include: a schema include structure
2783 *
2784 * Deallocate an include structure
2785 */
2786static void
2787xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2788{
2789 if (include == NULL)
2790 return;
2791
2792 xmlFreeDoc(include->doc);
2793 xmlFree(include);
2794}
2795
2796/**
2797 * xmlSchemaFreeIncludeList:
2798 * @includes: a schema include list
2799 *
2800 * Deallocate an include structure
2801 */
2802static void
2803xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2804{
2805 xmlSchemaIncludePtr next;
2806
2807 while (includes != NULL) {
2808 next = includes->next;
2809 xmlSchemaFreeInclude(includes);
2810 includes = next;
2811 }
2812}
2813
2814/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002815 * xmlSchemaFreeNotation:
2816 * @schema: a schema notation structure
2817 *
2818 * Deallocate a Schema Notation structure.
2819 */
2820static void
2821xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2822{
2823 if (nota == NULL)
2824 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002825 xmlFree(nota);
2826}
2827
2828/**
2829 * xmlSchemaFreeAttribute:
2830 * @schema: a schema attribute structure
2831 *
2832 * Deallocate a Schema Attribute structure.
2833 */
2834static void
2835xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2836{
2837 if (attr == NULL)
2838 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002839 if (attr->annot != NULL)
2840 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002841 if (attr->defVal != NULL)
2842 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002843 xmlFree(attr);
2844}
2845
2846/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002847 * xmlSchemaFreeWildcardNsSet:
2848 * set: a schema wildcard namespace
2849 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002850 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002851 */
2852static void
2853xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2854{
2855 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002856
Daniel Veillard3646d642004-06-02 19:19:14 +00002857 while (set != NULL) {
2858 next = set->next;
2859 xmlFree(set);
2860 set = next;
2861 }
2862}
2863
2864/**
2865 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002866 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002867 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002868 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002869 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002870void
Daniel Veillard3646d642004-06-02 19:19:14 +00002871xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2872{
2873 if (wildcard == NULL)
2874 return;
2875 if (wildcard->annot != NULL)
2876 xmlSchemaFreeAnnot(wildcard->annot);
2877 if (wildcard->nsSet != NULL)
2878 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2879 if (wildcard->negNsSet != NULL)
2880 xmlFree(wildcard->negNsSet);
2881 xmlFree(wildcard);
2882}
2883
2884/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002885 * xmlSchemaFreeAttributeGroup:
2886 * @schema: a schema attribute group structure
2887 *
2888 * Deallocate a Schema Attribute Group structure.
2889 */
2890static void
2891xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2892{
2893 if (attr == NULL)
2894 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002895 if (attr->annot != NULL)
2896 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002897 xmlFree(attr);
2898}
2899
2900/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002901 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002902 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002903 *
2904 * Deallocate a list of schema attribute uses.
2905 */
2906static void
2907xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2908{
2909 xmlSchemaAttributeLinkPtr next;
2910
2911 while (attrUse != NULL) {
2912 next = attrUse->next;
2913 xmlFree(attrUse);
2914 attrUse = next;
2915 }
2916}
2917
2918/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00002919 * xmlSchemaFreeQNameRef:
2920 * @item: a QName reference structure
2921 *
2922 * Deallocatea a QName reference structure.
2923 */
2924static void
2925xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
2926{
2927 xmlFree(item);
2928}
2929
2930static int
2931xmlSchemaAddVolatile(xmlSchemaPtr schema,
2932 xmlSchemaBasicItemPtr item)
2933{
2934 xmlSchemaItemListPtr list;
2935
2936 if (schema->volatiles == NULL) {
2937 schema->volatiles = (void *) xmlMalloc(sizeof(xmlSchemaItemList));
2938 if (schema->volatiles == NULL) {
2939 xmlSchemaPErrMemory(NULL,
2940 "allocating list of volatiles", NULL);
2941 return (-1);
2942 }
2943 memset(schema->volatiles, 0, sizeof(xmlSchemaItemList));
2944
2945 }
2946 list = (xmlSchemaItemListPtr) schema->volatiles;
2947 if (list->items == NULL) {
2948 list->items = (void **) xmlMalloc(
2949 20 * sizeof(xmlSchemaBasicItemPtr));
2950 if (list->items == NULL) {
2951 xmlSchemaPErrMemory(NULL,
2952 "allocating new volatile item buffer", NULL);
2953 return (-1);
2954 }
2955 list->sizeItems = 20;
2956 } else if (list->sizeItems <= list->nbItems) {
2957 list->sizeItems *= 2;
2958 list->items = (void **) xmlRealloc(list->items,
2959 list->sizeItems * sizeof(xmlSchemaTypePtr));
2960 if (list->items == NULL) {
2961 xmlSchemaPErrMemory(NULL,
2962 "growing volatile item buffer", NULL);
2963 list->sizeItems = 0;
2964 return (-1);
2965 }
2966 }
2967 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
2968 return (0);
2969}
2970
2971/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002972 * xmlSchemaFreeTypeLinkList:
2973 * @alink: a type link
2974 *
2975 * Deallocate a list of types.
2976 */
2977static void
2978xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2979{
2980 xmlSchemaTypeLinkPtr next;
2981
2982 while (link != NULL) {
2983 next = link->next;
2984 xmlFree(link);
2985 link = next;
2986 }
2987}
2988
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002989static void
2990xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
2991{
2992 xmlSchemaIDCStateObjPtr next;
2993 while (sto != NULL) {
2994 next = sto->next;
2995 if (sto->history != NULL)
2996 xmlFree(sto->history);
2997 if (sto->xpathCtxt != NULL)
2998 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
2999 xmlFree(sto);
3000 sto = next;
3001 }
3002}
3003
3004/**
3005 * xmlSchemaFreeIDC:
3006 * @idc: a identity-constraint definition
3007 *
3008 * Deallocates an identity-constraint definition.
3009 */
3010static void
3011xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3012{
3013 xmlSchemaIDCSelectPtr cur, prev;
3014
3015 if (idcDef == NULL)
3016 return;
3017 if (idcDef->annot != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003018 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003019 /* Selector */
3020 if (idcDef->selector != NULL) {
3021 if (idcDef->selector->xpathComp != NULL)
3022 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3023 xmlFree(idcDef->selector);
3024 }
3025 /* Fields */
3026 if (idcDef->fields != NULL) {
3027 cur = idcDef->fields;
3028 do {
3029 prev = cur;
3030 cur = cur->next;
3031 if (prev->xpathComp != NULL)
3032 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3033 xmlFree(prev);
3034 } while (cur != NULL);
3035 }
3036 xmlFree(idcDef);
3037}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003038
Daniel Veillard01fa6152004-06-29 17:04:39 +00003039/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003040 * xmlSchemaFreeElement:
3041 * @schema: a schema element structure
3042 *
3043 * Deallocate a Schema Element structure.
3044 */
3045static void
3046xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3047{
3048 if (elem == NULL)
3049 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003050 if (elem->annot != NULL)
3051 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003052 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003053 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003054 if (elem->defVal != NULL)
3055 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003056 xmlFree(elem);
3057}
3058
3059/**
3060 * xmlSchemaFreeFacet:
3061 * @facet: a schema facet structure
3062 *
3063 * Deallocate a Schema Facet structure.
3064 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003065void
Daniel Veillard4255d502002-04-16 15:50:10 +00003066xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3067{
3068 if (facet == NULL)
3069 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003070 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003071 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003072 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003073 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003074 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003075 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003076 xmlFree(facet);
3077}
3078
3079/**
3080 * xmlSchemaFreeType:
3081 * @type: a schema type structure
3082 *
3083 * Deallocate a Schema Type structure.
3084 */
3085void
3086xmlSchemaFreeType(xmlSchemaTypePtr type)
3087{
3088 if (type == NULL)
3089 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003090 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003091 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003092 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003093 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003094
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003095 facet = type->facets;
3096 while (facet != NULL) {
3097 next = facet->next;
3098 xmlSchemaFreeFacet(facet);
3099 facet = next;
3100 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003101 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003102 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3103 if (type->attributeUses != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003104 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003105 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003106 if (type->memberTypes != NULL)
3107 xmlSchemaFreeTypeLinkList(type->memberTypes);
3108 if (type->facetSet != NULL) {
3109 xmlSchemaFacetLinkPtr next, link;
3110
3111 link = type->facetSet;
3112 do {
3113 next = link->next;
3114 xmlFree(link);
3115 link = next;
3116 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003117 }
3118 if (type->contModel != NULL)
3119 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003120 xmlFree(type);
3121}
3122
3123/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003124 * xmlSchemaFreeModelGroupDef:
3125 * @item: a schema model group definition
3126 *
3127 * Deallocates a schema model group definition.
3128 */
3129static void
3130xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3131{
3132 if (item->annot != NULL)
3133 xmlSchemaFreeAnnot(item->annot);
3134 xmlFree(item);
3135}
3136
3137/**
3138 * xmlSchemaFreeModelGroup:
3139 * @item: a schema model group
3140 *
3141 * Deallocates a schema model group structure.
3142 */
3143static void
3144xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3145{
3146 if (item->annot != NULL)
3147 xmlSchemaFreeAnnot(item->annot);
3148 xmlFree(item);
3149}
3150
3151/**
3152 * xmlSchemaFreeParticle:
3153 * @type: a schema type structure
3154 *
3155 * Deallocate a Schema Type structure.
3156 */
3157static void
3158xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3159{
3160 if (item->annot != NULL)
3161 xmlSchemaFreeAnnot(item->annot);
3162 xmlFree(item);
3163}
3164
3165/**
3166 * xmlSchemaFreeMiscComponents:
3167 * @item: a schema component
3168 *
3169 * Deallocates misc. schema component structures.
3170 */
3171static void
3172xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3173{
3174 if (item == NULL)
3175 return;
3176 switch (item->type) {
3177 case XML_SCHEMA_TYPE_PARTICLE:
3178 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3179 return;
3180 case XML_SCHEMA_TYPE_SEQUENCE:
3181 case XML_SCHEMA_TYPE_CHOICE:
3182 case XML_SCHEMA_TYPE_ALL:
3183 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3184 return;
3185 case XML_SCHEMA_TYPE_ANY:
3186 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3187 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3188 break;
3189 default:
3190 /* TODO: This should never be hit. */
3191 TODO
3192 return;
3193 }
3194}
3195
3196static void
3197xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3198{
3199 if (schema->volatiles == NULL)
3200 return;
3201 {
3202 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3203 xmlSchemaTreeItemPtr item;
3204 int i;
3205
3206 for (i = 0; i < list->nbItems; i++) {
3207 if (list->items[i] != NULL) {
3208 item = (xmlSchemaTreeItemPtr) list->items[i];
3209 switch (item->type) {
3210 case XML_SCHEMA_EXTRA_QNAMEREF:
3211 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3212 break;
3213 default:
3214 xmlSchemaFreeMiscComponents(item);
3215 }
3216 }
3217 }
3218 if (list->items != NULL)
3219 xmlFree(list->items);
3220 xmlFree(list);
3221 }
3222}
3223/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003224 * xmlSchemaFreeTypeList:
3225 * @type: a schema type structure
3226 *
3227 * Deallocate a Schema Type structure.
3228 */
3229static void
3230xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3231{
3232 xmlSchemaTypePtr next;
3233
3234 while (type != NULL) {
3235 next = type->redef;
3236 xmlSchemaFreeType(type);
3237 type = next;
3238 }
3239}
3240
3241/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003242 * xmlSchemaFree:
3243 * @schema: a schema structure
3244 *
3245 * Deallocate a Schema structure.
3246 */
3247void
3248xmlSchemaFree(xmlSchemaPtr schema)
3249{
3250 if (schema == NULL)
3251 return;
3252
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003253 if (schema->volatiles != NULL)
3254 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003255 if (schema->notaDecl != NULL)
3256 xmlHashFree(schema->notaDecl,
3257 (xmlHashDeallocator) xmlSchemaFreeNotation);
3258 if (schema->attrDecl != NULL)
3259 xmlHashFree(schema->attrDecl,
3260 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3261 if (schema->attrgrpDecl != NULL)
3262 xmlHashFree(schema->attrgrpDecl,
3263 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3264 if (schema->elemDecl != NULL)
3265 xmlHashFree(schema->elemDecl,
3266 (xmlHashDeallocator) xmlSchemaFreeElement);
3267 if (schema->typeDecl != NULL)
3268 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003269 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003270 if (schema->groupDecl != NULL)
3271 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003272 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003273 if (schema->idcDef != NULL)
3274 xmlHashFree(schema->idcDef,
3275 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003276 if (schema->schemasImports != NULL)
3277 xmlHashFree(schema->schemasImports,
3278 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003279 if (schema->includes != NULL) {
3280 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3281 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003282 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003283 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003284 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003285 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003286 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003287 xmlFree(schema);
3288}
3289
3290/************************************************************************
3291 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003292 * Debug functions *
3293 * *
3294 ************************************************************************/
3295
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003296#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003297
Daniel Veillard4255d502002-04-16 15:50:10 +00003298/**
3299 * xmlSchemaElementDump:
3300 * @elem: an element
3301 * @output: the file output
3302 *
3303 * Dump the element
3304 */
3305static void
3306xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003307 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003308 const xmlChar * namespace ATTRIBUTE_UNUSED,
3309 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003310{
3311 if (elem == NULL)
3312 return;
3313
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003314 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3315 fprintf(output, "Particle: %s", name);
3316 fprintf(output, ", term element: %s", elem->ref);
3317 if (elem->refNs != NULL)
3318 fprintf(output, " ns %s", elem->refNs);
3319 } else {
3320 fprintf(output, "Element");
3321 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3322 fprintf(output, " (global)");
3323 fprintf(output, ": %s ", elem->name);
3324 if (namespace != NULL)
3325 fprintf(output, "ns %s", namespace);
3326 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003327 fprintf(output, "\n");
3328 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003329 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003330 if (elem->maxOccurs >= UNBOUNDED)
3331 fprintf(output, "max: unbounded\n");
3332 else if (elem->maxOccurs != 1)
3333 fprintf(output, "max: %d\n", elem->maxOccurs);
3334 else
3335 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003336 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003337 /*
3338 * Misc other properties.
3339 */
3340 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3341 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3342 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3343 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3344 (elem->id != NULL)) {
3345 fprintf(output, " props: ");
3346 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3347 fprintf(output, "[fixed] ");
3348 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3349 fprintf(output, "[default] ");
3350 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3351 fprintf(output, "[abstract] ");
3352 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3353 fprintf(output, "[nillable] ");
3354 if (elem->id != NULL)
3355 fprintf(output, "[id: '%s'] ", elem->id);
3356 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003357 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003358 /*
3359 * Default/fixed value.
3360 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003361 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003362 fprintf(output, " value: '%s'\n", elem->value);
3363 /*
3364 * Type.
3365 */
3366 if (elem->namedType != NULL) {
3367 fprintf(output, " type: %s ", elem->namedType);
3368 if (elem->namedTypeNs != NULL)
3369 fprintf(output, "ns %s\n", elem->namedTypeNs);
3370 else
3371 fprintf(output, "\n");
3372 }
3373 /*
3374 * Substitution group.
3375 */
3376 if (elem->substGroup != NULL) {
3377 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3378 if (elem->substGroupNs != NULL)
3379 fprintf(output, "ns %s\n", elem->substGroupNs);
3380 else
3381 fprintf(output, "\n");
3382 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003383}
3384
3385/**
3386 * xmlSchemaAnnotDump:
3387 * @output: the file output
3388 * @annot: a annotation
3389 *
3390 * Dump the annotation
3391 */
3392static void
3393xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3394{
3395 xmlChar *content;
3396
3397 if (annot == NULL)
3398 return;
3399
3400 content = xmlNodeGetContent(annot->content);
3401 if (content != NULL) {
3402 fprintf(output, " Annot: %s\n", content);
3403 xmlFree(content);
3404 } else
3405 fprintf(output, " Annot: empty\n");
3406}
3407
3408/**
3409 * xmlSchemaTypeDump:
3410 * @output: the file output
3411 * @type: a type structure
3412 *
3413 * Dump a SchemaType structure
3414 */
3415static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003416xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3417{
3418 xmlChar *str = NULL;
3419 xmlSchemaTreeItemPtr term;
3420 char shift[100];
3421 int i;
3422
3423 if (particle == NULL)
3424 return;
3425 for (i = 0;((i < depth) && (i < 25));i++)
3426 shift[2 * i] = shift[2 * i + 1] = ' ';
3427 shift[2 * i] = shift[2 * i + 1] = 0;
3428 fprintf(output, shift);
3429 if (particle->children == NULL) {
3430 fprintf(output, "MISSING particle term\n");
3431 return;
3432 }
3433 term = particle->children;
3434 switch (term->type) {
3435 case XML_SCHEMA_TYPE_ELEMENT:
3436 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
3437 ((xmlSchemaElementPtr)term)->targetNamespace,
3438 ((xmlSchemaElementPtr)term)->name));
3439 break;
3440 case XML_SCHEMA_TYPE_SEQUENCE:
3441 fprintf(output, "SEQUENCE");
3442 break;
3443 case XML_SCHEMA_TYPE_CHOICE:
3444 fprintf(output, "CHOICE");
3445 break;
3446 case XML_SCHEMA_TYPE_ALL:
3447 fprintf(output, "ALL");
3448 break;
3449 case XML_SCHEMA_TYPE_ANY:
3450 fprintf(output, "ANY");
3451 break;
3452 default:
3453 fprintf(output, "UNKNOWN\n");
3454 return;
3455 }
3456 if (particle->minOccurs != 1)
3457 fprintf(output, " min: %d", particle->minOccurs);
3458 if (particle->maxOccurs >= UNBOUNDED)
3459 fprintf(output, " max: unbounded");
3460 else if (particle->maxOccurs != 1)
3461 fprintf(output, " max: %d", particle->maxOccurs);
3462 fprintf(output, "\n");
3463 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3464 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3465 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3466 (term->children != NULL)) {
3467 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3468 output, depth +1);
3469 }
3470 if (particle->next != NULL)
3471 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3472 output, depth);
3473}
3474/**
3475 * xmlSchemaTypeDump:
3476 * @output: the file output
3477 * @type: a type structure
3478 *
3479 * Dump a SchemaType structure
3480 */
3481static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003482xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3483{
3484 if (type == NULL) {
3485 fprintf(output, "Type: NULL\n");
3486 return;
3487 }
3488 fprintf(output, "Type: ");
3489 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003490 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003491 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003492 fprintf(output, "no name ");
3493 if (type->targetNamespace != NULL)
3494 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003495 switch (type->type) {
3496 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003497 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003498 break;
3499 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003500 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003501 break;
3502 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003503 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003504 break;
3505 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003506 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003507 break;
3508 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003509 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003510 break;
3511 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003512 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003513 break;
3514 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003515 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003516 break;
3517 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003518 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003519 break;
3520 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003521 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003522 break;
3523 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003524 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003525 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003526 }
3527 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003528 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003529 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003530 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003531 break;
3532 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003533 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003534 break;
3535 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003536 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003537 break;
3538 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003539 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003540 break;
3541 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003542 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003543 break;
3544 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003545 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003546 break;
3547 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003548 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003549 break;
3550 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003551 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003552 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003553 }
3554 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003555 if (type->base != NULL) {
3556 fprintf(output, " base type: %s", type->base);
3557 if (type->baseNs != NULL)
3558 fprintf(output, " ns %s\n", type->baseNs);
3559 else
3560 fprintf(output, "\n");
3561 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003562 if (type->annot != NULL)
3563 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003564#ifdef DUMP_CONTENT_MODEL
3565 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3566 (type->subtypes != NULL)) {
3567 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3568 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003569 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003570#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003571}
3572
3573/**
3574 * xmlSchemaDump:
3575 * @output: the file output
3576 * @schema: a schema structure
3577 *
3578 * Dump a Schema structure.
3579 */
3580void
3581xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3582{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003583 if (output == NULL)
3584 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003585 if (schema == NULL) {
3586 fprintf(output, "Schemas: NULL\n");
3587 return;
3588 }
3589 fprintf(output, "Schemas: ");
3590 if (schema->name != NULL)
3591 fprintf(output, "%s, ", schema->name);
3592 else
3593 fprintf(output, "no name, ");
3594 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003595 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003596 else
3597 fprintf(output, "no target namespace");
3598 fprintf(output, "\n");
3599 if (schema->annot != NULL)
3600 xmlSchemaAnnotDump(output, schema->annot);
3601
3602 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3603 output);
3604 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003605 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003606}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003607
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003608#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003609/**
3610 * xmlSchemaDebugDumpIDCTable:
3611 * @vctxt: the WXS validation context
3612 *
3613 * Displays the current IDC table for debug purposes.
3614 */
3615static void
3616xmlSchemaDebugDumpIDCTable(FILE * output,
3617 const xmlChar *namespaceName,
3618 const xmlChar *localName,
3619 xmlSchemaPSVIIDCBindingPtr bind)
3620{
3621 xmlChar *str = NULL, *value;
3622 xmlSchemaPSVIIDCNodePtr tab;
3623 xmlSchemaPSVIIDCKeyPtr key;
3624 int i, j, res;
3625
3626 fprintf(output, "IDC: TABLES on %s\n",
3627 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
3628 FREE_AND_NULL(str)
3629
3630 if (bind == NULL)
3631 return;
3632 do {
3633 fprintf(output, "IDC: BINDING %s\n",
3634 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
3635 bind->definition->name));
3636 FREE_AND_NULL(str)
3637 for (i = 0; i < bind->nbNodes; i++) {
3638 tab = bind->nodeTable[i];
3639 fprintf(output, " ( ");
3640 for (j = 0; j < bind->definition->nbFields; j++) {
3641 key = tab->keys[j];
3642 if ((key != NULL) && (key->compValue != NULL)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003643 res = xmlSchemaGetCanonValue(key->compValue, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003644 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003645 fprintf(output, "\"%s\" ", value);
3646 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003647 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003648 if (res == 0)
3649 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003650 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003651 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003652 else
3653 fprintf(output, "(key missing), ");
3654 }
3655 fprintf(output, ")\n");
3656 }
3657 bind = bind->next;
3658 } while (bind != NULL);
3659}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003660#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003661#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003662
3663/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003664 * *
3665 * Utilities *
3666 * *
3667 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003668
Daniel Veillardc0826a72004-08-10 14:17:33 +00003669/**
3670 * xmlSchemaGetPropNode:
3671 * @node: the element node
3672 * @name: the name of the attribute
3673 *
3674 * Seeks an attribute with a name of @name in
3675 * no namespace.
3676 *
3677 * Returns the attribute or NULL if not present.
3678 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003679static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003680xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003681{
3682 xmlAttrPtr prop;
3683
Daniel Veillardc0826a72004-08-10 14:17:33 +00003684 if ((node == NULL) || (name == NULL))
3685 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003686 prop = node->properties;
3687 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003688 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3689 return(prop);
3690 prop = prop->next;
3691 }
3692 return (NULL);
3693}
3694
3695/**
3696 * xmlSchemaGetPropNodeNs:
3697 * @node: the element node
3698 * @uri: the uri
3699 * @name: the name of the attribute
3700 *
3701 * Seeks an attribute with a local name of @name and
3702 * a namespace URI of @uri.
3703 *
3704 * Returns the attribute or NULL if not present.
3705 */
3706static xmlAttrPtr
3707xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3708{
3709 xmlAttrPtr prop;
3710
3711 if ((node == NULL) || (name == NULL))
3712 return(NULL);
3713 prop = node->properties;
3714 while (prop != NULL) {
3715 if ((prop->ns != NULL) &&
3716 xmlStrEqual(prop->name, BAD_CAST name) &&
3717 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003718 return(prop);
3719 prop = prop->next;
3720 }
3721 return (NULL);
3722}
3723
3724static const xmlChar *
3725xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3726{
3727 xmlChar *val;
3728 const xmlChar *ret;
3729
3730 val = xmlNodeGetContent(node);
3731 if (val == NULL)
3732 return(NULL);
3733 ret = xmlDictLookup(ctxt->dict, val, -1);
3734 xmlFree(val);
3735 return(ret);
3736}
3737
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003738/**
3739 * xmlSchemaGetProp:
3740 * @ctxt: the parser context
3741 * @node: the node
3742 * @name: the property name
3743 *
3744 * Read a attribute value and internalize the string
3745 *
3746 * Returns the string or NULL if not present.
3747 */
3748static const xmlChar *
3749xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3750 const char *name)
3751{
3752 xmlChar *val;
3753 const xmlChar *ret;
3754
3755 val = xmlGetProp(node, BAD_CAST name);
3756 if (val == NULL)
3757 return(NULL);
3758 ret = xmlDictLookup(ctxt->dict, val, -1);
3759 xmlFree(val);
3760 return(ret);
3761}
3762
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003763/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003764 * *
3765 * Parsing functions *
3766 * *
3767 ************************************************************************/
3768
3769/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003770 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003771 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003772 * @name: the element name
3773 * @ns: the element namespace
3774 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003775 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003776 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003777 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003778 */
3779static xmlSchemaElementPtr
3780xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003781 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003782{
3783 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003784
3785 if ((name == NULL) || (schema == NULL))
3786 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003787
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003788 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003789 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003790 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003791 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003792 } else
3793 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003794 /*
3795 * This one was removed, since top level element declarations have
3796 * the target namespace specified in targetNamespace of the <schema>
3797 * information element, even if elementFormDefault is "unqualified".
3798 */
3799
3800 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003801 if (xmlStrEqual(namespace, schema->targetNamespace))
3802 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3803 else
3804 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003805 if ((ret != NULL) &&
3806 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003807 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003808 }
William M. Bracke7091952004-05-11 15:09:58 +00003809 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003810
William M. Brack2f2a6632004-08-20 23:09:47 +00003811 /*
3812 * Removed since imported components will be hold by the main schema only.
3813 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003814 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003815 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003816 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003817 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003818 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003819 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003820 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3821 return (ret);
3822 } else
3823 ret = NULL;
3824 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003825 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003826#ifdef DEBUG
3827 if (ret == NULL) {
3828 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003829 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003830 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003831 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003832 namespace);
3833 }
3834#endif
3835 return (ret);
3836}
3837
3838/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003839 * xmlSchemaGetType:
3840 * @schema: the schemas context
3841 * @name: the type name
3842 * @ns: the type namespace
3843 *
3844 * Lookup a type in the schemas or the predefined types
3845 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003846 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003847 */
3848static xmlSchemaTypePtr
3849xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003850 const xmlChar * namespace)
3851{
Daniel Veillard4255d502002-04-16 15:50:10 +00003852 xmlSchemaTypePtr ret;
3853
3854 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003855 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003856 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003857 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003858 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003859 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003860 }
3861 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003862 if (ret != NULL)
3863 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003864 /*
3865 * Removed, since the imported components will be grafted on the
3866 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003867 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003868 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003869 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003870 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003871 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003872 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003873 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3874 return (ret);
3875 } else
3876 ret = NULL;
3877 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003878 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003879#ifdef DEBUG
3880 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003881 if (namespace == NULL)
3882 fprintf(stderr, "Unable to lookup type %s", name);
3883 else
3884 fprintf(stderr, "Unable to lookup type %s:%s", name,
3885 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003886 }
3887#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003888 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003889}
3890
Daniel Veillard3646d642004-06-02 19:19:14 +00003891/**
3892 * xmlSchemaGetAttribute:
3893 * @schema: the context of the schema
3894 * @name: the name of the attribute
3895 * @ns: the target namespace of the attribute
3896 *
3897 * Lookup a an attribute in the schema or imported schemas
3898 *
3899 * Returns the attribute declaration or NULL if not found.
3900 */
3901static xmlSchemaAttributePtr
3902xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
3903 const xmlChar * namespace)
3904{
3905 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003906
3907 if ((name == NULL) || (schema == NULL))
3908 return (NULL);
3909
3910
3911 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
3912 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
3913 return (ret);
3914 else
3915 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003916 /*
3917 * Removed, since imported components will be hold by the main schema only.
3918 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003919 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003920 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003921 else
3922 import = xmlHashLookup(schema->schemasImports, namespace);
3923 if (import != NULL) {
3924 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
3925 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
3926 return (ret);
3927 } else
3928 ret = NULL;
3929 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003930 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003931#ifdef DEBUG
3932 if (ret == NULL) {
3933 if (namespace == NULL)
3934 fprintf(stderr, "Unable to lookup attribute %s", name);
3935 else
3936 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
3937 namespace);
3938 }
3939#endif
3940 return (ret);
3941}
3942
3943/**
3944 * xmlSchemaGetAttributeGroup:
3945 * @schema: the context of the schema
3946 * @name: the name of the attribute group
3947 * @ns: the target namespace of the attribute group
3948 *
3949 * Lookup a an attribute group in the schema or imported schemas
3950 *
3951 * Returns the attribute group definition or NULL if not found.
3952 */
3953static xmlSchemaAttributeGroupPtr
3954xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
3955 const xmlChar * namespace)
3956{
3957 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003958
3959 if ((name == NULL) || (schema == NULL))
3960 return (NULL);
3961
3962
3963 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
3964 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3965 return (ret);
3966 else
3967 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003968 /*
3969 * Removed since imported components will be hold by the main schema only.
3970 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003971 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003972 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003973 else
3974 import = xmlHashLookup(schema->schemasImports, namespace);
3975 if (import != NULL) {
3976 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
3977 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3978 return (ret);
3979 else
3980 ret = NULL;
3981 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003982 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003983#ifdef DEBUG
3984 if (ret == NULL) {
3985 if (namespace == NULL)
3986 fprintf(stderr, "Unable to lookup attribute group %s", name);
3987 else
3988 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
3989 namespace);
3990 }
3991#endif
3992 return (ret);
3993}
3994
3995/**
3996 * xmlSchemaGetGroup:
3997 * @schema: the context of the schema
3998 * @name: the name of the group
3999 * @ns: the target namespace of the group
4000 *
4001 * Lookup a group in the schema or imported schemas
4002 *
4003 * Returns the group definition or NULL if not found.
4004 */
4005static xmlSchemaTypePtr
4006xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4007 const xmlChar * namespace)
4008{
4009 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004010
4011 if ((name == NULL) || (schema == NULL))
4012 return (NULL);
4013
Daniel Veillard3646d642004-06-02 19:19:14 +00004014 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004015 /*
4016 * Removed since imported components will be hold by the main schema only.
4017 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004018 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004019 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004020 else
4021 import = xmlHashLookup(schema->schemasImports, namespace);
4022 if (import != NULL) {
4023 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4024 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4025 return (ret);
4026 else
4027 ret = NULL;
4028 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004029 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004030#ifdef DEBUG
4031 if (ret == NULL) {
4032 if (namespace == NULL)
4033 fprintf(stderr, "Unable to lookup group %s", name);
4034 else
4035 fprintf(stderr, "Unable to lookup group %s:%s", name,
4036 namespace);
4037 }
4038#endif
4039 return (ret);
4040}
4041
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004042/**
4043 * xmlSchemaGetNamedComponent:
4044 * @schema: the schema
4045 * @name: the name of the group
4046 * @ns: the target namespace of the group
4047 *
4048 * Lookup a group in the schema or imported schemas
4049 *
4050 * Returns the group definition or NULL if not found.
4051 */
4052static xmlSchemaTreeItemPtr
4053xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4054 xmlSchemaTypeType itemType,
4055 const xmlChar *name,
4056 const xmlChar *targetNs)
4057{
4058 switch (itemType) {
4059 case XML_SCHEMA_TYPE_GROUP:
4060 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4061 name, targetNs));
4062 case XML_SCHEMA_TYPE_ELEMENT:
4063 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4064 name, targetNs));
4065 default:
4066 return (NULL);
4067 }
4068}
4069
Daniel Veillard4255d502002-04-16 15:50:10 +00004070/************************************************************************
4071 * *
4072 * Parsing functions *
4073 * *
4074 ************************************************************************/
4075
4076#define IS_BLANK_NODE(n) \
4077 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
4078
4079/**
4080 * xmlSchemaIsBlank:
4081 * @str: a string
4082 *
4083 * Check if a string is ignorable
4084 *
4085 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4086 */
4087static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004088xmlSchemaIsBlank(xmlChar * str)
4089{
Daniel Veillard4255d502002-04-16 15:50:10 +00004090 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004091 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004092 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00004093 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004094 return (0);
4095 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004096 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004097 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004098}
4099
4100/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004101 * xmlSchemaAddAssembledItem:
4102 * @ctxt: a schema parser context
4103 * @schema: the schema being built
4104 * @item: the item
4105 *
4106 * Add a item to the schema's list of current items.
4107 * This is used if the schema was already constructed and
4108 * new schemata need to be added to it.
4109 * *WARNING* this interface is highly subject to change.
4110 *
4111 * Returns 0 if suceeds and -1 if an internal error occurs.
4112 */
4113static int
4114xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4115 xmlSchemaTypePtr item)
4116{
4117 static int growSize = 100;
4118 xmlSchemaAssemblePtr ass;
4119
4120 ass = ctxt->assemble;
4121 if (ass->sizeItems < 0) {
4122 /* If disabled. */
4123 return (0);
4124 }
4125 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004126 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004127 if (ass->items == NULL) {
4128 xmlSchemaPErrMemory(ctxt,
4129 "allocating new item buffer", NULL);
4130 return (-1);
4131 }
4132 ass->sizeItems = growSize;
4133 } else if (ass->sizeItems <= ass->nbItems) {
4134 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004135 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004136 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4137 if (ass->items == NULL) {
4138 xmlSchemaPErrMemory(ctxt,
4139 "growing item buffer", NULL);
4140 ass->sizeItems = 0;
4141 return (-1);
4142 }
4143 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004144 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004145 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4146 return (0);
4147}
4148
4149/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004150 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004151 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004152 * @schema: the schema being built
4153 * @name: the item name
4154 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004155 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004156 * *WARNING* this interface is highly subject to change
4157 *
4158 * Returns the new struture or NULL in case of error
4159 */
4160static xmlSchemaNotationPtr
4161xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004162 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004163{
4164 xmlSchemaNotationPtr ret = NULL;
4165 int val;
4166
4167 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4168 return (NULL);
4169
4170 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004171 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004172 if (schema->notaDecl == NULL)
4173 return (NULL);
4174
4175 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4176 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004177 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004178 return (NULL);
4179 }
4180 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004181 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004182 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4183 ret);
4184 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004185 /*
4186 * TODO: This should never happen, since a unique name will be computed.
4187 * If it fails, then an other internal error must have occured.
4188 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004189 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4190 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004191 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004192 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004193 xmlFree(ret);
4194 return (NULL);
4195 }
4196 return (ret);
4197}
4198
4199
4200/**
4201 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004202 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004203 * @schema: the schema being built
4204 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004205 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004206 *
4207 * Add an XML schema Attrribute declaration
4208 * *WARNING* this interface is highly subject to change
4209 *
4210 * Returns the new struture or NULL in case of error
4211 */
4212static xmlSchemaAttributePtr
4213xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004214 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004215 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004216{
4217 xmlSchemaAttributePtr ret = NULL;
4218 int val;
4219
4220 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4221 return (NULL);
4222
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004223#ifdef DEBUG
4224 fprintf(stderr, "Adding attribute %s\n", name);
4225 if (namespace != NULL)
4226 fprintf(stderr, " target namespace %s\n", namespace);
4227#endif
4228
Daniel Veillard4255d502002-04-16 15:50:10 +00004229 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004230 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004231 if (schema->attrDecl == NULL)
4232 return (NULL);
4233
4234 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4235 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004236 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004237 return (NULL);
4238 }
4239 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004240 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004241 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004242 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004243 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004244 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004245 if (topLevel) {
4246 xmlSchemaPCustomErr(ctxt,
4247 XML_SCHEMAP_REDEFINED_ATTR,
4248 NULL, NULL, node,
4249 "A global attribute declaration with the name '%s' does "
4250 "already exist", name);
4251 xmlFree(ret);
4252 return (NULL);
4253 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004254 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004255 /*
4256 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4257 * in the scenario:
4258 * 1. multiple top-level complex types have different target
4259 * namespaces but have the SAME NAME; this can happen if
4260 * schemata are imported
4261 * 2. those complex types contain attributes with an equal name
4262 * 3. those attributes are in no namespace
4263 * We will compute a new context string.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004264 */
4265 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004266 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004267 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004268
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004269 if (val != 0) {
4270 xmlSchemaPCustomErr(ctxt,
4271 XML_SCHEMAP_INTERNAL,
4272 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004273 "Internal error: xmlSchemaAddAttribute, "
4274 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004275 "could not be added to the hash.", name);
4276 xmlFree(ret);
4277 return (NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004278 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004279 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004280 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004281 if (ctxt->assemble != NULL)
4282 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004283 return (ret);
4284}
4285
4286/**
4287 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004288 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004289 * @schema: the schema being built
4290 * @name: the item name
4291 *
4292 * Add an XML schema Attrribute Group declaration
4293 *
4294 * Returns the new struture or NULL in case of error
4295 */
4296static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004297xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004298 xmlSchemaPtr schema, const xmlChar * name,
4299 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004300{
4301 xmlSchemaAttributeGroupPtr ret = NULL;
4302 int val;
4303
4304 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4305 return (NULL);
4306
4307 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004308 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004309 if (schema->attrgrpDecl == NULL)
4310 return (NULL);
4311
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004312 ret =
4313 (xmlSchemaAttributeGroupPtr)
4314 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004315 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004316 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004317 return (NULL);
4318 }
4319 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004320 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004321 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004322 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004323 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004324 xmlSchemaPCustomErr(ctxt,
4325 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4326 NULL, NULL, node,
4327 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004328 xmlFree(ret);
4329 return (NULL);
4330 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004331 if (ctxt->assemble != NULL)
4332 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004333 return (ret);
4334}
4335
4336/**
4337 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004338 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004339 * @schema: the schema being built
4340 * @name: the type name
4341 * @namespace: the type namespace
4342 *
4343 * Add an XML schema Element declaration
4344 * *WARNING* this interface is highly subject to change
4345 *
4346 * Returns the new struture or NULL in case of error
4347 */
4348static xmlSchemaElementPtr
4349xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004350 const xmlChar * name, const xmlChar * namespace,
4351 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004352{
4353 xmlSchemaElementPtr ret = NULL;
4354 int val;
4355
4356 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4357 return (NULL);
4358
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004359#ifdef DEBUG
4360 fprintf(stderr, "Adding element %s\n", name);
4361 if (namespace != NULL)
4362 fprintf(stderr, " target namespace %s\n", namespace);
4363#endif
4364
Daniel Veillard4255d502002-04-16 15:50:10 +00004365 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004366 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004367 if (schema->elemDecl == NULL)
4368 return (NULL);
4369
4370 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4371 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004372 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004373 return (NULL);
4374 }
4375 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004376 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004377 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004378 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004379 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004380 if (topLevel) {
4381 xmlSchemaPCustomErr(ctxt,
4382 XML_SCHEMAP_REDEFINED_ELEMENT,
4383 NULL, NULL, node,
4384 "A global element declaration with the name '%s' does "
4385 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004386 xmlFree(ret);
4387 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004388 } else {
4389 char buf[30];
4390
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004391 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004392 val = xmlHashAddEntry3(schema->elemDecl, name,
4393 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004394 if (val != 0) {
4395 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004396 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004397 NULL, NULL, node,
4398 "Internal error: xmlSchemaAddElement, "
4399 "a dublicate element declaration with the name '%s' "
4400 "could not be added to the hash.", name);
4401 xmlFree(ret);
4402 return (NULL);
4403 }
4404 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004405
Daniel Veillard4255d502002-04-16 15:50:10 +00004406 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004407 if (ctxt->assemble != NULL)
4408 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004409 return (ret);
4410}
4411
4412/**
4413 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004414 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004415 * @schema: the schema being built
4416 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004417 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004418 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004419 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004420 * *WARNING* this interface is highly subject to change
4421 *
4422 * Returns the new struture or NULL in case of error
4423 */
4424static xmlSchemaTypePtr
4425xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004426 const xmlChar * name, const xmlChar * namespace,
4427 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004428{
4429 xmlSchemaTypePtr ret = NULL;
4430 int val;
4431
4432 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4433 return (NULL);
4434
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004435#ifdef DEBUG
4436 fprintf(stderr, "Adding type %s\n", name);
4437 if (namespace != NULL)
4438 fprintf(stderr, " target namespace %s\n", namespace);
4439#endif
4440
Daniel Veillard4255d502002-04-16 15:50:10 +00004441 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004442 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004443 if (schema->typeDecl == NULL)
4444 return (NULL);
4445
4446 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4447 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004448 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004449 return (NULL);
4450 }
4451 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004452 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004453 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004454 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004455 if (val != 0) {
4456 if (ctxt->includes == 0) {
4457 xmlSchemaPCustomErr(ctxt,
4458 XML_SCHEMAP_REDEFINED_TYPE,
4459 NULL, NULL, node,
4460 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004461 xmlFree(ret);
4462 return (NULL);
4463 } else {
4464 xmlSchemaTypePtr prev;
4465
4466 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4467 if (prev == NULL) {
4468 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004469 XML_ERR_INTERNAL_ERROR,
4470 "Internal error: xmlSchemaAddType, on type "
4471 "'%s'.\n",
4472 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004473 xmlFree(ret);
4474 return (NULL);
4475 }
4476 ret->redef = prev->redef;
4477 prev->redef = ret;
4478 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004479 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004480 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004481 ret->minOccurs = 1;
4482 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004483 ret->attributeUses = NULL;
4484 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004485 if (ctxt->assemble != NULL)
4486 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004487 return (ret);
4488}
4489
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004490static xmlSchemaQNameRefPtr
4491xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4492 xmlSchemaTypeType refType,
4493 const xmlChar *refName,
4494 const xmlChar *refNs)
4495{
4496 xmlSchemaQNameRefPtr ret;
4497
4498 ret = (xmlSchemaQNameRefPtr)
4499 xmlMalloc(sizeof(xmlSchemaQNameRef));
4500 if (ret == NULL) {
4501 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4502 NULL);
4503 return (NULL);
4504 }
4505 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4506 ret->name = refName;
4507 ret->targetNamespace = refNs;
4508 ret->item = NULL;
4509 ret->itemType = refType;
4510 /*
4511 * Store the reference item in the schema.
4512 */
4513 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4514 return (ret);
4515}
4516
4517/**
4518 * xmlSchemaAddModelGroup:
4519 * @ctxt: a schema parser context
4520 * @schema: the schema being built
4521 * @type: the "compositor" type of the model group
4522 * @container: the internal component name
4523 * @node: the node in the schema doc
4524 *
4525 * Adds a schema model group
4526 * *WARNING* this interface is highly subject to change
4527 *
4528 * Returns the new struture or NULL in case of error
4529 */
4530static xmlSchemaModelGroupPtr
4531xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4532 xmlSchemaTypeType type, const xmlChar **container,
4533 xmlNodePtr node)
4534{
4535 xmlSchemaModelGroupPtr ret = NULL;
4536 xmlChar buf[30];
4537
4538 if ((ctxt == NULL) || (schema == NULL))
4539 return (NULL);
4540
4541#ifdef DEBUG
4542 fprintf(stderr, "Adding model group component\n");
4543#endif
4544 ret = (xmlSchemaModelGroupPtr)
4545 xmlMalloc(sizeof(xmlSchemaModelGroup));
4546 if (ret == NULL) {
4547 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4548 NULL);
4549 return (NULL);
4550 }
4551 ret->type = type;
4552 ret->annot = NULL;
4553 ret->node = node;
4554 ret->children = NULL;
4555 ret->next = NULL;
4556 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4557 if (container != NULL)
4558 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4559 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
4560 if (container != NULL)
4561 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4562 } else {
4563 if (container != NULL)
4564 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4565 }
4566 if (container != NULL)
4567 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4568 /*
4569 * Add to volatile items.
4570 * TODO: this should be changed someday.
4571 */
4572 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4573 xmlFree(ret);
4574 return (NULL);
4575 }
4576 return (ret);
4577}
4578
4579
4580/**
4581 * xmlSchemaAddParticle:
4582 * @ctxt: a schema parser context
4583 * @schema: the schema being built
4584 * @node: the corresponding node in the schema doc
4585 * @min: the minOccurs
4586 * @max: the maxOccurs
4587 *
4588 * Adds an XML schema particle component.
4589 * *WARNING* this interface is highly subject to change
4590 *
4591 * Returns the new struture or NULL in case of error
4592 */
4593static xmlSchemaParticlePtr
4594xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4595 xmlNodePtr node, int min, int max)
4596{
4597 xmlSchemaParticlePtr ret = NULL;
4598 if ((ctxt == NULL) || (schema == NULL))
4599 return (NULL);
4600
4601#ifdef DEBUG
4602 fprintf(stderr, "Adding particle component\n");
4603#endif
4604 ret = (xmlSchemaParticlePtr)
4605 xmlMalloc(sizeof(xmlSchemaParticle));
4606 if (ret == NULL) {
4607 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4608 NULL);
4609 return (NULL);
4610 }
4611 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4612 ret->annot = NULL;
4613 ret->node = node;
4614 ret->minOccurs = min;
4615 ret->maxOccurs = max;
4616 ret->next = NULL;
4617 ret->children = NULL;
4618
4619 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4620 xmlFree(ret);
4621 return (NULL);
4622 }
4623 return (ret);
4624}
4625
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004626/**
4627 * xmlSchemaAddGroup:
4628 * @ctxt: a schema validation context
4629 * @schema: the schema being built
4630 * @name: the group name
4631 *
4632 * Add an XML schema Group definition
4633 *
4634 * Returns the new struture or NULL in case of error
4635 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004636static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004637xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004638 const xmlChar *name, const xmlChar *namespaceName,
4639 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004640{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004641 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004642 int val;
4643
4644 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4645 return (NULL);
4646
4647 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004648 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004649 if (schema->groupDecl == NULL)
4650 return (NULL);
4651
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004652 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004653 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004654 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004655 return (NULL);
4656 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004657 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004658 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004659 ret->type = XML_SCHEMA_TYPE_GROUP;
4660 ret->node = node;
4661 ret->targetNamespace = namespaceName;
4662 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004663 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004664 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004665 XML_SCHEMAP_REDEFINED_GROUP,
4666 NULL, NULL, node,
4667 "A global model group definition with the name '%s' does already "
4668 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004669 xmlFree(ret);
4670 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004671 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004672 if (ctxt->assemble != NULL)
4673 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004674 return (ret);
4675}
4676
Daniel Veillard3646d642004-06-02 19:19:14 +00004677/**
4678 * xmlSchemaNewWildcardNs:
4679 * @ctxt: a schema validation context
4680 *
4681 * Creates a new wildcard namespace constraint.
4682 *
4683 * Returns the new struture or NULL in case of error
4684 */
4685static xmlSchemaWildcardNsPtr
4686xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4687{
4688 xmlSchemaWildcardNsPtr ret;
4689
4690 ret = (xmlSchemaWildcardNsPtr)
4691 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4692 if (ret == NULL) {
4693 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
4694 return (NULL);
4695 }
4696 ret->value = NULL;
4697 ret->next = NULL;
4698 return (ret);
4699}
4700
4701/**
4702 * xmlSchemaAddWildcard:
4703 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004704 * @schema: a schema
4705 *
4706 * Adds a wildcard.
4707 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004708 *
4709 * Returns the new struture or NULL in case of error
4710 */
4711static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004712xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4713 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004714{
4715 xmlSchemaWildcardPtr ret = NULL;
4716
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004717 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004718 return (NULL);
4719
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004720#ifdef DEBUG
4721 fprintf(stderr, "Adding wildcard component\n");
4722#endif
4723
Daniel Veillard3646d642004-06-02 19:19:14 +00004724 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4725 if (ret == NULL) {
4726 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4727 return (NULL);
4728 }
4729 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004730 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004731 ret->minOccurs = 1;
4732 ret->maxOccurs = 1;
4733
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004734 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4735 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4736 "Failed to add a wildcard component to the list", NULL);
4737 xmlFree(ret);
4738 return (NULL);
4739 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004740 return (ret);
4741}
4742
Daniel Veillard4255d502002-04-16 15:50:10 +00004743/************************************************************************
4744 * *
4745 * Utilities for parsing *
4746 * *
4747 ************************************************************************/
4748
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004749#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004750/**
4751 * xmlGetQNameProp:
4752 * @ctxt: a schema validation context
4753 * @node: a subtree containing XML Schema informations
4754 * @name: the attribute name
4755 * @namespace: the result namespace if any
4756 *
4757 * Extract a QName Attribute value
4758 *
4759 * Returns the NCName or NULL if not found, and also update @namespace
4760 * with the namespace URI
4761 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004762static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004763xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004764 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004765{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004766 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004767 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004768 const xmlChar *ret, *prefix;
4769 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004770 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004771
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004772 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004773 attr = xmlSchemaGetPropNode(node, name);
4774 if (attr == NULL)
4775 return (NULL);
4776 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004777
Daniel Veillard4255d502002-04-16 15:50:10 +00004778 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004779 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004780
Daniel Veillardba0153a2004-04-01 10:42:31 +00004781 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004782 ns = xmlSearchNs(node->doc, node, 0);
4783 if (ns) {
4784 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4785 return (val);
4786 }
4787 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004788 ret = xmlSplitQName3(val, &len);
4789 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004790 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004791 }
4792 ret = xmlDictLookup(ctxt->dict, ret, -1);
4793 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004794
4795 ns = xmlSearchNs(node->doc, node, prefix);
4796 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004797 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4798 NULL, NULL, (xmlNodePtr) attr,
4799 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004800 "The QName value '%s' has no corresponding namespace "
4801 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004802 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004803 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004804 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004805 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004806}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004807#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004808
4809/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004810 * xmlSchemaPValAttrNodeQNameValue:
4811 * @ctxt: a schema parser context
4812 * @schema: the schema context
4813 * @ownerDes: the designation of the parent element
4814 * @ownerItem: the parent as a schema object
4815 * @value: the QName value
4816 * @local: the resulting local part if found, the attribute value otherwise
4817 * @uri: the resulting namespace URI if found
4818 *
4819 * Extracts the local name and the URI of a QName value and validates it.
4820 * This one is intended to be used on attribute values that
4821 * should resolve to schema components.
4822 *
4823 * Returns 0, in case the QName is valid, a positive error code
4824 * if not valid and -1 if an internal error occurs.
4825 */
4826static int
4827xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
4828 xmlSchemaPtr schema,
4829 xmlChar **ownerDes,
4830 xmlSchemaTypePtr ownerItem,
4831 xmlAttrPtr attr,
4832 const xmlChar *value,
4833 const xmlChar **uri,
4834 const xmlChar **prefix,
4835 const xmlChar **local)
4836{
4837 const xmlChar *pref;
4838 xmlNsPtr ns;
4839 int len, ret;
4840
4841 *uri = NULL;
4842 *local = NULL;
4843 if (prefix != 0)
4844 *prefix = NULL;
4845 ret = xmlValidateQName(value, 1);
4846 if (ret > 0) {
4847 xmlSchemaPSimpleTypeErr(ctxt,
4848 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4849 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004850 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4851 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004852 NULL, NULL, NULL);
4853 *local = value;
4854 return (ctxt->err);
4855 } else if (ret < 0)
4856 return (-1);
4857
4858 if (!strchr((char *) value, ':')) {
4859 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4860 if (ns)
4861 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4862 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4863 /*
4864 * This one takes care of included schemas with no
4865 * target namespace.
4866 */
4867 *uri = schema->targetNamespace;
4868 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004869 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004870 return (0);
4871 }
4872 /*
4873 * At this point xmlSplitQName3 has to return a local name.
4874 */
4875 *local = xmlSplitQName3(value, &len);
4876 *local = xmlDictLookup(ctxt->dict, *local, -1);
4877 pref = xmlDictLookup(ctxt->dict, value, len);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004878 if (prefix != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00004879 *prefix = pref;
4880 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4881 if (ns == NULL) {
4882 xmlSchemaPSimpleTypeErr(ctxt,
4883 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4884 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004885 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
4886 "The QName value '%s' has no corresponding namespace "
4887 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004888 return (ctxt->err);
4889 } else {
4890 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4891 }
4892 return (0);
4893}
4894
4895/**
4896 * xmlSchemaPValAttrNodeQName:
4897 * @ctxt: a schema parser context
4898 * @schema: the schema context
4899 * @ownerDes: the designation of the owner element
4900 * @ownerItem: the owner as a schema object
4901 * @attr: the attribute node
4902 * @local: the resulting local part if found, the attribute value otherwise
4903 * @uri: the resulting namespace URI if found
4904 *
4905 * Extracts and validates the QName of an attribute value.
4906 * This one is intended to be used on attribute values that
4907 * should resolve to schema components.
4908 *
4909 * Returns 0, in case the QName is valid, a positive error code
4910 * if not valid and -1 if an internal error occurs.
4911 */
4912static int
4913xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
4914 xmlSchemaPtr schema,
4915 xmlChar **ownerDes,
4916 xmlSchemaTypePtr ownerItem,
4917 xmlAttrPtr attr,
4918 const xmlChar **uri,
4919 const xmlChar **prefix,
4920 const xmlChar **local)
4921{
4922 const xmlChar *value;
4923
4924 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4925 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
4926 ownerDes, ownerItem, attr, value, uri, prefix, local));
4927}
4928
4929/**
4930 * xmlSchemaPValAttrQName:
4931 * @ctxt: a schema parser context
4932 * @schema: the schema context
4933 * @ownerDes: the designation of the parent element
4934 * @ownerItem: the owner as a schema object
4935 * @ownerElem: the parent node of the attribute
4936 * @name: the name of the attribute
4937 * @local: the resulting local part if found, the attribute value otherwise
4938 * @uri: the resulting namespace URI if found
4939 *
4940 * Extracts and validates the QName of an attribute value.
4941 *
4942 * Returns 0, in case the QName is valid, a positive error code
4943 * if not valid and -1 if an internal error occurs.
4944 */
4945static int
4946xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
4947 xmlSchemaPtr schema,
4948 xmlChar **ownerDes,
4949 xmlSchemaTypePtr ownerItem,
4950 xmlNodePtr ownerElem,
4951 const char *name,
4952 const xmlChar **uri,
4953 const xmlChar **prefix,
4954 const xmlChar **local)
4955{
4956 xmlAttrPtr attr;
4957
4958 attr = xmlSchemaGetPropNode(ownerElem, name);
4959 if (attr == NULL) {
4960 *local = NULL;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004961 if (prefix != NULL)
4962 *prefix = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004963 *uri = NULL;
4964 return (0);
4965 }
4966 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
4967 ownerDes, ownerItem, attr, uri, prefix, local));
4968}
4969
4970/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004971 * xmlSchemaPValAttrID:
4972 * @ctxt: a schema parser context
4973 * @schema: the schema context
4974 * @ownerDes: the designation of the parent element
4975 * @ownerItem: the owner as a schema object
4976 * @ownerElem: the parent node of the attribute
4977 * @name: the name of the attribute
4978 *
4979 * Extracts and validates the ID of an attribute value.
4980 *
4981 * Returns 0, in case the ID is valid, a positive error code
4982 * if not valid and -1 if an internal error occurs.
4983 */
4984static int
4985xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
4986 xmlChar **ownerDes,
4987 xmlSchemaTypePtr ownerItem,
4988 xmlNodePtr ownerElem,
4989 const xmlChar *name)
4990{
4991 int ret;
4992 xmlChar *value;
4993 xmlAttrPtr attr;
4994
4995 value = xmlGetNoNsProp(ownerElem, name);
4996 if (value == NULL)
4997 return (0);
4998
4999 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5000 if (attr == NULL)
5001 return (-1);
5002
5003 ret = xmlValidateNCName(BAD_CAST value, 1);
5004 if (ret == 0) {
5005 /*
5006 * NOTE: the IDness might have already be declared in the DTD
5007 */
5008 if (attr->atype != XML_ATTRIBUTE_ID) {
5009 xmlIDPtr res;
5010 xmlChar *strip;
5011
5012 /*
5013 * TODO: Use xmlSchemaStrip here; it's not exported at this
5014 * moment.
5015 */
5016 strip = xmlSchemaCollapseString(BAD_CAST value);
5017 if (strip != NULL)
5018 value = strip;
5019 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5020 if (res == NULL) {
5021 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5022 xmlSchemaPSimpleTypeErr(ctxt,
5023 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5024 ownerDes, ownerItem, (xmlNodePtr) attr,
5025 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00005026 NULL, NULL, "The ID '%s' is already defined",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005027 BAD_CAST value, NULL);
5028 } else
5029 attr->atype = XML_ATTRIBUTE_ID;
5030 if (strip != NULL)
5031 xmlFree(strip);
5032 }
5033 } else if (ret > 0) {
5034 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5035 xmlSchemaPSimpleTypeErr(ctxt,
5036 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5037 ownerDes, ownerItem, (xmlNodePtr) attr,
5038 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5039 NULL, BAD_CAST value, NULL, NULL, NULL);
5040 }
5041 xmlFree(value);
5042
5043 return (ret);
5044}
5045
5046/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005047 * xmlGetMaxOccurs:
5048 * @ctxt: a schema validation context
5049 * @node: a subtree containing XML Schema informations
5050 *
5051 * Get the maxOccurs property
5052 *
5053 * Returns the default if not found, or the value
5054 */
5055static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005056xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5057 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005058{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005059 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005060 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005061 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005062
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005063 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5064 if (attr == NULL)
5065 return (def);
5066 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005067
5068 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005069 if (max != UNBOUNDED) {
5070 xmlSchemaPSimpleTypeErr(ctxt,
5071 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5072 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5073 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5074 val, NULL, NULL, NULL);
5075 return (def);
5076 } else
5077 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005078 }
5079
5080 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005081 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005082 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005083 if (*cur == 0) {
5084 xmlSchemaPSimpleTypeErr(ctxt,
5085 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5086 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5087 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5088 val, NULL, NULL, NULL);
5089 return (def);
5090 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005091 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005092 ret = ret * 10 + (*cur - '0');
5093 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005094 }
William M. Brack76e95df2003-10-18 16:20:14 +00005095 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005096 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005097 /*
5098 * TODO: Restrict the maximal value to Integer.
5099 */
5100 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
5101 xmlSchemaPSimpleTypeErr(ctxt,
5102 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5103 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5104 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5105 val, NULL, NULL, NULL);
5106 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005107 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005108 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005109}
5110
5111/**
5112 * xmlGetMinOccurs:
5113 * @ctxt: a schema validation context
5114 * @node: a subtree containing XML Schema informations
5115 *
5116 * Get the minOccurs property
5117 *
5118 * Returns the default if not found, or the value
5119 */
5120static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005121xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5122 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005123{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005124 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005125 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005126 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005127
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005128 attr = xmlSchemaGetPropNode(node, "minOccurs");
5129 if (attr == NULL)
5130 return (def);
5131 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005132 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005133 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005134 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005135 if (*cur == 0) {
5136 xmlSchemaPSimpleTypeErr(ctxt,
5137 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5138 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5139 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5140 val, NULL, NULL, NULL);
5141 return (def);
5142 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005143 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005144 ret = ret * 10 + (*cur - '0');
5145 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005146 }
William M. Brack76e95df2003-10-18 16:20:14 +00005147 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005148 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005149 /*
5150 * TODO: Restrict the maximal value to Integer.
5151 */
5152 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
5153 xmlSchemaPSimpleTypeErr(ctxt,
5154 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5155 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5156 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
5157 val, NULL, NULL, NULL);
5158 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005159 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005160 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005161}
5162
5163/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005164 * xmlSchemaPGetBoolNodeValue:
5165 * @ctxt: a schema validation context
5166 * @ownerDes: owner designation
5167 * @ownerItem: the owner as a schema item
5168 * @node: the node holding the value
5169 *
5170 * Converts a boolean string value into 1 or 0.
5171 *
5172 * Returns 0 or 1.
5173 */
5174static int
5175xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5176 xmlChar **ownerDes,
5177 xmlSchemaTypePtr ownerItem,
5178 xmlNodePtr node)
5179{
5180 xmlChar *value = NULL;
5181 int res = 0;
5182
5183 value = xmlNodeGetContent(node);
5184 /*
5185 * 3.2.2.1 Lexical representation
5186 * An instance of a datatype that is defined as ·boolean·
5187 * can have the following legal literals {true, false, 1, 0}.
5188 */
5189 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5190 res = 1;
5191 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5192 res = 0;
5193 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5194 res = 1;
5195 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
5196 res = 0;
5197 else {
5198 xmlSchemaPSimpleTypeErr(ctxt,
5199 XML_SCHEMAP_INVALID_BOOLEAN,
5200 ownerDes, ownerItem, node,
5201 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5202 "(1 | 0 | true | false)", BAD_CAST value,
5203 NULL, NULL, NULL);
5204 }
5205 if (value != NULL)
5206 xmlFree(value);
5207 return (res);
5208}
5209
5210/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005211 * xmlGetBooleanProp:
5212 * @ctxt: a schema validation context
5213 * @node: a subtree containing XML Schema informations
5214 * @name: the attribute name
5215 * @def: the default value
5216 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005217 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005218 *
5219 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005220 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005221 */
5222static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00005223xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5224 xmlChar **ownerDes,
5225 xmlSchemaTypePtr ownerItem,
5226 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005227 const char *name, int def)
5228{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005229 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005230
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005231 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005232 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005233 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005234 /*
5235 * 3.2.2.1 Lexical representation
5236 * An instance of a datatype that is defined as ·boolean·
5237 * can have the following legal literals {true, false, 1, 0}.
5238 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005239 if (xmlStrEqual(val, BAD_CAST "true"))
5240 def = 1;
5241 else if (xmlStrEqual(val, BAD_CAST "false"))
5242 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005243 else if (xmlStrEqual(val, BAD_CAST "1"))
5244 def = 1;
5245 else if (xmlStrEqual(val, BAD_CAST "0"))
5246 def = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005247 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005248 xmlSchemaPSimpleTypeErr(ctxt,
5249 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005250 ownerDes, ownerItem,
5251 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
William M. Brack2f2a6632004-08-20 23:09:47 +00005252 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5253 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005254 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005255 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005256}
5257
5258/************************************************************************
5259 * *
5260 * Shema extraction from an Infoset *
5261 * *
5262 ************************************************************************/
5263static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5264 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005265 xmlNodePtr node,
5266 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005267static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5268 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005269 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005270 xmlNodePtr node,
5271 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005272static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5273 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005274 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005275 xmlNodePtr node,
5276 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005277static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5278 ctxt,
5279 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005280 xmlNodePtr node,
5281 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005282static xmlSchemaAttributeGroupPtr
5283xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005284 xmlSchemaPtr schema, xmlNodePtr node,
5285 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005286static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5287 xmlSchemaPtr schema,
5288 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005289static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005290xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5291 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005292
5293/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005294 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005295 *
5296 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005297 * @ownerDes: the designation of the parent element
5298 * @ownerItem: the schema object owner if existent
5299 * @attr: the schema attribute node being validated
5300 * @value: the value
5301 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005302 *
5303 * Validates a value against the given built-in type.
5304 * This one is intended to be used internally for validation
5305 * of schema attribute values during parsing of the schema.
5306 *
5307 * Returns 0 if the value is valid, a positive error code
5308 * number otherwise and -1 in case of an internal or API error.
5309 */
5310static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00005311xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
5312 xmlChar **ownerDes,
5313 xmlSchemaTypePtr ownerItem,
5314 xmlAttrPtr attr,
5315 const xmlChar *value,
5316 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005317{
Daniel Veillard01fa6152004-06-29 17:04:39 +00005318
Daniel Veillardc0826a72004-08-10 14:17:33 +00005319 int ret = 0;
5320
5321 /*
5322 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5323 * one is really meant to be used internally, so better not.
5324 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005325 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005326 return (-1);
5327 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5328 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005329 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005330 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005331 "type '%s' is not a built-in type.\n",
5332 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005333 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005334 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005335 switch (type->builtInType) {
5336 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005337 case XML_SCHEMAS_QNAME:
5338 case XML_SCHEMAS_ANYURI:
5339 case XML_SCHEMAS_TOKEN:
5340 case XML_SCHEMAS_LANGUAGE:
5341 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
5342 break;
5343
5344 /*
5345 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00005346 ret = xmlValidateNCName(value, 1);
5347 break;
5348 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00005349 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005350 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005351 "Internal error: xmlSchemaPvalueAttrNode, use "
5352 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
5353 "for extracting QName valueues instead.\n",
5354 NULL, NULL);
5355 return (-1);
5356 case XML_SCHEMAS_ANYURI:
5357 if (value != NULL) {
5358 xmlURIPtr uri = xmlParseURI((const char *) value);
5359 if (uri == NULL)
5360 ret = 1;
5361 else
5362 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00005363 }
5364 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005365 case XML_SCHEMAS_TOKEN: {
5366 const xmlChar *cur = value;
5367
5368 if (IS_BLANK_CH(*cur)) {
5369 ret = 1;
5370 } else while (*cur != 0) {
5371 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
5372 ret = 1;
5373 break;
5374 } else if (*cur == ' ') {
5375 cur++;
5376 if ((*cur == 0) || (*cur == ' ')) {
5377 ret = 1;
5378 break;
5379 }
5380 } else {
5381 cur++;
5382 }
5383 }
5384 }
5385 break;
5386 case XML_SCHEMAS_LANGUAGE:
5387 if (xmlCheckLanguageID(value) != 1)
5388 ret = 1;
5389 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005390 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00005391 default: {
5392 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005393 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005394 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00005395 "valueidation using the type '%s' is not implemented "
5396 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00005397 type->name, NULL);
5398 return (-1);
5399 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005400 }
5401 /*
5402 * TODO: Should we use the S4S error codes instead?
5403 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005404 if (ret < 0) {
5405 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
5406 XML_SCHEMAP_INTERNAL,
5407 "Internal error: xmlSchemaPValAttrNodeValue, "
5408 "failed to validate a schema attribute value.\n",
5409 NULL, NULL);
5410 return (-1);
5411 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005412 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
5413 xmlSchemaPSimpleTypeErr(ctxt,
5414 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
5415 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005416 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005417 NULL, NULL, NULL);
5418 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
5419 } else {
5420 xmlSchemaPSimpleTypeErr(ctxt,
5421 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
5422 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005423 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005424 NULL, NULL, NULL);
5425 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
5426 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005427 }
5428 return (ret);
5429}
5430
5431/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005432 * xmlSchemaPValAttrNode:
5433 *
5434 * @ctxt: a schema parser context
5435 * @ownerDes: the designation of the parent element
5436 * @ownerItem: the schema object owner if existent
5437 * @attr: the schema attribute node being validated
5438 * @type: the built-in type to be validated against
5439 * @value: the resulting value if any
5440 *
5441 * Extracts and validates a value against the given built-in type.
5442 * This one is intended to be used internally for validation
5443 * of schema attribute values during parsing of the schema.
5444 *
5445 * Returns 0 if the value is valid, a positive error code
5446 * number otherwise and -1 in case of an internal or API error.
5447 */
5448static int
5449xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5450 xmlChar **ownerDes,
5451 xmlSchemaTypePtr ownerItem,
5452 xmlAttrPtr attr,
5453 xmlSchemaTypePtr type,
5454 const xmlChar **value)
5455{
5456 const xmlChar *val;
5457
5458 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
5459 return (-1);
5460
5461 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5462 if (value != NULL)
5463 *value = val;
5464
5465 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
5466 val, type));
5467}
5468
5469/**
5470 * xmlSchemaPValAttr:
5471 *
5472 * @ctxt: a schema parser context
5473 * @node: the element node of the attribute
5474 * @ownerDes: the designation of the parent element
5475 * @ownerItem: the schema object owner if existent
5476 * @ownerElem: the owner element node
5477 * @name: the name of the schema attribute node
5478 * @type: the built-in type to be validated against
5479 * @value: the resulting value if any
5480 *
5481 * Extracts and validates a value against the given built-in type.
5482 * This one is intended to be used internally for validation
5483 * of schema attribute values during parsing of the schema.
5484 *
5485 * Returns 0 if the value is valid, a positive error code
5486 * number otherwise and -1 in case of an internal or API error.
5487 */
5488static int
5489xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
5490 xmlChar **ownerDes,
5491 xmlSchemaTypePtr ownerItem,
5492 xmlNodePtr ownerElem,
5493 const char *name,
5494 xmlSchemaTypePtr type,
5495 const xmlChar **value)
5496{
5497 xmlAttrPtr attr;
5498
5499 if ((ctxt == NULL) || (type == NULL)) {
5500 if (value != NULL)
5501 *value = NULL;
5502 return (-1);
5503 }
5504 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5505 if (value != NULL)
5506 *value = NULL;
5507 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005508 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005509 "Internal error: xmlSchemaPValAttr, the given "
5510 "type '%s' is not a built-in type.\n",
5511 type->name, NULL);
5512 return (-1);
5513 }
5514 attr = xmlSchemaGetPropNode(ownerElem, name);
5515 if (attr == NULL) {
5516 if (value != NULL)
5517 *value = NULL;
5518 return (0);
5519 }
5520 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
5521 type, value));
5522}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005523
5524static int
5525xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5526 xmlSchemaPtr schema,
5527 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005528 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005529 const xmlChar *namespaceName)
5530{
5531 if (xmlStrEqual(schema->targetNamespace, namespaceName))
5532 return (1);
5533 if (pctxt->localImports != NULL) {
5534 int i;
5535 for (i = 0; i < pctxt->nbLocalImports; i++)
5536 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5537 return (1);
5538 }
5539 if (namespaceName == NULL)
5540 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005541 NULL, (xmlSchemaTypePtr) item, node,
5542 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005543 "namespace are not valid, since not indicated by an import "
5544 "statement", NULL);
5545 else
5546 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005547 NULL, (xmlSchemaTypePtr) item, node,
5548 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005549 "namespace '%s' are not valid, since not indicated by an import "
5550 "statement", namespaceName);
5551 return (0);
5552}
5553
Daniel Veillardc0826a72004-08-10 14:17:33 +00005554/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005555 * xmlSchemaParseAttrDecls:
5556 * @ctxt: a schema validation context
5557 * @schema: the schema being built
5558 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005559 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005560 *
5561 * parse a XML schema attrDecls declaration corresponding to
5562 * <!ENTITY % attrDecls
5563 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5564 */
5565static xmlNodePtr
5566xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5567 xmlNodePtr child, xmlSchemaTypePtr type)
5568{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005569 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005570
Daniel Veillard4255d502002-04-16 15:50:10 +00005571 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005572 (IS_SCHEMA(child, "attributeGroup"))) {
5573 attr = NULL;
5574 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005575 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005576 } else if (IS_SCHEMA(child, "attributeGroup")) {
5577 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005578 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005579 }
5580 if (attr != NULL) {
5581 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005582 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5583 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5584 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005585 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005586 lastattr = attr;
5587 } else {
5588 lastattr->next = attr;
5589 lastattr = attr;
5590 }
5591 }
5592 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005593 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005594 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005595}
5596
5597/**
5598 * xmlSchemaParseAnnotation:
5599 * @ctxt: a schema validation context
5600 * @schema: the schema being built
5601 * @node: a subtree containing XML Schema informations
5602 *
5603 * parse a XML schema Attrribute declaration
5604 * *WARNING* this interface is highly subject to change
5605 *
William M. Bracke7091952004-05-11 15:09:58 +00005606 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005607 * 1 in case of success.
5608 */
5609static xmlSchemaAnnotPtr
5610xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5611 xmlNodePtr node)
5612{
5613 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005614 xmlNodePtr child = NULL;
5615 xmlAttrPtr attr;
5616 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005617
Daniel Veillardc0826a72004-08-10 14:17:33 +00005618 /*
5619 * INFO: S4S completed.
5620 */
5621 /*
5622 * id = ID
5623 * {any attributes with non-schema namespace . . .}>
5624 * Content: (appinfo | documentation)*
5625 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005626 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5627 return (NULL);
5628 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005629 attr = node->properties;
5630 while (attr != NULL) {
5631 if (((attr->ns == NULL) &&
5632 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
5633 ((attr->ns != NULL) &&
5634 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
5635
5636 xmlSchemaPIllegalAttrErr(ctxt,
5637 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5638 NULL, NULL, attr);
5639 }
5640 attr = attr->next;
5641 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005642 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005643 /*
5644 * And now for the children...
5645 */
5646 child = node->children;
5647 while (child != NULL) {
5648 if (IS_SCHEMA(child, "appinfo")) {
5649 /* TODO: make available the content of "appinfo". */
5650 /*
5651 * source = anyURI
5652 * {any attributes with non-schema namespace . . .}>
5653 * Content: ({any})*
5654 */
5655 attr = child->properties;
5656 while (attr != NULL) {
5657 if (((attr->ns == NULL) &&
5658 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
5659 ((attr->ns != NULL) &&
5660 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005661
Daniel Veillardc0826a72004-08-10 14:17:33 +00005662 xmlSchemaPIllegalAttrErr(ctxt,
5663 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5664 NULL, NULL, attr);
5665 }
5666 attr = attr->next;
5667 }
5668 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5669 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
5670 child = child->next;
5671 } else if (IS_SCHEMA(child, "documentation")) {
5672 /* TODO: make available the content of "documentation". */
5673 /*
5674 * source = anyURI
5675 * {any attributes with non-schema namespace . . .}>
5676 * Content: ({any})*
5677 */
5678 attr = child->properties;
5679 while (attr != NULL) {
5680 if (attr->ns == NULL) {
5681 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
5682 xmlSchemaPIllegalAttrErr(ctxt,
5683 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5684 NULL, NULL, attr);
5685 }
5686 } else {
5687 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5688 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5689 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
5690
5691 xmlSchemaPIllegalAttrErr(ctxt,
5692 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5693 NULL, NULL, attr);
5694 }
5695 }
5696 attr = attr->next;
5697 }
5698 /*
5699 * Attribute "xml:lang".
5700 */
5701 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5702 if (attr != NULL)
5703 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
5704 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
5705 child = child->next;
5706 } else {
5707 if (!barked)
5708 xmlSchemaPContentErr(ctxt,
5709 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5710 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5711 barked = 1;
5712 child = child->next;
5713 }
5714 }
5715
Daniel Veillard4255d502002-04-16 15:50:10 +00005716 return (ret);
5717}
5718
5719/**
5720 * xmlSchemaParseFacet:
5721 * @ctxt: a schema validation context
5722 * @schema: the schema being built
5723 * @node: a subtree containing XML Schema informations
5724 *
5725 * parse a XML schema Facet declaration
5726 * *WARNING* this interface is highly subject to change
5727 *
5728 * Returns the new type structure or NULL in case of error
5729 */
5730static xmlSchemaFacetPtr
5731xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005732 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005733{
5734 xmlSchemaFacetPtr facet;
5735 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005736 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005737
5738 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5739 return (NULL);
5740
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005741 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005742 if (facet == NULL) {
5743 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5744 return (NULL);
5745 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005746 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005747 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005748 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005749 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5750 "Facet %s has no value\n", node->name, NULL);
5751 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005752 return (NULL);
5753 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005754 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005755 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005756 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005757 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005758 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005759 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005760 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005761 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005762 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005763 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005764 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005765 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005766 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005767 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005768 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005769 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005770 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005771 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005772 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005773 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005774 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005775 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5776 } else if (IS_SCHEMA(node, "minLength")) {
5777 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5778 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005779 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5780 "Unknown facet type %s\n", node->name, NULL);
5781 xmlSchemaFreeFacet(facet);
5782 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005783 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005784 xmlSchemaPValAttrID(ctxt, NULL,
5785 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005786 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005787 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5788 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5789 const xmlChar *fixed;
5790
5791 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5792 if (fixed != NULL) {
5793 if (xmlStrEqual(fixed, BAD_CAST "true"))
5794 facet->fixed = 1;
5795 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005796 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005797 child = node->children;
5798
5799 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005800 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5801 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005802 }
5803 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005804 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5805 "Facet %s has unexpected child content\n",
5806 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005807 }
5808 return (facet);
5809}
5810
5811/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005812 * xmlSchemaParseWildcardNs:
5813 * @ctxt: a schema parser context
5814 * @wildc: the wildcard, already created
5815 * @node: a subtree containing XML Schema informations
5816 *
5817 * Parses the attribute "processContents" and "namespace"
5818 * of a xsd:anyAttribute and xsd:any.
5819 * *WARNING* this interface is highly subject to change
5820 *
5821 * Returns 0 if everything goes fine, a positive error code
5822 * if something is not valid and -1 if an internal error occurs.
5823 */
5824static int
5825xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5826 xmlSchemaPtr schema,
5827 xmlSchemaWildcardPtr wildc,
5828 xmlNodePtr node)
5829{
5830 const xmlChar *pc, *ns, *dictnsItem;
5831 int ret = 0;
5832 xmlChar *nsItem;
5833 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5834 xmlAttrPtr attr;
5835
5836 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5837 if ((pc == NULL)
5838 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5839 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5840 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5841 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5842 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5843 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5844 } else {
5845 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005846 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005847 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00005848 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005849 NULL, NULL, NULL);
5850 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005851 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005852 }
5853 /*
5854 * Build the namespace constraints.
5855 */
5856 attr = xmlSchemaGetPropNode(node, "namespace");
5857 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5858 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
5859 wildc->any = 1;
5860 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5861 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5862 if (wildc->negNsSet == NULL) {
5863 return (-1);
5864 }
5865 wildc->negNsSet->value = schema->targetNamespace;
5866 } else {
5867 const xmlChar *end, *cur;
5868
5869 cur = ns;
5870 do {
5871 while (IS_BLANK_CH(*cur))
5872 cur++;
5873 end = cur;
5874 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5875 end++;
5876 if (end == cur)
5877 break;
5878 nsItem = xmlStrndup(cur, end - cur);
5879 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5880 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
5881 xmlSchemaPSimpleTypeErr(ctxt,
5882 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
5883 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005884 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005885 "((##any | ##other) | List of (anyURI | "
5886 "(##targetNamespace | ##local)))",
5887 nsItem, NULL, NULL, NULL);
5888 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5889 } else {
5890 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5891 dictnsItem = schema->targetNamespace;
5892 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5893 dictnsItem = NULL;
5894 } else {
5895 /*
5896 * Validate the item (anyURI).
5897 */
5898 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
5899 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5900 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5901 }
5902 /*
5903 * Avoid dublicate namespaces.
5904 */
5905 tmp = wildc->nsSet;
5906 while (tmp != NULL) {
5907 if (dictnsItem == tmp->value)
5908 break;
5909 tmp = tmp->next;
5910 }
5911 if (tmp == NULL) {
5912 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5913 if (tmp == NULL) {
5914 xmlFree(nsItem);
5915 return (-1);
5916 }
5917 tmp->value = dictnsItem;
5918 tmp->next = NULL;
5919 if (wildc->nsSet == NULL)
5920 wildc->nsSet = tmp;
5921 else
5922 lastNs->next = tmp;
5923 lastNs = tmp;
5924 }
5925
5926 }
5927 xmlFree(nsItem);
5928 cur = end;
5929 } while (*cur != 0);
5930 }
5931 return (ret);
5932}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005933
5934static int
5935xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005936 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005937 xmlNodePtr node,
5938 int minOccurs,
5939 int maxOccurs) {
5940
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005941 if ((maxOccurs == 0) && ( minOccurs == 0))
5942 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005943 if (maxOccurs != UNBOUNDED) {
5944 /*
5945 * TODO: Maby we should better not create the particle,
5946 * if min/max is invalid, since it could confuse the build of the
5947 * content model.
5948 */
5949 /*
5950 * 3.9.6 Schema Component Constraint: Particle Correct
5951 *
5952 */
5953 if (maxOccurs < 1) {
5954 /*
5955 * 2.2 {max occurs} must be greater than or equal to 1.
5956 */
5957 xmlSchemaPCustomAttrErr(ctxt,
5958 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005959 NULL, NULL,
5960 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005961 "The value must be greater than or equal to 1");
5962 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
5963 } else if (minOccurs > maxOccurs) {
5964 /*
5965 * 2.1 {min occurs} must not be greater than {max occurs}.
5966 */
5967 xmlSchemaPCustomAttrErr(ctxt,
5968 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005969 NULL, NULL,
5970 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005971 "The value must not be greater than the value of 'maxOccurs'");
5972 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
5973 }
5974 }
5975 return (0);
5976}
5977
Daniel Veillardc0826a72004-08-10 14:17:33 +00005978/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005979 * xmlSchemaParseAny:
5980 * @ctxt: a schema validation context
5981 * @schema: the schema being built
5982 * @node: a subtree containing XML Schema informations
5983 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005984 * Parsea a XML schema <any> element. A particle and wildcard
5985 * will be created (except if minOccurs==maxOccurs==0, in this case
5986 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00005987 * *WARNING* this interface is highly subject to change
5988 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005989 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00005990 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005991static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00005992xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5993 xmlNodePtr node)
5994{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005995 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00005996 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005997 xmlSchemaWildcardPtr wild;
5998 int min, max;
5999 xmlAttrPtr attr;
6000 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006001
6002 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6003 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006004 /*
6005 * Check for illegal attributes.
6006 */
6007 attr = node->properties;
6008 while (attr != NULL) {
6009 if (attr->ns == NULL) {
6010 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6011 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6012 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6013 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6014 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6015 xmlSchemaPIllegalAttrErr(ctxt,
6016 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6017 NULL, NULL, attr);
6018 }
6019 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6020 xmlSchemaPIllegalAttrErr(ctxt,
6021 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6022 NULL, NULL, attr);
6023 }
6024 attr = attr->next;
6025 }
6026 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6027 /*
6028 * minOccurs/maxOccurs.
6029 */
6030 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006031 "(nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006032 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6033 "nonNegativeInteger");
6034 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6035 /*
6036 * Create & parse the wildcard.
6037 */
6038 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6039 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006040 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006041 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006042 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006043 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006044 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006045 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006046 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006047 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006048 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006049 }
6050 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006051 xmlSchemaPContentErr(ctxt,
6052 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6053 NULL, NULL, node, child,
6054 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006055 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006056 /*
6057 * No component if minOccurs==maxOccurs==0.
6058 */
6059 if ((min == 0) && (max == 0)) {
6060 /* Don't free the wildcard, since it's already on the list. */
6061 return (NULL);
6062 }
6063 /*
6064 * Create the particle.
6065 */
6066 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6067 if (particle == NULL)
6068 return (NULL);
6069 particle->annot = annot;
6070 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006071
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006072 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006073}
6074
6075/**
6076 * xmlSchemaParseNotation:
6077 * @ctxt: a schema validation context
6078 * @schema: the schema being built
6079 * @node: a subtree containing XML Schema informations
6080 *
6081 * parse a XML schema Notation declaration
6082 *
6083 * Returns the new structure or NULL in case of error
6084 */
6085static xmlSchemaNotationPtr
6086xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006087 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006088{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006089 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006090 xmlSchemaNotationPtr ret;
6091 xmlNodePtr child = NULL;
6092
6093 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6094 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006095 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006096 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006097 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6098 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006099 return (NULL);
6100 }
6101 ret = xmlSchemaAddNotation(ctxt, schema, name);
6102 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006103 return (NULL);
6104 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006105 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006106
6107 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6108 node, BAD_CAST "id");
6109
6110 if (IS_SCHEMA(child, "annotation")) {
6111 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6112 child = child->next;
6113 }
6114
Daniel Veillard4255d502002-04-16 15:50:10 +00006115 child = node->children;
6116 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006117 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6118 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006119 }
6120 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006121 xmlSchemaPContentErr(ctxt,
6122 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6123 NULL, NULL, node, child,
6124 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006125 }
6126
6127 return (ret);
6128}
6129
6130/**
6131 * xmlSchemaParseAnyAttribute:
6132 * @ctxt: a schema validation context
6133 * @schema: the schema being built
6134 * @node: a subtree containing XML Schema informations
6135 *
6136 * parse a XML schema AnyAttrribute declaration
6137 * *WARNING* this interface is highly subject to change
6138 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006139 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006140 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006141static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006142xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6143 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006144{
Daniel Veillard3646d642004-06-02 19:19:14 +00006145 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006146 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006147 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006148
6149 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6150 return (NULL);
6151
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006152 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6153 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006154 if (ret == NULL) {
6155 return (NULL);
6156 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006157 /*
6158 * Check for illegal attributes.
6159 */
6160 attr = node->properties;
6161 while (attr != NULL) {
6162 if (attr->ns == NULL) {
6163 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6164 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6165 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6166 xmlSchemaPIllegalAttrErr(ctxt,
6167 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6168 NULL, NULL, attr);
6169 }
6170 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6171 xmlSchemaPIllegalAttrErr(ctxt,
6172 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6173 NULL, NULL, attr);
6174 }
6175 attr = attr->next;
6176 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006177 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6178 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006179 /*
6180 * Parse the namespace list.
6181 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006182 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006183 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006184 /*
6185 * And now for the children...
6186 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006187 child = node->children;
6188 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006189 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6190 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006191 }
6192 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006193 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006194 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6195 NULL, NULL, node, child,
6196 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006197 }
6198
6199 return (ret);
6200}
6201
6202
6203/**
6204 * xmlSchemaParseAttribute:
6205 * @ctxt: a schema validation context
6206 * @schema: the schema being built
6207 * @node: a subtree containing XML Schema informations
6208 *
6209 * parse a XML schema Attrribute declaration
6210 * *WARNING* this interface is highly subject to change
6211 *
William M. Bracke7091952004-05-11 15:09:58 +00006212 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006213 */
6214static xmlSchemaAttributePtr
6215xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006216 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006217{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006218 const xmlChar *name, *attrValue;
6219 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006220 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006221 xmlNodePtr child = NULL;
6222 xmlAttrPtr attr, nameAttr;
6223 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006224
6225 /*
6226 * Note that the w3c spec assumes the schema to be validated with schema
6227 * for schemas beforehand.
6228 *
6229 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006230 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006231
6232 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6233 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006234 attr = xmlSchemaGetPropNode(node, "ref");
6235 nameAttr = xmlSchemaGetPropNode(node, "name");
6236
6237 if ((attr == NULL) && (nameAttr == NULL)) {
6238 /*
6239 * 3.2.3 : 3.1
6240 * One of ref or name must be present, but not both
6241 */
6242 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6243 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
6244 "One of the attributes 'ref' or 'name' must be present");
6245 return (NULL);
6246 }
6247 if ((topLevel) || (attr == NULL)) {
6248 if (nameAttr == NULL) {
6249 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6250 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
6251 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006252 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006253 }
6254 } else
6255 isRef = 1;
6256
6257 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006258 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006259 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
6260
6261 /*
6262 * Parse as attribute reference.
6263 */
6264 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6265 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6266 &refPrefix, &ref) != 0) {
6267 return (NULL);
6268 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006269 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006270 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006271 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006272 if (ret == NULL) {
6273 if (repName != NULL)
6274 xmlFree(repName);
6275 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006276 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006277 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6278 ret->node = node;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006279 ret->refNs = refNs;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006280 ret->refPrefix = refPrefix;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006281 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006282 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6283 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006284 /*
6285 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6286 */
6287 if (nameAttr != NULL)
6288 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6289 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6290 "ref", "name");
6291 /*
6292 * Check for illegal attributes.
6293 */
6294 attr = node->properties;
6295 while (attr != NULL) {
6296 if (attr->ns == NULL) {
6297 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6298 xmlStrEqual(attr->name, BAD_CAST "form")) {
6299 /*
6300 * 3.2.3 : 3.2
6301 * If ref is present, then all of <simpleType>,
6302 * form and type must be absent.
6303 */
6304 xmlSchemaPIllegalAttrErr(ctxt,
6305 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
6306 (xmlSchemaTypePtr) ret, attr);
6307 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6308 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6309 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6310 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6311 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6312 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
6313 xmlSchemaPIllegalAttrErr(ctxt,
6314 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6315 &repName, (xmlSchemaTypePtr) ret, attr);
6316 }
6317 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6318 xmlSchemaPIllegalAttrErr(ctxt,
6319 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6320 &repName, (xmlSchemaTypePtr) ret, attr);
6321 }
6322 attr = attr->next;
6323 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006324 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006325 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006326
6327 /*
6328 * Parse as attribute declaration.
6329 */
6330 if (xmlSchemaPValAttrNode(ctxt,
6331 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
6332 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6333 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006334 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006335 /*
6336 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6337 */
6338 /*
6339 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6340 */
6341 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
6342 xmlSchemaPSimpleTypeErr(ctxt,
6343 XML_SCHEMAP_NO_XMLNS,
6344 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006345 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006346 "The value must not match 'xmlns'",
6347 NULL, NULL);
6348 if (repName != NULL)
6349 xmlFree(repName);
6350 return (NULL);
6351 }
6352 /*
6353 * Evaluate the target namespace
6354 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006355 if (topLevel) {
6356 ns = schema->targetNamespace;
6357 } else {
6358 attr = xmlSchemaGetPropNode(node, "form");
6359 if (attr != NULL) {
6360 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6361 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6362 ns = schema->targetNamespace;
6363 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6364 xmlSchemaPSimpleTypeErr(ctxt,
6365 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6366 &repName, NULL, (xmlNodePtr) attr,
6367 NULL, "(qualified | unqualified)",
6368 attrValue, NULL, NULL, NULL);
6369 }
6370 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
6371 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006372 }
6373 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006374 if (ret == NULL) {
6375 if (repName != NULL)
6376 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006377 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006378 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006379 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006380 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006381 if (topLevel)
6382 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
6383 /*
6384 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6385 */
6386 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
6387 xmlSchemaPCustomErr(ctxt,
6388 XML_SCHEMAP_NO_XSI,
6389 &repName, (xmlSchemaTypePtr) ret, node,
6390 "The target namespace must not match '%s'",
6391 xmlSchemaInstanceNs);
6392 }
6393 /*
6394 * Check for illegal attributes.
6395 */
6396 attr = node->properties;
6397 while (attr != NULL) {
6398 if (attr->ns == NULL) {
6399 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6400 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6401 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6402 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6403 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
6404 if ((topLevel) ||
6405 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6406 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
6407 xmlSchemaPIllegalAttrErr(ctxt,
6408 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6409 &repName, (xmlSchemaTypePtr) ret, attr);
6410 }
6411 }
6412 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6413 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6414 &repName, (xmlSchemaTypePtr) ret, attr);
6415 }
6416 attr = attr->next;
6417 }
6418 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
6419 node, "type", &ret->typeNs, NULL, &ret->typeName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006420 }
6421 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6422 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006423 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006424 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006425 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006426 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6427 if (ret->defValue != NULL)
6428 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
6429 /*
6430 * Attribute "default".
6431 */
6432 attr = xmlSchemaGetPropNode(node, "default");
6433 if (attr != NULL) {
6434 /*
6435 * 3.2.3 : 1
6436 * default and fixed must not both be present.
6437 */
6438 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6439 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6440 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6441 } else
6442 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6443 }
6444 if (topLevel == 0) {
6445 /*
6446 * Attribute "use".
6447 */
6448 attr = xmlSchemaGetPropNode(node, "use");
6449 if (attr != NULL) {
6450 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6451 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6452 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6453 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6454 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6455 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6456 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6457 else
6458 xmlSchemaPSimpleTypeErr(ctxt,
6459 XML_SCHEMAP_INVALID_ATTR_USE,
6460 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006461 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006462 attrValue, NULL, NULL, NULL);
6463 } else
6464 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6465 /*
6466 * 3.2.3 : 2
6467 * If default and use are both present, use must have
6468 * the actual value optional.
6469 */
6470 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6471 (ret->defValue != NULL) &&
6472 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
6473 xmlSchemaPSimpleTypeErr(ctxt,
6474 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6475 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006476 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006477 "The value must be 'optional' if the attribute "
6478 "'default' is present as well", NULL, NULL);
6479 }
6480 }
6481 /*
6482 * And now for the children...
6483 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006484 child = node->children;
6485 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006486 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6487 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006488 }
6489 if (isRef) {
6490 if (child != NULL) {
6491 if (IS_SCHEMA(child, "simpleType"))
6492 /*
6493 * 3.2.3 : 3.2
6494 * If ref is present, then all of <simpleType>,
6495 * form and type must be absent.
6496 */
6497 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6498 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6499 "(annotation?)");
6500 else
6501 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6502 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6503 "(annotation?)");
6504 }
6505 } else {
6506 if (IS_SCHEMA(child, "simpleType")) {
6507 if (ret->typeName != NULL) {
6508 /*
6509 * 3.2.3 : 4
6510 * type and <simpleType> must not both be present.
6511 */
6512 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6513 &repName, (xmlSchemaTypePtr) ret, node, child,
6514 "The attribute 'type' and the <simpleType> child "
6515 "are mutually exclusive", NULL);
6516 } else
6517 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6518 child = child->next;
6519 }
6520 if (child != NULL)
6521 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6522 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6523 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006524 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006525 /*
6526 * Cleanup.
6527 */
6528 if (repName != NULL)
6529 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006530 return (ret);
6531}
6532
6533/**
6534 * xmlSchemaParseAttributeGroup:
6535 * @ctxt: a schema validation context
6536 * @schema: the schema being built
6537 * @node: a subtree containing XML Schema informations
6538 *
6539 * parse a XML schema Attribute Group declaration
6540 * *WARNING* this interface is highly subject to change
6541 *
6542 * Returns the attribute group or NULL in case of error.
6543 */
6544static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006545xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006546 xmlSchemaPtr schema, xmlNodePtr node,
6547 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006548{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006549 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006550 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006551 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006552 const xmlChar *oldcontainer;
6553 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006554
6555 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6556 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006557
6558 nameAttr = xmlSchemaGetPropNode(node, "name");
6559 attr = xmlSchemaGetPropNode(node, "ref");
6560 if ((topLevel) || (attr == NULL)) {
6561 /*
6562 * Parse as an attribute group definition.
6563 * Note that those are allowed at top level only.
6564 */
6565 if (nameAttr == NULL) {
6566 xmlSchemaPMissingAttrErr(ctxt,
6567 XML_SCHEMAP_S4S_ATTR_MISSING,
6568 NULL, NULL, node, "name", NULL);
6569 return (NULL);
6570 }
6571 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
6572 /*
6573 * The name is crucial, exit if invalid.
6574 */
6575 if (xmlSchemaPValAttrNode(ctxt,
6576 NULL, NULL, nameAttr,
6577 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6578 return (NULL);
6579 }
6580 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6581 if (ret == NULL)
6582 return (NULL);
6583 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6584 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6585 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006586 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006587 } else {
6588 char buf[50];
6589 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6590
6591 /*
6592 * Parse as an attribute group definition reference.
6593 */
6594 if (attr == NULL) {
6595 xmlSchemaPMissingAttrErr(ctxt,
6596 XML_SCHEMAP_S4S_ATTR_MISSING,
6597 NULL, NULL, node, "ref", NULL);
6598 }
6599 xmlSchemaPValAttrNodeQName(ctxt, schema,
6600 NULL, NULL, attr, &refNs, &refPrefix, &ref);
6601
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006602 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006603 name = (const xmlChar *) buf;
6604 if (name == NULL) {
6605 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6606 "attribute group definition reference", node);
6607 return (NULL);
6608 }
6609 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6610 if (ret == NULL)
6611 return (NULL);
6612 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6613 ret->ref = ref;
6614 ret->refNs = refNs;
6615 /* TODO: Is @refPrefix currently used? */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006616 ret->refPrefix = refPrefix;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006617 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006618 xmlSchemaCheckReference(ctxt, schema, node,
6619 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006620 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006621 /*
6622 * Check for illegal attributes.
6623 */
6624 attr = node->properties;
6625 while (attr != NULL) {
6626 if (attr->ns == NULL) {
6627 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6628 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
6629 (!xmlStrEqual(attr->name, BAD_CAST "id")))
6630 {
6631 xmlSchemaPIllegalAttrErr(ctxt,
6632 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6633 NULL, NULL, attr);
6634 }
6635 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6636 xmlSchemaPIllegalAttrErr(ctxt,
6637 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6638 NULL, NULL, attr);
6639 }
6640 attr = attr->next;
6641 }
6642 /* TODO: Validate "id" ? */
6643 /*
6644 * And now for the children...
6645 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006646 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006647 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006648 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006649 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006650 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6651 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006652 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006653 if (topLevel) {
6654 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
6655 if (IS_SCHEMA(child, "anyAttribute")) {
6656 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6657 child = child->next;
6658 }
6659 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006660 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006661 xmlSchemaPContentErr(ctxt,
6662 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6663 NULL, NULL, node, child, NULL,
6664 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006665 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006666 ctxt->container = oldcontainer;
6667 return (ret);
6668}
6669
6670/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006671 * xmlSchemaPValAttrFormDefault:
6672 * @value: the value
6673 * @flags: the flags to be modified
6674 * @flagQualified: the specific flag for "qualified"
6675 *
6676 * Returns 0 if the value is valid, 1 otherwise.
6677 */
6678static int
6679xmlSchemaPValAttrFormDefault(const xmlChar *value,
6680 int *flags,
6681 int flagQualified)
6682{
6683 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6684 if ((*flags & flagQualified) == 0)
6685 *flags |= flagQualified;
6686 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
6687 return (1);
6688
6689 return (0);
6690}
6691
6692/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006693 * xmlSchemaPValAttrBlockFinal:
6694 * @value: the value
6695 * @flags: the flags to be modified
6696 * @flagAll: the specific flag for "#all"
6697 * @flagExtension: the specific flag for "extension"
6698 * @flagRestriction: the specific flag for "restriction"
6699 * @flagSubstitution: the specific flag for "substitution"
6700 * @flagList: the specific flag for "list"
6701 * @flagUnion: the specific flag for "union"
6702 *
6703 * Validates the value of the attribute "final" and "block". The value
6704 * is converted into the specified flag values and returned in @flags.
6705 *
6706 * Returns 0 if the value is valid, 1 otherwise.
6707 */
6708
6709static int
6710xmlSchemaPValAttrBlockFinal(const xmlChar *value,
6711 int *flags,
6712 int flagAll,
6713 int flagExtension,
6714 int flagRestriction,
6715 int flagSubstitution,
6716 int flagList,
6717 int flagUnion)
6718{
6719 int ret = 0;
6720
6721 /*
6722 * TODO: This does not check for dublicate entries.
6723 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006724 if (value == NULL)
6725 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006726 if (xmlStrEqual(value, BAD_CAST "#all")) {
6727 if (flagAll != -1)
6728 *flags |= flagAll;
6729 else {
6730 if (flagExtension != -1)
6731 *flags |= flagExtension;
6732 if (flagRestriction != -1)
6733 *flags |= flagRestriction;
6734 if (flagSubstitution != -1)
6735 *flags |= flagSubstitution;
6736 if (flagList != -1)
6737 *flags |= flagList;
6738 if (flagUnion != -1)
6739 *flags |= flagUnion;
6740 }
6741 } else {
6742 const xmlChar *end, *cur = value;
6743 xmlChar *item;
6744
6745 do {
6746 while (IS_BLANK_CH(*cur))
6747 cur++;
6748 end = cur;
6749 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6750 end++;
6751 if (end == cur)
6752 break;
6753 item = xmlStrndup(cur, end - cur);
6754 if (xmlStrEqual(item, BAD_CAST "extension")) {
6755 if (flagExtension != -1) {
6756 if ((*flags & flagExtension) == 0)
6757 *flags |= flagExtension;
6758 } else
6759 ret = 1;
6760 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6761 if (flagRestriction != -1) {
6762 if ((*flags & flagRestriction) == 0)
6763 *flags |= flagRestriction;
6764 } else
6765 ret = 1;
6766 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6767 if (flagSubstitution != -1) {
6768 if ((*flags & flagSubstitution) == 0)
6769 *flags |= flagSubstitution;
6770 } else
6771 ret = 1;
6772 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6773 if (flagList != -1) {
6774 if ((*flags & flagList) == 0)
6775 *flags |= flagList;
6776 } else
6777 ret = 1;
6778 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6779 if (flagUnion != -1) {
6780 if ((*flags & flagUnion) == 0)
6781 *flags |= flagUnion;
6782 } else
6783 ret = 1;
6784 } else
6785 ret = 1;
6786 if (item != NULL)
6787 xmlFree(item);
6788 cur = end;
6789 } while ((ret == 0) && (*cur != 0));
6790 }
6791
6792 return (ret);
6793}
6794
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006795static int
6796xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006797 xmlSchemaIDCPtr idc,
6798 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006799 xmlAttrPtr attr,
6800 int isField)
6801{
6802 xmlNodePtr node;
6803
6804 /*
6805 * c-selector-xpath:
6806 * Schema Component Constraint: Selector Value OK
6807 *
6808 * TODO: 1 The {selector} must be a valid XPath expression, as defined
6809 * in [XPath].
6810 */
6811 if (selector == NULL) {
6812 xmlSchemaPErr(ctxt, idc->node,
6813 XML_SCHEMAP_INTERNAL,
6814 "Internal error: xmlSchemaCheckCSelectorXPath, "
6815 "the selector is not specified.\n", NULL, NULL);
6816 return (-1);
6817 }
6818 if (attr == NULL)
6819 node = idc->node;
6820 else
6821 node = (xmlNodePtr) attr;
6822 if (selector->xpath == NULL) {
6823 xmlSchemaPCustomErr(ctxt,
6824 /* TODO: Adjust error code. */
6825 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6826 NULL, NULL, node,
6827 "The XPath expression of the selector is not valid", NULL);
6828 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6829 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006830 const xmlChar **nsArray = NULL;
6831 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006832 /*
6833 * Compile the XPath expression.
6834 */
6835 /*
6836 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006837 * TODO: Call xmlPatterncompile with different options for selector/
6838 * field.
6839 */
6840 nsList = xmlGetNsList(attr->doc, attr->parent);
6841 /*
6842 * Build an array of prefixes and namespaces.
6843 */
6844 if (nsList != NULL) {
6845 int i, count = 0;
6846 xmlNsPtr ns;
6847
6848 for (i = 0; nsList[i] != NULL; i++)
6849 count++;
6850
6851 nsArray = (const xmlChar **) xmlMalloc(
6852 (count * 2 + 1) * sizeof(const xmlChar *));
6853 if (nsArray == NULL) {
6854 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6855 NULL);
6856 return (-1);
6857 }
6858 for (i = 0; i < count; i++) {
6859 ns = nsList[i];
6860 nsArray[2 * i] = nsList[i]->href;
6861 nsArray[2 * i + 1] = nsList[i]->prefix;
6862 }
6863 nsArray[count * 2] = NULL;
6864 xmlFree(nsList);
6865 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006866 /*
6867 * TODO: Differentiate between "selector" and "field".
6868 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006869 if (isField)
6870 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006871 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006872 else
6873 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006874 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006875 if (nsArray != NULL)
6876 xmlFree((xmlChar **) nsArray);
6877
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006878 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006879 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006880 /* TODO: Adjust error code? */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006881 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6882 NULL, NULL, node,
6883 "The XPath expression '%s' could not be "
6884 "compiled", selector->xpath);
6885 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006886 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006887 }
6888 return (0);
6889}
6890
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006891#define ADD_ANNOTATION(annot) \
6892 xmlSchemaAnnotPtr cur = item->annot; \
6893 if (item->annot == NULL) { \
6894 item->annot = annot; \
6895 return (annot); \
6896 } \
6897 cur = item->annot; \
6898 if (cur->next != NULL) { \
6899 cur = cur->next; \
6900 } \
6901 cur->next = annot;
6902
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006903/**
6904 * xmlSchemaAssignAnnotation:
6905 * @item: the schema component
6906 * @annot: the annotation
6907 *
6908 * Adds the annotation to the given schema component.
6909 *
6910 * Returns the given annotaion.
6911 */
6912static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006913xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
6914 xmlSchemaAnnotPtr annot)
6915{
6916 if ((annItem == NULL) || (annot == NULL))
6917 return (NULL);
6918 switch (annItem->type) {
6919 case XML_SCHEMA_TYPE_ELEMENT: {
6920 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
6921 ADD_ANNOTATION(annot)
6922 }
6923 break;
6924 case XML_SCHEMA_TYPE_ATTRIBUTE: {
6925 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
6926 ADD_ANNOTATION(annot)
6927 }
6928 break;
6929 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
6930 case XML_SCHEMA_TYPE_ANY: {
6931 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
6932 ADD_ANNOTATION(annot)
6933 }
6934 break;
6935 case XML_SCHEMA_TYPE_PARTICLE:
6936 case XML_SCHEMA_TYPE_IDC_KEY:
6937 case XML_SCHEMA_TYPE_IDC_KEYREF:
6938 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
6939 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
6940 ADD_ANNOTATION(annot)
6941 }
6942 break;
6943 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
6944 xmlSchemaAttributeGroupPtr item =
6945 (xmlSchemaAttributeGroupPtr) annItem;
6946 ADD_ANNOTATION(annot)
6947 }
6948 break;
6949 case XML_SCHEMA_TYPE_NOTATION: {
6950 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
6951 ADD_ANNOTATION(annot)
6952 }
6953 break;
6954 case XML_SCHEMA_FACET_MININCLUSIVE:
6955 case XML_SCHEMA_FACET_MINEXCLUSIVE:
6956 case XML_SCHEMA_FACET_MAXINCLUSIVE:
6957 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
6958 case XML_SCHEMA_FACET_TOTALDIGITS:
6959 case XML_SCHEMA_FACET_FRACTIONDIGITS:
6960 case XML_SCHEMA_FACET_PATTERN:
6961 case XML_SCHEMA_FACET_ENUMERATION:
6962 case XML_SCHEMA_FACET_WHITESPACE:
6963 case XML_SCHEMA_FACET_LENGTH:
6964 case XML_SCHEMA_FACET_MAXLENGTH:
6965 case XML_SCHEMA_FACET_MINLENGTH: {
6966 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
6967 ADD_ANNOTATION(annot)
6968 }
6969 break;
6970 case XML_SCHEMA_TYPE_SIMPLE:
6971 case XML_SCHEMA_TYPE_COMPLEX: {
6972 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
6973 ADD_ANNOTATION(annot)
6974 }
6975 break;
6976 case XML_SCHEMA_TYPE_GROUP: {
6977 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
6978 ADD_ANNOTATION(annot)
6979 }
6980 break;
6981 case XML_SCHEMA_TYPE_SEQUENCE:
6982 case XML_SCHEMA_TYPE_CHOICE:
6983 case XML_SCHEMA_TYPE_ALL: {
6984 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
6985 ADD_ANNOTATION(annot)
6986 }
6987 break;
6988 default:
6989 xmlSchemaPCustomErr(NULL,
6990 XML_SCHEMAP_INTERNAL,
6991 NULL, NULL, NULL,
6992 "Internal error: xmlSchemaAddAnnotation, "
6993 "The item is not a annotated schema component", NULL);
6994 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006995 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006996 return (annot);
6997}
6998
6999/**
7000 * xmlSchemaParseIDCSelectorAndField:
7001 * @ctxt: a schema validation context
7002 * @schema: the schema being built
7003 * @node: a subtree containing XML Schema informations
7004 *
7005 * Parses a XML Schema identity-contraint definition's
7006 * <selector> and <field> elements.
7007 *
7008 * Returns the parsed identity-constraint definition.
7009 */
7010static xmlSchemaIDCSelectPtr
7011xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
7012 xmlSchemaPtr schema,
7013 xmlSchemaIDCPtr idc,
7014 xmlNodePtr node,
7015 int isField)
7016{
7017 xmlSchemaIDCSelectPtr item;
7018 xmlNodePtr child = NULL;
7019 xmlAttrPtr attr;
7020
7021 /*
7022 * Check for illegal attributes.
7023 */
7024 attr = node->properties;
7025 while (attr != NULL) {
7026 if (attr->ns == NULL) {
7027 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7028 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
7029 xmlSchemaPIllegalAttrErr(ctxt,
7030 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7031 NULL, NULL, attr);
7032 }
7033 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7034 xmlSchemaPIllegalAttrErr(ctxt,
7035 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7036 NULL, NULL, attr);
7037 }
7038 attr = attr->next;
7039 }
7040 /*
7041 * Create the item.
7042 */
7043 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7044 if (item == NULL) {
7045 xmlSchemaPErrMemory(ctxt,
7046 "allocating a 'selector' of an identity-constraint definition",
7047 NULL);
7048 return (NULL);
7049 }
7050 memset(item, 0, sizeof(xmlSchemaIDCSelect));
7051 /*
7052 * Attribute "xpath" (mandatory).
7053 */
7054 attr = xmlSchemaGetPropNode(node, "xpath");
7055 if (attr == NULL) {
7056 xmlSchemaPMissingAttrErr(ctxt,
7057 XML_SCHEMAP_S4S_ATTR_MISSING,
7058 NULL, NULL, node,
7059 "name", NULL);
7060 } else {
7061 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7062 /*
7063 * URGENT TODO: "field"s have an other syntax than "selector"s.
7064 */
7065
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007066 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7067 isField) == -1) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007068 xmlSchemaPErr(ctxt,
7069 (xmlNodePtr) attr,
7070 XML_SCHEMAP_INTERNAL,
7071 "Internal error: xmlSchemaParseIDCSelectorAndField, "
7072 "validating the XPath expression of a IDC selector.\n",
7073 NULL, NULL);
7074 }
7075
7076 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007077 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007078 /*
7079 * And now for the children...
7080 */
7081 child = node->children;
7082 if (IS_SCHEMA(child, "annotation")) {
7083 /*
7084 * Add the annotation to the parent IDC.
7085 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007086 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007087 xmlSchemaParseAnnotation(ctxt, schema, child));
7088 child = child->next;
7089 }
7090 if (child != NULL) {
7091 xmlSchemaPContentErr(ctxt,
7092 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7093 NULL, NULL, node, child,
7094 NULL, "(annotation?)");
7095 }
7096
7097 return (item);
7098}
7099
7100/**
7101 * xmlSchemaParseIDC:
7102 * @ctxt: a schema validation context
7103 * @schema: the schema being built
7104 * @node: a subtree containing XML Schema informations
7105 *
7106 * Parses a XML Schema identity-contraint definition.
7107 *
7108 * Returns the parsed identity-constraint definition.
7109 */
7110static xmlSchemaIDCPtr
7111xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
7112 xmlSchemaPtr schema,
7113 xmlNodePtr node,
7114 xmlSchemaTypeType idcCategory,
7115 const xmlChar *targetNamespace)
7116{
7117 xmlSchemaIDCPtr item = NULL;
7118 xmlNodePtr child = NULL;
7119 xmlAttrPtr attr;
7120 const xmlChar *name = NULL;
7121 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7122 int resAdd;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00007123
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007124 /*
7125 * Check for illegal attributes.
7126 */
7127 attr = node->properties;
7128 while (attr != NULL) {
7129 if (attr->ns == NULL) {
7130 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7131 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7132 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7133 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
7134 xmlSchemaPIllegalAttrErr(ctxt,
7135 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7136 NULL, NULL, attr);
7137 }
7138 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7139 xmlSchemaPIllegalAttrErr(ctxt,
7140 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7141 NULL, NULL, attr);
7142 }
7143 attr = attr->next;
7144 }
7145 /*
7146 * Attribute "name" (mandatory).
7147 */
7148 attr = xmlSchemaGetPropNode(node, "name");
7149 if (attr == NULL) {
7150 xmlSchemaPMissingAttrErr(ctxt,
7151 XML_SCHEMAP_S4S_ATTR_MISSING,
7152 NULL, NULL, node,
7153 "name", NULL);
7154 return (NULL);
7155 } else if (xmlSchemaPValAttrNode(ctxt,
7156 NULL, NULL, attr,
7157 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7158 return (NULL);
7159 }
7160 /*
7161 * Create the component.
7162 */
7163 if (schema->idcDef == NULL)
7164 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
7165 if (schema->idcDef == NULL)
7166 return (NULL);
7167
7168 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7169 if (item == NULL) {
7170 xmlSchemaPErrMemory(ctxt,
7171 "allocating an identity-constraint definition", NULL);
7172 return (NULL);
7173 }
7174 /*
7175 * Add the IDC to the list of IDCs on the schema component.
7176 */
7177 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
7178 if (resAdd != 0) {
7179 xmlSchemaPCustomErrExt(ctxt,
7180 XML_SCHEMAP_REDEFINED_TYPE,
7181 NULL, NULL, node,
7182 "An identity-constraint definition with the name '%s' "
7183 "and targetNamespace '%s' does already exist",
7184 name, targetNamespace, NULL);
7185 xmlFree(item);
7186 return (NULL);
7187 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007188 memset(item, 0, sizeof(xmlSchemaIDC));
7189 item->name = name;
7190 item->type = idcCategory;
7191 item->node = node;
7192 /*
7193 * The target namespace of the parent element declaration.
7194 */
7195 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007196 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7197 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007198 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7199 /*
7200 * Attribute "refer" (mandatory).
7201 */
7202 attr = xmlSchemaGetPropNode(node, "refer");
7203 if (attr == NULL) {
7204 xmlSchemaPMissingAttrErr(ctxt,
7205 XML_SCHEMAP_S4S_ATTR_MISSING,
7206 NULL, NULL, node,
7207 "refer", NULL);
7208 } else {
7209 /*
7210 * Create a reference item.
7211 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007212 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
7213 NULL, NULL);
7214 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007215 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007216 xmlSchemaPValAttrNodeQName(ctxt, schema,
7217 NULL, NULL, attr,
7218 &(item->ref->targetNamespace), 0,
7219 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007220 xmlSchemaCheckReference(ctxt, schema, node,
7221 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007222 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007223 }
7224 }
7225 /*
7226 * And now for the children...
7227 */
7228 child = node->children;
7229 if (IS_SCHEMA(child, "annotation")) {
7230 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7231 child = child->next;
7232 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007233 if (child == NULL) {
7234 xmlSchemaPContentErr(ctxt,
7235 XML_SCHEMAP_S4S_ELEM_MISSING,
7236 NULL, NULL, node, child,
7237 "A child element is missing",
7238 "(annotation?, (selector, field+))");
7239 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007240 /*
7241 * Child element <selector>.
7242 */
7243 if (IS_SCHEMA(child, "selector")) {
7244 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
7245 item, child, 0);
7246 child = child->next;
7247 /*
7248 * Child elements <field>.
7249 */
7250 if (IS_SCHEMA(child, "field")) {
7251 do {
7252 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
7253 item, child, 1);
7254 if (field != NULL) {
7255 field->index = item->nbFields;
7256 item->nbFields++;
7257 if (lastField != NULL)
7258 lastField->next = field;
7259 else
7260 item->fields = field;
7261 lastField = field;
7262 }
7263 child = child->next;
7264 } while (IS_SCHEMA(child, "field"));
7265 } else {
7266 xmlSchemaPContentErr(ctxt,
7267 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7268 NULL, NULL, node, child,
7269 NULL, "(annotation?, (selector, field+))");
7270 }
7271 }
7272 if (child != NULL) {
7273 xmlSchemaPContentErr(ctxt,
7274 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7275 NULL, NULL, node, child,
7276 NULL, "(annotation?, (selector, field+))");
7277 }
7278
7279 return (item);
7280}
7281
Daniel Veillardc0826a72004-08-10 14:17:33 +00007282/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007283 * xmlSchemaParseElement:
7284 * @ctxt: a schema validation context
7285 * @schema: the schema being built
7286 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007287 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007288 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007289 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007290 * *WARNING* this interface is highly subject to change
7291 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007292 * Returns the element declaration or a particle; NULL in case
7293 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007294 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007295static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007296xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007297 xmlNodePtr node, int topLevel)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007298{
7299 xmlSchemaElementPtr decl = NULL;
7300 xmlSchemaParticlePtr particle = NULL;
7301 xmlSchemaAnnotPtr annot = NULL;
7302 xmlNodePtr child = NULL;
7303 xmlAttrPtr attr, nameAttr;
7304 int min, max, isRef = 0;
7305 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007306
7307 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7308 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007309
Daniel Veillard4255d502002-04-16 15:50:10 +00007310 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007311 return (NULL);
7312 /*
7313 * If we get a "ref" attribute on a local <element> we will assume it's
7314 * a reference - even if there's a "name" attribute; this seems to be more
7315 * robust.
7316 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007317 nameAttr = xmlSchemaGetPropNode(node, "name");
7318 attr = xmlSchemaGetPropNode(node, "ref");
7319 if ((topLevel) || (attr == NULL)) {
7320 if (nameAttr == NULL) {
7321 xmlSchemaPMissingAttrErr(ctxt,
7322 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007323 NULL, NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007324 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007325 }
7326 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007327 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007328
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007329 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7330 child = node->children;
7331 if (IS_SCHEMA(child, "annotation")) {
7332 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7333 child = child->next;
7334 }
7335 /*
7336 * Skip particle part if a global declaration.
7337 */
7338 if (topLevel)
7339 goto declaration_part;
7340 /*
7341 * The particle part ==================================================
7342 */
7343 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7344 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
7345 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
7346 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7347 if (particle == NULL)
7348 goto return_null;
7349
7350 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7351
7352 if (isRef) {
7353 const xmlChar *refNs = NULL, *ref = NULL;
7354 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007355 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007356 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007357 */
7358 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007359 NULL, NULL, attr, &refNs, NULL, &ref);
7360 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007361 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007362 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007363 */
7364 if (nameAttr != NULL) {
7365 xmlSchemaPMutualExclAttrErr(ctxt,
7366 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007367 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007368 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007369 /*
7370 * Check for illegal attributes.
7371 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007372 attr = node->properties;
7373 while (attr != NULL) {
7374 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007375 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7376 xmlStrEqual(attr->name, BAD_CAST "name") ||
7377 xmlStrEqual(attr->name, BAD_CAST "id") ||
7378 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7379 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7380 {
7381 attr = attr->next;
7382 continue;
7383 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007384 /* SPEC (3.3.3 : 2.2) */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007385 xmlSchemaPCustomAttrErr(ctxt,
7386 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007387 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007388 "Only the attributes 'minOccurs', 'maxOccurs' and "
7389 "'id' are allowed in addition to 'ref'");
7390 break;
7391 }
7392 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7393 xmlSchemaPIllegalAttrErr(ctxt,
7394 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007395 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007396 }
7397 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007398 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007399 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007400 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007401 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007402 if (child != NULL) {
7403 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7404 NULL, NULL, node, child, NULL, "(annotation?)");
7405 }
7406 if ((min == 0) && (max == 0))
7407 goto return_null;
7408 /*
7409 * Create the reference item.
7410 */
7411 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7412 ref, refNs);
7413 if (refer == NULL)
7414 goto return_null;
7415 particle->children = (xmlSchemaTreeItemPtr) refer;
7416 particle->annot = annot;
7417 /*
7418 * Add to assembled items; the reference need to be resolved.
7419 */
7420 if (ctxt->assemble != NULL)
7421 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7422
7423 return ((xmlSchemaBasicItemPtr) particle);
7424 }
7425 /*
7426 * The declaration part ===============================================
7427 */
7428declaration_part:
7429 {
7430 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7431 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7432
7433 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007434 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007435 goto return_null;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007436 /*
7437 * Evaluate the target namespace.
7438 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007439 if (topLevel) {
7440 ns = schema->targetNamespace;
7441 } else {
7442 attr = xmlSchemaGetPropNode(node, "form");
7443 if (attr != NULL) {
7444 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7445 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007446 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007447 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
7448 xmlSchemaPSimpleTypeErr(ctxt,
7449 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007450 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007451 NULL, "(qualified | unqualified)",
7452 attrValue, NULL, NULL, NULL);
7453 }
7454 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7455 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00007456 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007457 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
7458 if (decl == NULL) {
7459 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007460 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007461 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7462 decl->node = node;
7463 decl->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007464 /*
7465 * Check for illegal attributes.
7466 */
William M. Bracke7091952004-05-11 15:09:58 +00007467 attr = node->properties;
7468 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007469 if (attr->ns == NULL) {
7470 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7471 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
7472 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7473 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7474 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7475 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007476 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7477 {
7478 if (topLevel == 0) {
7479 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007480 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007481 (!xmlStrEqual(attr->name, BAD_CAST "form")))
7482 {
7483 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
7484 /*
7485 * 3.3.6 : 3 If there is a non-·absent· {substitution
7486 * group affiliation}, then {scope} must be global.
7487 * TODO: This one is redundant, since the S4S does
7488 * prohibit this attribute on local declarations already;
7489 * so why an explicit error code? Weird spec.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007490 * TODO: Think about hanling this equal to the other attributes.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007491 */
7492 xmlSchemaPIllegalAttrErr(ctxt,
7493 XML_SCHEMAP_E_PROPS_CORRECT_3,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007494 NULL, (xmlSchemaTypePtr) decl, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007495 } else {
7496 xmlSchemaPIllegalAttrErr(ctxt,
7497 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007498 NULL, (xmlSchemaTypePtr) decl, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007499 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007500 }
7501 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7502 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
7503 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7504
7505 xmlSchemaPIllegalAttrErr(ctxt,
7506 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007507 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007508 }
7509 }
7510 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7511
7512 xmlSchemaPIllegalAttrErr(ctxt,
7513 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007514 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007515 }
7516 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007517 }
William M. Bracke7091952004-05-11 15:09:58 +00007518 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007519 * Extract/validate attributes.
7520 */
7521 if (topLevel) {
7522 /*
7523 * Process top attributes of global element declarations here.
7524 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007525 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7526 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
7527 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7528 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7529 &(decl->substGroupNs), NULL, &(decl->substGroup));
7530 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007531 node, "abstract", 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007532 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007533 /*
7534 * Attribute "final".
7535 */
7536 attr = xmlSchemaGetPropNode(node, "final");
7537 if (attr == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007538 decl->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007539 } else {
7540 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007541 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007542 -1,
7543 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7544 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
7545 xmlSchemaPSimpleTypeErr(ctxt,
7546 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007547 NULL, (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007548 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007549 attrValue, NULL, NULL, NULL);
7550 }
7551 }
7552 }
7553 /*
7554 * Attribute "block".
7555 */
7556 attr = xmlSchemaGetPropNode(node, "block");
7557 if (attr == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007558 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007559 } else {
7560 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007561 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007562 -1,
7563 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
7564 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
7565 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7566 xmlSchemaPSimpleTypeErr(ctxt,
7567 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007568 NULL, (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007569 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00007570 "restriction | substitution))", attrValue,
7571 NULL, NULL, NULL);
7572 }
7573 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007574 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007575 node, "nillable", 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007576 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007577
Daniel Veillardc0826a72004-08-10 14:17:33 +00007578 xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007579 NULL, (xmlSchemaTypePtr) decl, node,
7580 "type", &(decl->namedTypeNs), NULL, &(decl->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00007581
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007582 decl->value = xmlSchemaGetProp(ctxt, node, "default");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007583 attr = xmlSchemaGetPropNode(node, "fixed");
7584 if (attr != NULL) {
7585 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007586 if (decl->value != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007587 /*
7588 * 3.3.3 : 1
7589 * default and fixed must not both be present.
7590 */
7591 xmlSchemaPMutualExclAttrErr(ctxt,
7592 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007593 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007594 "default", "fixed");
7595 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007596 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7597 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007598 }
William M. Bracke7091952004-05-11 15:09:58 +00007599 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007600 /*
7601 * And now for the children...
7602 */
7603 oldcontainer = ctxt->container;
7604 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007605 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007606 /*
7607 * 3.3.3 : 3
7608 * "type" and either <simpleType> or <complexType> are mutually
7609 * exclusive
7610 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007611 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007612 xmlSchemaPContentErr(ctxt,
7613 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007614 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007615 "The attribute 'type' and the <complexType> child are "
7616 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007617 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007618 decl->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007619 child = child->next;
7620 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007621 /*
7622 * 3.3.3 : 3
7623 * "type" and either <simpleType> or <complexType> are
7624 * mutually exclusive
7625 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007626 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007627 xmlSchemaPContentErr(ctxt,
7628 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007629 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007630 "The attribute 'type' and the <simpleType> child are "
7631 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007632 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007633 decl->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007634 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007635 }
William M. Bracke7091952004-05-11 15:09:58 +00007636 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007637 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007638 if (IS_SCHEMA(child, "unique")) {
7639 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007640 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007641 } else if (IS_SCHEMA(child, "key")) {
7642 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007643 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007644 } else if (IS_SCHEMA(child, "keyref")) {
7645 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007646 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007647 }
7648 if (lastIDC != NULL)
7649 lastIDC->next = curIDC;
7650 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007651 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007652 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007653 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007654 }
7655 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007656 xmlSchemaPContentErr(ctxt,
7657 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007658 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007659 NULL, "(annotation?, ((simpleType | complexType)?, "
7660 "(unique | key | keyref)*))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007661 }
7662 ctxt->container = oldcontainer;
7663 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007664 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007665 /*
7666 * NOTE: Element Declaration Representation OK 4. will be checked at a
7667 * different layer.
7668 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007669 FREE_AND_NULL(des)
7670 if (topLevel)
7671 return ((xmlSchemaBasicItemPtr) decl);
7672 else {
7673 particle->children = (xmlSchemaTreeItemPtr) decl;
7674 return ((xmlSchemaBasicItemPtr) particle);
7675 }
7676
7677return_null:
7678 FREE_AND_NULL(des)
7679 if (annot != NULL)
7680 xmlSchemaFreeAnnot(annot);
7681 if (particle != NULL)
7682 xmlSchemaFreeParticle(particle);
7683 if (decl != NULL)
7684 xmlSchemaFreeElement(decl);
7685 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007686}
7687
7688/**
7689 * xmlSchemaParseUnion:
7690 * @ctxt: a schema validation context
7691 * @schema: the schema being built
7692 * @node: a subtree containing XML Schema informations
7693 *
7694 * parse a XML schema Union definition
7695 * *WARNING* this interface is highly subject to change
7696 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007697 * Returns -1 in case of internal error, 0 in case of success and a positive
7698 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007699 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007700static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007701xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007702 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007703{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007704 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007705 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007706 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007707 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007708
7709 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007710 return (-1);
7711 /* Not a component, don't create it. */
7712 type = ctxt->ctxtType;
7713 /*
7714 * Mark the simple type as being of variety "union".
7715 */
7716 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
William M. Brack2f2a6632004-08-20 23:09:47 +00007717 /*
7718 * Check for illegal attributes.
7719 */
7720 attr = node->properties;
7721 while (attr != NULL) {
7722 if (attr->ns == NULL) {
7723 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7724 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
7725 xmlSchemaPIllegalAttrErr(ctxt,
7726 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007727 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007728 }
7729 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7730 xmlSchemaPIllegalAttrErr(ctxt,
7731 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007732 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007733 }
7734 attr = attr->next;
7735 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007736 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007737 /*
7738 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007739 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007740 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007741 attr = xmlSchemaGetPropNode(node, "memberTypes");
7742 if (attr != NULL) {
7743 const xmlChar *end;
7744 xmlChar *tmp;
7745 const xmlChar *localName, *nsName;
7746 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7747 xmlSchemaQNameRefPtr ref;
7748
7749 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7750 type->ref = cur;
7751 do {
7752 while (IS_BLANK_CH(*cur))
7753 cur++;
7754 end = cur;
7755 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7756 end++;
7757 if (end == cur)
7758 break;
7759 tmp = xmlStrndup(cur, end - cur);
7760 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7761 NULL, attr, BAD_CAST tmp, &nsName, NULL, &localName) == 0) {
7762 /*
7763 * Create the member type link.
7764 */
7765 link = (xmlSchemaTypeLinkPtr)
7766 xmlMalloc(sizeof(xmlSchemaTypeLink));
7767 if (link == NULL) {
7768 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7769 "allocating a type link", NULL);
7770 return (-1);
7771 }
7772 link->type = NULL;
7773 link->next = NULL;
7774 if (lastLink == NULL)
7775 type->memberTypes = link;
7776 else
7777 lastLink->next = link;
7778 lastLink = link;
7779 /*
7780 * Create a reference item.
7781 */
7782 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
7783 localName, nsName);
7784 if (ref == NULL) {
7785 FREE_AND_NULL(tmp)
7786 return (-1);
7787 }
7788 /*
7789 * Assign the reference to the link, it will be resolved
7790 * later during fixup of the union simple type.
7791 */
7792 link->type = (xmlSchemaTypePtr) ref;
7793 }
7794 FREE_AND_NULL(tmp)
7795 cur = end;
7796 } while (*cur != 0);
7797
7798 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007799 /*
7800 * And now for the children...
7801 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007802 child = node->children;
7803 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007804 /*
7805 * Add the annotation to the simple type ancestor.
7806 */
7807 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7808 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007809 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007810 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007811 if (IS_SCHEMA(child, "simpleType")) {
7812 xmlSchemaTypePtr subtype, last = NULL;
7813
7814 /*
7815 * Anchor the member types in the "subtypes" field of the
7816 * simple type.
7817 */
7818 while (IS_SCHEMA(child, "simpleType")) {
7819 subtype = (xmlSchemaTypePtr)
7820 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7821 if (subtype != NULL) {
7822 if (last == NULL) {
7823 type->subtypes = subtype;
7824 last = subtype;
7825 } else {
7826 last->next = subtype;
7827 last = subtype;
7828 }
7829 last->next = NULL;
7830 }
7831 child = child->next;
7832 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007833 }
7834 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007835 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007836 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7837 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
7838 }
7839 if ((attr == NULL) && (type->subtypes == NULL)) {
7840 /*
7841 * src-union-memberTypes-or-simpleTypes
7842 * Either the memberTypes [attribute] of the <union> element must
7843 * be non-empty or there must be at least one simpleType [child].
7844 */
7845 xmlSchemaPCustomErr(ctxt,
7846 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
7847 NULL, NULL, node,
7848 "Either the attribute 'memberTypes' or "
7849 "at least one <simpleType> child must be present", NULL);
7850 }
7851 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007852}
7853
7854/**
7855 * xmlSchemaParseList:
7856 * @ctxt: a schema validation context
7857 * @schema: the schema being built
7858 * @node: a subtree containing XML Schema informations
7859 *
7860 * parse a XML schema List definition
7861 * *WARNING* this interface is highly subject to change
7862 *
William M. Bracke7091952004-05-11 15:09:58 +00007863 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007864 * 1 in case of success.
7865 */
7866static xmlSchemaTypePtr
7867xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007868 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007869{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007870 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007871 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007872 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007873
7874 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7875 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007876 /* Not a component, don't create it. */
7877 type = ctxt->ctxtType;
7878 /*
7879 * Mark the type as being of variety "list".
7880 */
7881 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
William M. Brack2f2a6632004-08-20 23:09:47 +00007882 /*
7883 * Check for illegal attributes.
7884 */
7885 attr = node->properties;
7886 while (attr != NULL) {
7887 if (attr->ns == NULL) {
7888 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7889 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
7890 xmlSchemaPIllegalAttrErr(ctxt,
7891 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007892 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007893 }
7894 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7895 xmlSchemaPIllegalAttrErr(ctxt,
7896 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007897 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007898 }
7899 attr = attr->next;
7900 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007901
7902 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7903
William M. Brack2f2a6632004-08-20 23:09:47 +00007904 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007905 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
7906 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00007907 */
7908 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007909 node, "itemType", &(type->refNs), NULL, &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00007910 /*
7911 * And now for the children...
7912 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007913 child = node->children;
7914 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007915 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7916 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007917 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007918 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007919 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007920 /*
7921 * src-list-itemType-or-simpleType
7922 * Either the itemType [attribute] or the <simpleType> [child] of
7923 * the <list> element must be present, but not both.
7924 */
7925 if (type->ref != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007926 xmlSchemaPCustomErr(ctxt,
7927 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007928 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00007929 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007930 "are mutually exclusive", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00007931 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007932 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007933 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007934 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007935 } else if (type->ref == NULL) {
7936 xmlSchemaPCustomErr(ctxt,
7937 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
7938 NULL, NULL, node,
7939 "Either the attribute 'itemType' or the <simpleType> child "
7940 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007941 }
7942 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007943 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007944 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7945 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007946 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007947 if ((type->ref == NULL) &&
7948 (type->subtypes == NULL) &&
7949 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
7950 xmlSchemaPCustomErr(ctxt,
7951 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
7952 NULL, NULL, node,
7953 "Either the attribute 'itemType' or the <simpleType> child "
7954 "must be present", NULL);
7955 }
7956 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007957}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007958
Daniel Veillard4255d502002-04-16 15:50:10 +00007959/**
7960 * xmlSchemaParseSimpleType:
7961 * @ctxt: a schema validation context
7962 * @schema: the schema being built
7963 * @node: a subtree containing XML Schema informations
7964 *
7965 * parse a XML schema Simple Type definition
7966 * *WARNING* this interface is highly subject to change
7967 *
William M. Bracke7091952004-05-11 15:09:58 +00007968 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00007969 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00007970 */
7971static xmlSchemaTypePtr
7972xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007973 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007974{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007975 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007976 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007977 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007978 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007979
7980 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7981 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007982
Daniel Veillardc0826a72004-08-10 14:17:33 +00007983 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007984 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007985 if (attr == NULL) {
7986 xmlSchemaPMissingAttrErr(ctxt,
7987 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007988 NULL, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007989 "name", NULL);
7990 return (NULL);
7991 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007992 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007993 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007994 return (NULL);
7995 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007996 }
7997
7998 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007999 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008000
Daniel Veillard01fa6152004-06-29 17:04:39 +00008001 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008002 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008003 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008004 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008005 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008006 if (type == NULL)
8007 return (NULL);
8008 type->node = node;
8009 type->type = XML_SCHEMA_TYPE_SIMPLE;
8010 /*
8011 * Check for illegal attributes.
8012 */
8013 attr = node->properties;
8014 while (attr != NULL) {
8015 if (attr->ns == NULL) {
8016 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
8017 xmlSchemaPIllegalAttrErr(ctxt,
8018 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008019 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008020 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008021 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8022 xmlSchemaPIllegalAttrErr(ctxt,
8023 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008024 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008025 }
8026 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008027 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008028 } else {
8029 /*
8030 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008031 *
8032 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008033 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008034 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008035 if (type == NULL)
8036 return (NULL);
8037 type->node = node;
8038 type->type = XML_SCHEMA_TYPE_SIMPLE;
8039 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8040 /*
8041 * Check for illegal attributes.
8042 */
8043 attr = node->properties;
8044 while (attr != NULL) {
8045 if (attr->ns == NULL) {
8046 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8047 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008048 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008049 xmlSchemaPIllegalAttrErr(ctxt,
8050 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008051 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008052 }
8053 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8054 xmlSchemaPIllegalAttrErr(ctxt,
8055 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008056 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008057 }
8058 attr = attr->next;
8059 }
8060 /*
8061 * Attribute "final".
8062 */
8063 attr = xmlSchemaGetPropNode(node, "final");
8064 if (attr == NULL) {
8065 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
8066 } else {
8067 attrValue = xmlSchemaGetProp(ctxt, node, "final");
8068 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8069 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
8070 XML_SCHEMAS_TYPE_FINAL_LIST,
8071 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8072
8073 xmlSchemaPSimpleTypeErr(ctxt,
8074 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008075 NULL, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00008076 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008077 attrValue, NULL, NULL, NULL);
8078 }
8079 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008080 }
8081 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008082 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008083 /*
8084 * And now for the children...
8085 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008086 oldCtxtType = ctxt->ctxtType;
8087 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008088 ctxt->ctxtType = type;
8089 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008090 child = node->children;
8091 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008092 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8093 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008094 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008095 if (child == NULL) {
8096 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8097 NULL, type, node, child, NULL,
8098 "(annotation?, (restriction | list | union))");
8099 } else if (IS_SCHEMA(child, "restriction")) {
8100 xmlSchemaParseRestriction(ctxt, schema, child,
8101 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008102 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008103 } else if (IS_SCHEMA(child, "list")) {
8104 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008105 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008106 } else if (IS_SCHEMA(child, "union")) {
8107 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008108 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008109 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008110 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008111 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008112 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008113 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008114 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008115 ctxt->parentItem = oldParentItem;
8116 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008117
Daniel Veillard4255d502002-04-16 15:50:10 +00008118 return (type);
8119}
8120
Daniel Veillard4255d502002-04-16 15:50:10 +00008121/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008122 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008123 * @ctxt: a schema validation context
8124 * @schema: the schema being built
8125 * @node: a subtree containing XML Schema informations
8126 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008127 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008128 * *WARNING* this interface is highly subject to change
8129 *
William M. Bracke7091952004-05-11 15:09:58 +00008130 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008131 * 1 in case of success.
8132 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008133static xmlSchemaTreeItemPtr
8134xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8135 xmlSchemaPtr schema,
8136 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008137{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008138 xmlSchemaParticlePtr item;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008139 xmlNodePtr child = NULL;
8140 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008141 const xmlChar *ref = NULL, *refNs = NULL;
8142 int min, max;
8143
8144 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8145 return (NULL);
8146
8147 attr = xmlSchemaGetPropNode(node, "ref");
8148 if (attr == NULL) {
8149 xmlSchemaPMissingAttrErr(ctxt,
8150 XML_SCHEMAP_S4S_ATTR_MISSING,
8151 NULL, NULL, node,
8152 "ref", NULL);
8153 return (NULL);
8154 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
8155 attr, &refNs, NULL, &ref) != 0) {
8156 return (NULL);
8157 }
8158 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8159 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8160 "(nonNegativeInteger | unbounded)");
8161 /*
8162 * Check for illegal attributes.
8163 */
8164 attr = node->properties;
8165 while (attr != NULL) {
8166 if (attr->ns == NULL) {
8167 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
8168 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8169 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8170 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
8171 xmlSchemaPIllegalAttrErr(ctxt,
8172 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8173 NULL, NULL, attr);
8174 }
8175 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8176 xmlSchemaPIllegalAttrErr(ctxt,
8177 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8178 NULL, NULL, attr);
8179 }
8180 attr = attr->next;
8181 }
8182 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8183 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8184 if (item == NULL)
8185 return (NULL);
8186 /*
8187 * Create a reference item as the term; it will be substituted for
8188 * the model group after the reference has been resolved.
8189 */
8190 item->children = (xmlSchemaTreeItemPtr)
8191 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8192 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8193 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8194 /*
8195 * And now for the children...
8196 */
8197 child = node->children;
8198 /* TODO: Is annotation even allowed for a model group reference? */
8199 if (IS_SCHEMA(child, "annotation")) {
8200 /*
8201 * TODO: What to do exactly with the annotation?
8202 */
8203 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8204 child = child->next;
8205 }
8206 if (child != NULL) {
8207 xmlSchemaPContentErr(ctxt,
8208 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8209 NULL, NULL, node, child, NULL,
8210 "(annotation?)");
8211 }
8212 /*
8213 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8214 */
8215 if ((min == 0) && (max == 0))
8216 return (NULL);
8217 if (ctxt->assemble != NULL)
8218 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8219 return ((xmlSchemaTreeItemPtr) item);
8220}
8221
8222/**
8223 * xmlSchemaParseModelGroupDefinition:
8224 * @ctxt: a schema validation context
8225 * @schema: the schema being built
8226 * @node: a subtree containing XML Schema informations
8227 *
8228 * Parses a XML schema model group definition.
8229 * *WARNING* this interface is highly subject to change
8230 *
8231 * Returns -1 in case of error, 0 if the declaration is improper and
8232 * 1 in case of success.
8233 */
8234static xmlSchemaModelGroupDefPtr
8235xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8236 xmlSchemaPtr schema,
8237 xmlNodePtr node)
8238{
8239 xmlSchemaModelGroupDefPtr item;
8240 xmlNodePtr child = NULL;
8241 xmlAttrPtr attr;
8242 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008243
8244 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008245 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008246
8247 attr = xmlSchemaGetPropNode(node, "name");
8248 if (attr == NULL) {
8249 xmlSchemaPMissingAttrErr(ctxt,
8250 XML_SCHEMAP_S4S_ATTR_MISSING,
8251 NULL, NULL, node,
8252 "name", NULL);
8253 return (NULL);
8254 } else if (xmlSchemaPValAttrNode(ctxt,
8255 NULL, NULL, attr,
8256 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8257 return (NULL);
8258 }
8259 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8260 if (item == NULL)
8261 return (NULL);
8262 /*
8263 * Check for illegal attributes.
8264 */
8265 attr = node->properties;
8266 while (attr != NULL) {
8267 if (attr->ns == NULL) {
8268 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8269 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
8270 xmlSchemaPIllegalAttrErr(ctxt,
8271 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8272 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008273 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008274 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8275 xmlSchemaPIllegalAttrErr(ctxt,
8276 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8277 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008278 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008279 attr = attr->next;
8280 }
8281 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8282 /*
8283 * And now for the children...
8284 */
8285 child = node->children;
8286 if (IS_SCHEMA(child, "annotation")) {
8287 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8288 child = child->next;
8289 }
8290 if (IS_SCHEMA(child, "all")) {
8291 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8292 XML_SCHEMA_TYPE_ALL, 0);
8293 child = child->next;
8294 } else if (IS_SCHEMA(child, "choice")) {
8295 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8296 XML_SCHEMA_TYPE_CHOICE, 0);
8297 child = child->next;
8298 } else if (IS_SCHEMA(child, "sequence")) {
8299 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8300 XML_SCHEMA_TYPE_SEQUENCE, 0);
8301 child = child->next;
8302 }
8303 if (child != NULL) {
8304 xmlSchemaPContentErr(ctxt,
8305 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8306 NULL, NULL, node, child, NULL,
8307 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008308 }
8309
8310 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008311}
8312
8313/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008314 * xmlSchemaCleanupDoc:
8315 * @ctxt: a schema validation context
8316 * @node: the root of the document.
8317 *
8318 * removes unwanted nodes in a schemas document tree
8319 */
8320static void
8321xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8322{
8323 xmlNodePtr delete, cur;
8324
8325 if ((ctxt == NULL) || (root == NULL)) return;
8326
8327 /*
8328 * Remove all the blank text nodes
8329 */
8330 delete = NULL;
8331 cur = root;
8332 while (cur != NULL) {
8333 if (delete != NULL) {
8334 xmlUnlinkNode(delete);
8335 xmlFreeNode(delete);
8336 delete = NULL;
8337 }
8338 if (cur->type == XML_TEXT_NODE) {
8339 if (IS_BLANK_NODE(cur)) {
8340 if (xmlNodeGetSpacePreserve(cur) != 1) {
8341 delete = cur;
8342 }
8343 }
8344 } else if ((cur->type != XML_ELEMENT_NODE) &&
8345 (cur->type != XML_CDATA_SECTION_NODE)) {
8346 delete = cur;
8347 goto skip_children;
8348 }
8349
8350 /*
8351 * Skip to next node
8352 */
8353 if (cur->children != NULL) {
8354 if ((cur->children->type != XML_ENTITY_DECL) &&
8355 (cur->children->type != XML_ENTITY_REF_NODE) &&
8356 (cur->children->type != XML_ENTITY_NODE)) {
8357 cur = cur->children;
8358 continue;
8359 }
8360 }
8361 skip_children:
8362 if (cur->next != NULL) {
8363 cur = cur->next;
8364 continue;
8365 }
8366
8367 do {
8368 cur = cur->parent;
8369 if (cur == NULL)
8370 break;
8371 if (cur == root) {
8372 cur = NULL;
8373 break;
8374 }
8375 if (cur->next != NULL) {
8376 cur = cur->next;
8377 break;
8378 }
8379 } while (cur != NULL);
8380 }
8381 if (delete != NULL) {
8382 xmlUnlinkNode(delete);
8383 xmlFreeNode(delete);
8384 delete = NULL;
8385 }
8386}
8387
William M. Brack2f2a6632004-08-20 23:09:47 +00008388
8389/**
8390 * xmlSchemaImportSchema
8391 *
8392 * @ctxt: a schema validation context
8393 * @schemaLocation: an URI defining where to find the imported schema
8394 *
8395 * import a XML schema
8396 * *WARNING* this interface is highly subject to change
8397 *
8398 * Returns -1 in case of error and 1 in case of success.
8399 */
8400#if 0
8401static xmlSchemaImportPtr
8402xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8403 const xmlChar *schemaLocation)
8404{
8405 xmlSchemaImportPtr import;
8406 xmlSchemaParserCtxtPtr newctxt;
8407
8408 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8409 if (newctxt == NULL) {
8410 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8411 NULL);
8412 return (NULL);
8413 }
8414 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8415 /* Keep the same dictionnary for parsing, really */
8416 xmlDictReference(ctxt->dict);
8417 newctxt->dict = ctxt->dict;
8418 newctxt->includes = 0;
8419 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8420
8421 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8422 ctxt->userData);
8423
8424 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8425 if (import == NULL) {
8426 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8427 NULL);
8428 xmlSchemaFreeParserCtxt(newctxt);
8429 return (NULL);
8430 }
8431
8432 memset(import, 0, sizeof(xmlSchemaImport));
8433 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8434 import->schema = xmlSchemaParse(newctxt);
8435
8436 if (import->schema == NULL) {
8437 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008438 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008439 "Failed to import schema from location \"%s\".\n",
8440 schemaLocation, NULL);
8441
8442 xmlSchemaFreeParserCtxt(newctxt);
8443 /* The schemaLocation is held by the dictionary.
8444 if (import->schemaLocation != NULL)
8445 xmlFree((xmlChar *)import->schemaLocation);
8446 */
8447 xmlFree(import);
8448 return NULL;
8449 }
8450
8451 xmlSchemaFreeParserCtxt(newctxt);
8452 return import;
8453}
8454#endif
8455
8456static void
8457xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8458{
8459 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8460 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8461
8462 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8463 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8464
8465 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8466 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8467 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8468 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8469 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8470 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8471 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8472 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8473
8474 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8475 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8476 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8477 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8478 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8479 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8480}
8481
8482static void
8483xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
8484 xmlSchemaPtr schema,
8485 xmlNodePtr node)
8486{
8487 xmlAttrPtr attr;
8488 const xmlChar *val;
8489
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008490 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8491 if (schema->version == NULL)
8492 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8493 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8494 else
8495 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
8496 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8497
William M. Brack2f2a6632004-08-20 23:09:47 +00008498 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
8499 if (attr != NULL) {
8500 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8501 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
8502 XML_SCHEMAS_QUALIF_ELEM) != 0) {
8503 xmlSchemaPSimpleTypeErr(ctxt,
8504 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
8505 NULL, NULL, (xmlNodePtr) attr, NULL,
8506 "(qualified | unqualified)", val, NULL, NULL, NULL);
8507 }
8508 }
8509
8510 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
8511 if (attr != NULL) {
8512 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8513 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
8514 XML_SCHEMAS_QUALIF_ATTR) != 0) {
8515 xmlSchemaPSimpleTypeErr(ctxt,
8516 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
8517 NULL, NULL, (xmlNodePtr) attr, NULL,
8518 "(qualified | unqualified)", val, NULL, NULL, NULL);
8519 }
8520 }
8521
8522 attr = xmlSchemaGetPropNode(node, "finalDefault");
8523 if (attr != NULL) {
8524 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8525 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8526 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8527 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8528 -1,
8529 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8530 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8531 xmlSchemaPSimpleTypeErr(ctxt,
8532 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8533 NULL, NULL, (xmlNodePtr) attr, NULL,
8534 "(#all | List of (extension | restriction | list | union))",
8535 val, NULL, NULL, NULL);
8536 }
8537 }
8538
8539 attr = xmlSchemaGetPropNode(node, "blockDefault");
8540 if (attr != NULL) {
8541 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8542 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8543 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8544 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8545 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8546 xmlSchemaPSimpleTypeErr(ctxt,
8547 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8548 NULL, NULL, (xmlNodePtr) attr, NULL,
8549 "(#all | List of (extension | restriction | substitution))",
8550 val, NULL, NULL, NULL);
8551 }
8552 }
8553}
8554
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008555/**
8556 * xmlSchemaParseSchemaTopLevel:
8557 * @ctxt: a schema validation context
8558 * @schema: the schemas
8559 * @nodes: the list of top level nodes
8560 *
8561 * Returns the internal XML Schema structure built from the resource or
8562 * NULL in case of error
8563 */
8564static void
8565xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8566 xmlSchemaPtr schema, xmlNodePtr nodes)
8567{
8568 xmlNodePtr child;
8569 xmlSchemaAnnotPtr annot;
8570
8571 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8572 return;
8573
8574 child = nodes;
8575 while ((IS_SCHEMA(child, "include")) ||
8576 (IS_SCHEMA(child, "import")) ||
8577 (IS_SCHEMA(child, "redefine")) ||
8578 (IS_SCHEMA(child, "annotation"))) {
8579 if (IS_SCHEMA(child, "annotation")) {
8580 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8581 if (schema->annot == NULL)
8582 schema->annot = annot;
8583 else
8584 xmlSchemaFreeAnnot(annot);
8585 } else if (IS_SCHEMA(child, "import")) {
8586 xmlSchemaParseImport(ctxt, schema, child);
8587 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008588 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008589 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008590 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008591 } else if (IS_SCHEMA(child, "redefine")) {
8592 TODO
8593 }
8594 child = child->next;
8595 }
8596 while (child != NULL) {
8597 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008598 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008599 child = child->next;
8600 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008601 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008602 child = child->next;
8603 } else if (IS_SCHEMA(child, "element")) {
8604 xmlSchemaParseElement(ctxt, schema, child, 1);
8605 child = child->next;
8606 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008607 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008608 child = child->next;
8609 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008610 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008611 child = child->next;
8612 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008613 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008614 child = child->next;
8615 } else if (IS_SCHEMA(child, "notation")) {
8616 xmlSchemaParseNotation(ctxt, schema, child);
8617 child = child->next;
8618 } else {
8619 xmlSchemaPErr2(ctxt, NULL, child,
8620 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008621 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008622 child->name, NULL);
8623 child = child->next;
8624 }
8625 while (IS_SCHEMA(child, "annotation")) {
8626 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8627 if (schema->annot == NULL)
8628 schema->annot = annot;
8629 else
8630 xmlSchemaFreeAnnot(annot);
8631 child = child->next;
8632 }
8633 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008634 ctxt->parentItem = NULL;
8635 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008636}
8637
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008638static xmlSchemaImportPtr
8639xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
8640 xmlHashTablePtr *imports,
8641 const xmlChar *nsName)
8642{
8643 xmlSchemaImportPtr ret;
8644
8645 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008646 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008647 if (*imports == NULL) {
8648 xmlSchemaPCustomErr(ctxt,
8649 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8650 NULL, NULL, (xmlNodePtr) ctxt->doc,
8651 "Internal error: failed to build the import table",
8652 NULL);
8653 return (NULL);
8654 }
8655 }
8656 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8657 if (ret == NULL) {
8658 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8659 return (NULL);
8660 }
8661 memset(ret, 0, sizeof(xmlSchemaImport));
8662 if (nsName == NULL)
8663 nsName = XML_SCHEMAS_NO_NAMESPACE;
8664 xmlHashAddEntry(*imports, nsName, ret);
8665
8666 return (ret);
8667}
8668
8669static int
8670xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008671 xmlSchemaPtr schema,
8672 xmlNodePtr node,
8673 const xmlChar *nsName,
8674 const xmlChar *location,
8675 xmlDocPtr *doc,
8676 const xmlChar **targetNamespace,
8677 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008678{
8679 xmlParserCtxtPtr parserCtxt;
8680 xmlSchemaImportPtr import;
8681 const xmlChar *ns;
8682 xmlNodePtr root;
8683
8684 /*
8685 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8686 * <xsi:noNamespaceSchemaLocation>.
8687 */
8688 *doc = NULL;
8689 /*
8690 * Given that the schemaLocation [attribute] is only a hint, it is open
8691 * to applications to ignore all but the first <import> for a given
8692 * namespace, regardless of the ·actual value· of schemaLocation, but
8693 * such a strategy risks missing useful information when new
8694 * schemaLocations are offered.
8695 *
8696 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8697 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8698 * valid or not.
8699 * We will follow XSV here.
8700 */
8701 if (location == NULL) {
8702 /*
8703 * Schema Document Location Strategy:
8704 *
8705 * 3 Based on the namespace name, identify an existing schema document,
8706 * either as a resource which is an XML document or a <schema> element
8707 * information item, in some local schema repository;
8708 *
8709 * 5 Attempt to resolve the namespace name to locate such a resource.
8710 *
8711 * NOTE: Those stategies are not supported, so we will skip.
8712 */
8713 return (0);
8714 }
8715 if (nsName == NULL)
8716 ns = XML_SCHEMAS_NO_NAMESPACE;
8717 else
8718 ns = nsName;
8719
8720 import = xmlHashLookup(schema->schemasImports, ns);
8721 if (import != NULL) {
8722 /*
8723 * There was a valid resource for the specified namespace already
8724 * defined, so skip.
8725 * TODO: This might be changed someday to allow import of
8726 * components from multiple documents for a single target namespace.
8727 */
8728 return (0);
8729 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008730
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008731 /*
8732 * Schema Document Location Strategy:
8733 *
8734 * 2 Based on the location URI, identify an existing schema document,
8735 * either as a resource which is an XML document or a <schema> element
8736 * information item, in some local schema repository;
8737 *
8738 * 4 Attempt to resolve the location URI, to locate a resource on the
8739 * web which is or contains or references a <schema> element;
8740 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8741 *
8742 */
8743 if ((absolute == 0) && (node != NULL)) {
8744 xmlChar *base, *URI;
8745
8746 base = xmlNodeGetBase(node->doc, node);
8747 if (base == NULL) {
8748 URI = xmlBuildURI(location, node->doc->URL);
8749 } else {
8750 URI = xmlBuildURI(location, base);
8751 xmlFree(base);
8752 }
8753 if (URI != NULL) {
8754 location = xmlDictLookup(ctxt->dict, URI, -1);
8755 xmlFree(URI);
8756 }
8757 }
8758 parserCtxt = xmlNewParserCtxt();
8759 if (parserCtxt == NULL) {
8760 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8761 "allocating a parser context", NULL);
8762 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008763 }
8764
8765 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
8766 xmlDictFree(parserCtxt->dict);
8767 parserCtxt->dict = ctxt->dict;
8768 xmlDictReference(parserCtxt->dict);
8769 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008770
8771 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
8772 NULL, SCHEMAS_PARSE_OPTIONS);
8773
8774 /*
8775 * 2.1 The referent is (a fragment of) a resource which is an
8776 * XML document (see clause 1.1), which in turn corresponds to
8777 * a <schema> element information item in a well-formed information
8778 * set, which in turn corresponds to a valid schema.
8779 * TODO: What to do with the "fragment" stuff?
8780 *
8781 * 2.2 The referent is a <schema> element information item in
8782 * a well-formed information set, which in turn corresponds
8783 * to a valid schema.
8784 * NOTE: 2.2 won't apply, since only XML documents will be processed
8785 * here.
8786 */
8787 if (*doc == NULL) {
8788 xmlErrorPtr lerr;
8789 /*
8790 * It is *not* an error for the application schema reference
8791 * strategy to fail.
8792 *
8793 * If the doc is NULL and the parser error is an IO error we
8794 * will assume that the resource could not be located or accessed.
8795 *
8796 * TODO: Try to find specific error codes to react only on
8797 * localisation failures.
8798 *
8799 * TODO, FIXME: Check the spec: is a namespace added to the imported
8800 * namespaces, even if the schemaLocation did not provide
8801 * a resource? I guess so, since omitting the "schemaLocation"
8802 * attribute, imports a namespace as well.
8803 */
8804 lerr = xmlGetLastError();
8805 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
8806 xmlFreeParserCtxt(parserCtxt);
8807 return(0);
8808 }
8809
8810 xmlSchemaPCustomErr(ctxt,
8811 XML_SCHEMAP_SRC_IMPORT_2_1,
8812 NULL, NULL, node,
8813 "Failed to parse the resource '%s' for import",
8814 location);
8815 xmlFreeParserCtxt(parserCtxt);
8816 return(XML_SCHEMAP_SRC_IMPORT_2_1);
8817 }
8818 xmlFreeParserCtxt(parserCtxt);
8819
8820 root = xmlDocGetRootElement(*doc);
8821 if (root == NULL) {
8822 xmlSchemaPCustomErr(ctxt,
8823 XML_SCHEMAP_SRC_IMPORT_2_1,
8824 NULL, NULL, node,
8825 "The XML document '%s' to be imported has no document "
8826 "element", location);
8827 xmlFreeDoc(*doc);
8828 *doc = NULL;
8829 return (XML_SCHEMAP_SRC_IMPORT_2_1);
8830 }
8831
8832 xmlSchemaCleanupDoc(ctxt, root);
8833
8834 if (!IS_SCHEMA(root, "schema")) {
8835 xmlSchemaPCustomErr(ctxt,
8836 XML_SCHEMAP_SRC_IMPORT_2_1,
8837 NULL, NULL, node,
8838 "The XML document '%s' to be imported is not a XML schema document",
8839 location);
8840 xmlFreeDoc(*doc);
8841 *doc = NULL;
8842 return (XML_SCHEMAP_SRC_IMPORT_2_1);
8843 }
8844 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
8845 /*
8846 * Schema Representation Constraint: Import Constraints and Semantics
8847 */
8848 if (nsName == NULL) {
8849 if (*targetNamespace != NULL) {
8850 xmlSchemaPCustomErr(ctxt,
8851 XML_SCHEMAP_SRC_IMPORT_3_2,
8852 NULL, NULL, node,
8853 "The XML schema to be imported is not expected "
8854 "to have a target namespace; this differs from "
8855 "its target namespace of '%s'", *targetNamespace);
8856 xmlFreeDoc(*doc);
8857 *doc = NULL;
8858 return (XML_SCHEMAP_SRC_IMPORT_3_2);
8859 }
8860 } else {
8861 if (*targetNamespace == NULL) {
8862 xmlSchemaPCustomErr(ctxt,
8863 XML_SCHEMAP_SRC_IMPORT_3_1,
8864 NULL, NULL, node,
8865 "The XML schema to be imported is expected to have a target "
8866 "namespace of '%s'", nsName);
8867 xmlFreeDoc(*doc);
8868 *doc = NULL;
8869 return (XML_SCHEMAP_SRC_IMPORT_3_1);
8870 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
8871 xmlSchemaPCustomErrExt(ctxt,
8872 XML_SCHEMAP_SRC_IMPORT_3_1,
8873 NULL, NULL, node,
8874 "The XML schema to be imported is expected to have a "
8875 "target namespace of '%s'; this differs from "
8876 "its target namespace of '%s'",
8877 nsName, *targetNamespace, NULL);
8878 xmlFreeDoc(*doc);
8879 *doc = NULL;
8880 return (XML_SCHEMAP_SRC_IMPORT_3_1);
8881 }
8882 }
8883
8884 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
8885 if (import == NULL) {
8886 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
8887 NULL, NULL, NULL,
8888 "Internal error: xmlSchemaAcquireSchemaDoc, "
8889 "failed to build import table", NULL);
8890 xmlFreeDoc(*doc);
8891 *doc = NULL;
8892 return (-1);
8893 }
8894 import->schemaLocation = location;
8895 import->doc = *doc;
8896 return (0);
8897}
William M. Brack2f2a6632004-08-20 23:09:47 +00008898
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008899static void
8900xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
8901 xmlSchemaPtr schema,
8902 const xmlChar *targetNamespace,
8903 xmlNodePtr node)
8904{
8905 const xmlChar *oldURL, **oldLocImps, *oldTNS;
8906 int oldFlags, oldNumLocImps, oldSizeLocImps;
8907
8908 /*
8909 * Save and reset the context & schema.
8910 */
8911 oldURL = pctxt->URL;
8912 /* TODO: Is using the doc->URL here correct? */
8913 pctxt->URL = node->doc->URL;
8914 oldLocImps = pctxt->localImports;
8915 pctxt->localImports = NULL;
8916 oldNumLocImps = pctxt->nbLocalImports;
8917 pctxt->nbLocalImports = 0;
8918 oldSizeLocImps = pctxt->sizeLocalImports;
8919 pctxt->sizeLocalImports = 0;
8920 oldFlags = schema->flags;
8921 xmlSchemaClearSchemaDefaults(schema);
8922 oldTNS = schema->targetNamespace;
8923 schema->targetNamespace = targetNamespace;
8924 /*
8925 * Parse the schema.
8926 */
8927 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
8928 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
8929 /*
8930 * Restore the context & schema.
8931 */
8932 schema->flags = oldFlags;
8933 schema->targetNamespace = oldTNS;
8934 if (pctxt->localImports != NULL)
8935 xmlFree((xmlChar *) pctxt->localImports);
8936 pctxt->localImports = oldLocImps;
8937 pctxt->nbLocalImports = oldNumLocImps;
8938 pctxt->sizeLocalImports = oldSizeLocImps;
8939 pctxt->URL = oldURL;
8940}
8941
William M. Brack2f2a6632004-08-20 23:09:47 +00008942/**
8943 * xmlSchemaParseImport:
8944 * @ctxt: a schema validation context
8945 * @schema: the schema being built
8946 * @node: a subtree containing XML Schema informations
8947 *
8948 * parse a XML schema Import definition
8949 * *WARNING* this interface is highly subject to change
8950 *
8951 * Returns 0 in case of success, a positive error code if
8952 * not valid and -1 in case of an internal error.
8953 */
8954static int
8955xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8956 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008957{
8958 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008959 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008960 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008961 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00008962 xmlAttrPtr attr;
8963 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008964 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00008965
8966 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8967 return (-1);
8968
8969 /*
8970 * Check for illegal attributes.
8971 */
8972 attr = node->properties;
8973 while (attr != NULL) {
8974 if (attr->ns == NULL) {
8975 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8976 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
8977 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
8978 xmlSchemaPIllegalAttrErr(ctxt,
8979 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8980 NULL, NULL, attr);
8981 }
8982 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8983 xmlSchemaPIllegalAttrErr(ctxt,
8984 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8985 NULL, NULL, attr);
8986 }
8987 attr = attr->next;
8988 }
8989 /*
8990 * Extract and validate attributes.
8991 */
8992 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
8993 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008994 &namespaceName) != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008995 xmlSchemaPSimpleTypeErr(ctxt,
8996 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
8997 NULL, NULL, node,
8998 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008999 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009000 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9001 }
9002
9003 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9004 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
9005 &schemaLocation) != 0) {
9006 xmlSchemaPSimpleTypeErr(ctxt,
9007 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9008 NULL, NULL, node,
9009 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009010 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009011 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
9012 }
9013 /*
9014 * And now for the children...
9015 */
9016 child = node->children;
9017 if (IS_SCHEMA(child, "annotation")) {
9018 /*
9019 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009020 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009021 */
9022 child = child->next;
9023 }
9024 if (child != NULL) {
9025 xmlSchemaPContentErr(ctxt,
9026 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9027 NULL, NULL, node, child, NULL,
9028 "(annotation?)");
9029 }
9030 /*
9031 * Apply additional constraints.
9032 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009033 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009034 /*
9035 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9036 * must not match the ·actual value· of the enclosing <schema>'s
9037 * targetNamespace [attribute].
9038 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009039 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009040 xmlSchemaPCustomErr(ctxt,
9041 XML_SCHEMAP_SRC_IMPORT_1_1,
9042 NULL, NULL, node,
9043 "The value of the attribute 'namespace' must not match "
9044 "the target namespace '%s' of the importing schema",
9045 schema->targetNamespace);
9046 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9047 }
9048 } else {
9049 /*
9050 * 1.2 If the namespace [attribute] is not present, then the enclosing
9051 * <schema> must have a targetNamespace [attribute].
9052 */
9053 if (schema->targetNamespace == NULL) {
9054 xmlSchemaPCustomErr(ctxt,
9055 XML_SCHEMAP_SRC_IMPORT_1_2,
9056 NULL, NULL, node,
9057 "The attribute 'namespace' must be existent if "
9058 "the importing schema has no target namespace",
9059 NULL);
9060 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9061 }
9062 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009063 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009064 * Add the namespace to the list of locally imported namespace.
9065 */
9066 if (ctxt->localImports == NULL) {
9067 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
9068 sizeof(const xmlChar*));
9069 ctxt->sizeLocalImports = 10;
9070 ctxt->nbLocalImports = 0;
9071 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9072 ctxt->sizeLocalImports *= 2;
9073 ctxt->localImports = (const xmlChar **) xmlRealloc(
9074 (xmlChar **) ctxt->localImports,
9075 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9076 }
9077 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9078 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009079 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009080 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009081 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009082 schemaLocation, &doc, &targetNamespace, 0);
9083 if (ret != 0) {
9084 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009085 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009086 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009087 } else if (doc != NULL) {
9088 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9089 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009090 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009091
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009092 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009093}
9094
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009095/**
9096 * xmlSchemaParseInclude:
9097 * @ctxt: a schema validation context
9098 * @schema: the schema being built
9099 * @node: a subtree containing XML Schema informations
9100 *
9101 * parse a XML schema Include definition
9102 *
William M. Bracke7091952004-05-11 15:09:58 +00009103 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009104 * 1 in case of success.
9105 */
9106static int
9107xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9108 xmlNodePtr node)
9109{
9110 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009111 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009112 xmlDocPtr doc = NULL;
9113 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009114 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009115 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009116 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009117 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009118
9119
9120 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9121 return (-1);
9122
9123 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009124 * Check for illegal attributes.
9125 */
9126 attr = node->properties;
9127 while (attr != NULL) {
9128 if (attr->ns == NULL) {
9129 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9130 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
9131 xmlSchemaPIllegalAttrErr(ctxt,
9132 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9133 NULL, NULL, attr);
9134 }
9135 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9136 xmlSchemaPIllegalAttrErr(ctxt,
9137 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9138 NULL, NULL, attr);
9139 }
9140 attr = attr->next;
9141 }
9142 /*
9143 * Extract and validate attributes.
9144 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009145 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009146 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009147 * Preliminary step, extract the URI-Reference for the include and
9148 * make an URI from the base.
9149 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009150 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9151 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009152 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009153 xmlChar *uri = NULL;
9154
9155 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9156 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009157 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009158 base = xmlNodeGetBase(node->doc, node);
9159 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009160 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009161 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009162 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009163 xmlFree(base);
9164 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009165 if (uri == NULL) {
9166 xmlSchemaPErr(ctxt,
9167 node,
9168 XML_SCHEMAP_INTERNAL,
9169 "Internal error: xmlSchemaParseInclude, "
9170 "could not build an URI from the schemaLocation.\n",
9171 NULL, NULL);
9172 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009173 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009174 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9175 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009176 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009177 xmlSchemaPMissingAttrErr(ctxt,
9178 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9179 NULL, NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009180 goto exit_invalid;
9181 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009182 /*
9183 * And now for the children...
9184 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009185 child = node->children;
9186 while (IS_SCHEMA(child, "annotation")) {
9187 /*
9188 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009189 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009190 */
9191 child = child->next;
9192 }
9193 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009194 xmlSchemaPContentErr(ctxt,
9195 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9196 NULL, NULL, node, child, NULL,
9197 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009198 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009199 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009200 * Report self-inclusion.
9201 */
9202 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9203 xmlSchemaPCustomErr(ctxt,
9204 XML_SCHEMAP_SRC_INCLUDE,
9205 NULL, NULL, node,
9206 "The schema document '%s' cannot include itself.",
9207 schemaLocation);
9208 return (XML_SCHEMAP_SRC_INCLUDE);
9209 }
9210 /*
9211 * Check if this one was already processed to avoid incorrect
9212 * duplicate component errors and infinite circular inclusion.
9213 */
9214 include = schema->includes;
9215 while (include != NULL) {
9216 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9217 targetNamespace = include->origTargetNamespace;
9218 if (targetNamespace == NULL) {
9219 /*
9220 * Chameleon include: skip only if it was build for
9221 * the targetNamespace of the including schema.
9222 */
9223 if (xmlStrEqual(schema->targetNamespace,
9224 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009225 goto check_targetNamespace;
9226 }
9227 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009228 goto check_targetNamespace;
9229 }
9230 }
9231 include = include->next;
9232 }
9233 /*
9234 * First step is to parse the input document into an DOM/Infoset
9235 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009236 */
9237 parserCtxt = xmlNewParserCtxt();
9238 if (parserCtxt == NULL) {
9239 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9240 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009241 goto exit_failure;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009242 }
9243
9244 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9245 xmlDictFree(parserCtxt->dict);
9246 parserCtxt->dict = ctxt->dict;
9247 xmlDictReference(parserCtxt->dict);
9248 }
9249
9250 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
9251 NULL, SCHEMAS_PARSE_OPTIONS);
9252 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009253 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009254 /*
9255 * TODO: It is not an error for the ·actual value· of the
9256 * schemaLocation [attribute] to fail to resolve it all, in which
9257 * case no corresponding inclusion is performed.
9258 * So do we need a warning report here?
9259 */
9260 xmlSchemaPCustomErr(ctxt,
9261 XML_SCHEMAP_FAILED_LOAD,
9262 NULL, NULL, node,
9263 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009264 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009265 }
9266
9267 /*
9268 * Then extract the root of the schema
9269 */
9270 root = xmlDocGetRootElement(doc);
9271 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009272 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009273 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009274 NULL, NULL, node,
9275 "The included document '%s' has no document "
9276 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009277 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009278 }
9279
9280 /*
9281 * Remove all the blank text nodes
9282 */
9283 xmlSchemaCleanupDoc(ctxt, root);
9284
9285 /*
9286 * Check the schemas top level element
9287 */
9288 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009289 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009290 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009291 NULL, NULL, node,
9292 "The document '%s' to be included is not a schema document",
9293 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009294 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009295 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00009296
William M. Brack2f2a6632004-08-20 23:09:47 +00009297 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009298 /*
9299 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9300 * value· is identical to the ·actual value· of the targetNamespace
9301 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9302 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009303check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009304 if (targetNamespace != NULL) {
9305 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009306 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009307 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009308 NULL, NULL, node,
9309 "The target namespace of the included schema "
9310 "'%s' has to be absent, since the including schema "
9311 "has no target namespace",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009312 schemaLocation);
9313 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009314 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9315 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009316 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009317 NULL, NULL, node,
9318 "The target namespace '%s' of the included schema '%s' "
9319 "differs from '%s' of the including schema",
9320 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009321 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009322 }
9323 } else if (schema->targetNamespace != NULL) {
9324 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
9325 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
9326 } else
9327 wasConvertingNs = 1;
9328 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009329
9330 if (include != NULL)
9331 goto exit;
9332
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009333 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009334 * URGENT TODO: If the schema is a chameleon-include then copy the
9335 * components into the including schema and modify the targetNamespace
9336 * of those components, do nothing otherwise.
9337 * NOTE: This is currently worked-around by compiling the chameleon
9338 * for every destinct including targetNamespace; thus not performant at
9339 * the moment.
9340 * TODO: Check when the namespace in wildcards for chameleons needs
9341 * to be converted: before we built wildcard intersections or after.
9342 */
9343 /*
9344 * Register the include.
9345 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009346 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9347 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009348 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9349 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009350 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009351 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009352 include->next = schema->includes;
9353 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009354 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009355 * TODO: Use the resolved URI for the this location, since it might
9356 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009357 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009358 include->schemaLocation = schemaLocation;
9359 include->doc = doc;
9360 /*
9361 * In case of chameleons, the original target namespace will differ
9362 * from the resulting namespace.
9363 */
9364 include->origTargetNamespace = targetNamespace;
9365 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009366#ifdef DEBUG_INCLUDES
9367 if (targetNamespace != schema->targetNamespace)
9368 xmlGenericError(xmlGenericErrorContext,
9369 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9370 " into TNS '%s'\n", schemaLocation,
9371 targetNamespace, schema->targetNamespace);
9372 else
9373 xmlGenericError(xmlGenericErrorContext,
9374 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9375 targetNamespace);
9376#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009377 /*
9378 * Compile the included schema.
9379 */
9380 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9381
9382exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009383 /*
9384 * Remove the converting flag.
9385 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009386 if ((wasConvertingNs == 0) &&
9387 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009388 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009389 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009390
9391exit_invalid:
9392 if (doc != NULL) {
9393 if (include != NULL)
9394 include->doc = NULL;
9395 xmlFreeDoc(doc);
9396 }
9397 return (ctxt->err);
9398
9399exit_failure:
9400 if (doc != NULL) {
9401 if (include != NULL)
9402 include->doc = NULL;
9403 xmlFreeDoc(doc);
9404 }
9405 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009406}
9407
9408/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009409 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009410 * @ctxt: a schema validation context
9411 * @schema: the schema being built
9412 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009413 * @type: the "compositor" type
9414 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009415 *
9416 * parse a XML schema Sequence definition
9417 * *WARNING* this interface is highly subject to change
9418 *
William M. Bracke7091952004-05-11 15:09:58 +00009419 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009420 * 1 in case of success.
9421 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009422static xmlSchemaTreeItemPtr
9423xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9424 xmlNodePtr node, xmlSchemaTypeType type,
9425 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009426{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009427 xmlSchemaModelGroupPtr item;
9428 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009429 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009430 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009431 const xmlChar *oldcontainer, *container;
9432 int min, max;
Daniel Veillard4255d502002-04-16 15:50:10 +00009433
9434 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009435 return (NULL);
9436 /*
9437 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009438 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009439 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9440 if (item == NULL)
9441 return (NULL);
9442
9443 if (withParticle) {
9444 if (type == XML_SCHEMA_TYPE_ALL) {
9445 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
9446 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
9447 } else {
9448 /* choice + sequence */
9449 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
9450 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9451 "(nonNegativeInteger | unbounded)");
9452 }
9453 /*
9454 * Create a particle
9455 */
9456 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9457 if (particle == NULL)
9458 return (NULL);
9459 particle->children = (xmlSchemaTreeItemPtr) item;
9460 /*
9461 * Check for illegal attributes.
9462 */
9463 attr = node->properties;
9464 while (attr != NULL) {
9465 if (attr->ns == NULL) {
9466 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9467 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9468 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
9469 xmlSchemaPIllegalAttrErr(ctxt,
9470 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9471 NULL, NULL, attr);
9472 }
9473 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009474 xmlSchemaPIllegalAttrErr(ctxt,
9475 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009476 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009477 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009478 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009479 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009480 } else {
9481 /*
9482 * Check for illegal attributes.
9483 */
9484 attr = node->properties;
9485 while (attr != NULL) {
9486 if (attr->ns == NULL) {
9487 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9488 xmlSchemaPIllegalAttrErr(ctxt,
9489 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9490 NULL, NULL, attr);
9491 }
9492 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9493 xmlSchemaPIllegalAttrErr(ctxt,
9494 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9495 NULL, NULL, attr);
9496 }
9497 attr = attr->next;
9498 }
9499
William M. Brack2f2a6632004-08-20 23:09:47 +00009500 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009501
William M. Brack2f2a6632004-08-20 23:09:47 +00009502 /*
9503 * Extract and validate attributes.
9504 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009505 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009506 /*
9507 * And now for the children...
9508 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009509 child = node->children;
9510 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009511 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009512 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009513 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009514 oldcontainer = ctxt->container;
9515 ctxt->container = container;
9516 if (type == XML_SCHEMA_TYPE_ALL) {
9517 xmlSchemaParticlePtr part, last = NULL;
9518
9519 while (IS_SCHEMA(child, "element")) {
9520 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9521 schema, child, 0);
9522 if (part != NULL) {
9523 if (part->minOccurs > 1)
9524 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
9525 NULL, NULL, child,
9526 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9527 if (part->maxOccurs > 1)
9528 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
9529 NULL, NULL, child,
9530 "Invalid value for maxOccurs (must be 0 or 1)",
9531 NULL);
9532 if (last == NULL)
9533 item->children = (xmlSchemaTreeItemPtr) part;
9534 else
9535 last->next = (xmlSchemaTreeItemPtr) part;
9536 last = part;
9537 }
9538 child = child->next;
9539 }
9540 if (child != NULL) {
9541 xmlSchemaPContentErr(ctxt,
9542 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9543 NULL, NULL, node, child, NULL,
9544 "(annotation?, (annotation?, element*)");
9545 }
9546 } else {
9547 /* choice + sequence */
9548 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9549
9550 while ((IS_SCHEMA(child, "element")) ||
9551 (IS_SCHEMA(child, "group")) ||
9552 (IS_SCHEMA(child, "any")) ||
9553 (IS_SCHEMA(child, "choice")) ||
9554 (IS_SCHEMA(child, "sequence"))) {
9555
9556 if (IS_SCHEMA(child, "element")) {
9557 part = (xmlSchemaTreeItemPtr)
9558 xmlSchemaParseElement(ctxt, schema, child, 0);
9559 } else if (IS_SCHEMA(child, "group")) {
9560 part =
9561 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9562 } else if (IS_SCHEMA(child, "any")) {
9563 part = (xmlSchemaTreeItemPtr)
9564 xmlSchemaParseAny(ctxt, schema, child);
9565 } else if (IS_SCHEMA(child, "choice")) {
9566 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9567 XML_SCHEMA_TYPE_CHOICE, 1);
9568 } else if (IS_SCHEMA(child, "sequence")) {
9569 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9570 XML_SCHEMA_TYPE_SEQUENCE, 1);
9571 }
9572 if (part != NULL) {
9573 if (last == NULL)
9574 item->children = part;
9575 else
9576 last->next = part;
9577 last = part;
9578 }
9579 child = child->next;
9580 }
9581 if (child != NULL) {
9582 xmlSchemaPContentErr(ctxt,
9583 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9584 NULL, NULL, node, child, NULL,
9585 "(annotation?, (element | group | choice | sequence | any)*)");
9586 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009587 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009588 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009589 if (withParticle)
9590 return ((xmlSchemaTreeItemPtr) particle);
9591 else
9592 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009593}
9594
9595/**
9596 * xmlSchemaParseRestriction:
9597 * @ctxt: a schema validation context
9598 * @schema: the schema being built
9599 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009600 *
9601 * parse a XML schema Restriction definition
9602 * *WARNING* this interface is highly subject to change
9603 *
9604 * Returns the type definition or NULL in case of error
9605 */
9606static xmlSchemaTypePtr
9607xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009608 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009609{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009610 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009611 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009612 char buf[30];
9613 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009614 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009615
9616 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9617 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009618 /* Not a component, don't create it. */
9619 type = ctxt->ctxtType;
9620 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
9621
9622 /*
9623 * TODO: Is the container needed at all? the anonymous
9624 * items inside should generate unique names already.
9625 */
9626 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
9627 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009628 /*
9629 * Check for illegal attributes.
9630 */
9631 attr = node->properties;
9632 while (attr != NULL) {
9633 if (attr->ns == NULL) {
9634 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9635 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
9636 xmlSchemaPIllegalAttrErr(ctxt,
9637 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009638 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009639 }
9640 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9641 xmlSchemaPIllegalAttrErr(ctxt,
9642 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009643 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009644 }
9645 attr = attr->next;
9646 }
9647 /*
9648 * Extract and validate attributes.
9649 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009650 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009651 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009652 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009653 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009654 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009655 NULL, NULL, node, "base",
9656 &(type->baseNs), NULL,
9657 &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009658 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009659 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009660 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009661 XML_SCHEMAP_S4S_ATTR_MISSING,
William M. Brack2f2a6632004-08-20 23:09:47 +00009662 NULL, type, node, "base", NULL);
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009663 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009664 /*
9665 * And now for the children...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009666 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009667 child = node->children;
9668 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009669 /*
9670 * Add the annotation to the simple type ancestor.
9671 */
9672 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9673 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009674 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009675 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009676 oldcontainer = ctxt->container;
9677 ctxt->container = container;
9678 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9679 /*
9680 * Corresponds to <simpleType><restriction><simpleType>.
9681 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009682 if (IS_SCHEMA(child, "simpleType")) {
9683 if (type->base != NULL) {
9684 /*
9685 * src-restriction-base-or-simpleType
9686 * Either the base [attribute] or the simpleType [child] of the
9687 * <restriction> element must be present, but not both.
9688 */
9689 xmlSchemaPContentErr(ctxt,
9690 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009691 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009692 "The attribute 'base' and the <simpleType> child are "
9693 "mutually exclusive", NULL);
9694 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009695 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009696 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009697 }
9698 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009699 } else if (type->base == NULL) {
9700 xmlSchemaPContentErr(ctxt,
9701 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9702 NULL, NULL, node, child,
9703 "Either the attribute 'base' or a <simpleType> child "
9704 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009705 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009706 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9707 /*
9708 * Corresponds to <complexType><complexContent><restriction>...
9709 * followed by:
9710 *
9711 * Model groups <all>, <choice> and <sequence>.
9712 */
9713 if (IS_SCHEMA(child, "all")) {
9714 type->subtypes = (xmlSchemaTypePtr)
9715 xmlSchemaParseModelGroup(ctxt, schema, child,
9716 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009717 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009718 } else if (IS_SCHEMA(child, "choice")) {
9719 type->subtypes = (xmlSchemaTypePtr)
9720 xmlSchemaParseModelGroup(ctxt,
9721 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9722 child = child->next;
9723 } else if (IS_SCHEMA(child, "sequence")) {
9724 type->subtypes = (xmlSchemaTypePtr)
9725 xmlSchemaParseModelGroup(ctxt, schema, child,
9726 XML_SCHEMA_TYPE_SEQUENCE, 1);
9727 child = child->next;
9728 /*
9729 * Model group reference <group>.
9730 */
9731 } else if (IS_SCHEMA(child, "group")) {
9732 type->subtypes = (xmlSchemaTypePtr)
9733 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9734 child = child->next;
9735 }
9736 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
9737 xmlSchemaTypePtr contType, baseType = NULL;
9738 /*
9739 * Corresponds to <complexType><simpleContent><restriction>...
9740 *
9741 * SPEC (content type):
9742 * "1 If the type definition ·resolved· to by the ·actual value· of
9743 * the base [attribute] is a complex type definition whose own
9744 * {content type} is a simple type definition and the <restriction>
9745 * alternative is chosen, then starting from either" ...
9746 *
9747 * "1.1 the simple type definition corresponding to the <simpleType>
9748 * among the [children] of <restriction> if there is one;"
9749 */
9750 if (IS_SCHEMA(child, "simpleType")) {
9751
9752 baseType = (xmlSchemaTypePtr)
9753 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9754 if (baseType == NULL)
9755 return (NULL);
9756 child = child->next;
9757 }
9758 /*
9759 * SPEC
9760 * "... a simple type definition which restricts the simple type
9761 * definition identified in clause 1.1 or clause 1.2 with a set
9762 * of facet components"
9763 *
9764 * Create the anonymous simple type, which will be the content type
9765 * of the complex type.
9766 * Note that we will use the same node as for the <restriction> to
9767 * have it somehow anchored in the schema doc.
9768 */
9769 snprintf(buf, 29, "#scST%d", ctxt->counter++ + 1);
9770 contType = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf,
9771 container, node);
9772 if (contType == NULL)
9773 return (NULL);
9774 contType->node = node;
9775 contType->type = XML_SCHEMA_TYPE_SIMPLE;
9776 contType->baseType = baseType;
9777 type->contentTypeDef = contType;
William M. Brack2f2a6632004-08-20 23:09:47 +00009778 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009779
9780 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
9781 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
9782 xmlSchemaFacetPtr facet, lastfacet = NULL;
9783 xmlSchemaTypePtr facetHolder;
9784
9785 if (parentType == XML_SCHEMA_TYPE_SIMPLE)
9786 facetHolder = type;
9787 else
9788 facetHolder = type->contentTypeDef;
9789 /*
9790 * Corresponds to <complexType><simpleContent><restriction>...
9791 * <simpleType><restriction>...
9792 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009793
Daniel Veillard01fa6152004-06-29 17:04:39 +00009794 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009795 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009796 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009797 /*
9798 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9799 * Simple Type Definition Schema Representation Constraint:
9800 * *Single Facet Value*
9801 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009802 while ((IS_SCHEMA(child, "minInclusive")) ||
9803 (IS_SCHEMA(child, "minExclusive")) ||
9804 (IS_SCHEMA(child, "maxInclusive")) ||
9805 (IS_SCHEMA(child, "maxExclusive")) ||
9806 (IS_SCHEMA(child, "totalDigits")) ||
9807 (IS_SCHEMA(child, "fractionDigits")) ||
9808 (IS_SCHEMA(child, "pattern")) ||
9809 (IS_SCHEMA(child, "enumeration")) ||
9810 (IS_SCHEMA(child, "whiteSpace")) ||
9811 (IS_SCHEMA(child, "length")) ||
9812 (IS_SCHEMA(child, "maxLength")) ||
9813 (IS_SCHEMA(child, "minLength"))) {
9814 facet = xmlSchemaParseFacet(ctxt, schema, child);
9815 if (facet != NULL) {
9816 if (lastfacet == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009817 facetHolder->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009818 else
9819 lastfacet->next = facet;
9820 lastfacet = facet;
9821 lastfacet->next = NULL;
9822 }
9823 child = child->next;
9824 }
9825 /*
9826 * Create links for derivation and validation.
9827 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009828 if (facetHolder->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009829 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
9830
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009831 facet = facetHolder->facets;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009832 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009833 facetLink = (xmlSchemaFacetLinkPtr)
9834 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +00009835 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009836 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009837 xmlFree(facetLink);
9838 return (NULL);
9839 }
9840 facetLink->facet = facet;
9841 facetLink->next = NULL;
9842 if (lastFacetLink == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009843 facetHolder->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009844 else
9845 lastFacetLink->next = facetLink;
9846 lastFacetLink = facetLink;
9847 facet = facet->next;
9848 } while (facet != NULL);
9849 }
9850 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009851 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
9852 /*
9853 * Attribute uses/declarations.
9854 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009855 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009856 /*
9857 * Attribute wildcard.
9858 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009859 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009860 type->attributeWildcard =
9861 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009862 child = child->next;
9863 }
9864 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009865 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009866 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009867 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009868 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9869 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009870 "annotation?, (group | all | choice | sequence)?, "
9871 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009872 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009873 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009874 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9875 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009876 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
9877 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
9878 "length | minLength | maxLength | enumeration | whiteSpace | "
9879 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
9880 } else {
9881 /* Simple type */
9882 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009883 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9884 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009885 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
9886 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
9887 "length | minLength | maxLength | enumeration | whiteSpace | "
9888 "pattern)*))");
9889 }
9890 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009891 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009892 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009893}
9894
9895/**
9896 * xmlSchemaParseExtension:
9897 * @ctxt: a schema validation context
9898 * @schema: the schema being built
9899 * @node: a subtree containing XML Schema informations
9900 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009901 * Parses an <extension>, which is found inside a
9902 * <simpleContent> or <complexContent>.
9903 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +00009904 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009905 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +00009906 */
9907static xmlSchemaTypePtr
9908xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009909 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009910{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009911 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009912 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009913 char buf[30];
9914 const xmlChar *oldcontainer, *container;
9915 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009916
9917 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9918 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009919 /* Not a component, don't create it. */
9920 type = ctxt->ctxtType;
9921 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00009922
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009923 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
9924 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
9925 /*
9926 * Check for illegal attributes.
9927 */
9928 attr = node->properties;
9929 while (attr != NULL) {
9930 if (attr->ns == NULL) {
9931 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9932 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
9933 xmlSchemaPIllegalAttrErr(ctxt,
9934 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9935 NULL, NULL, attr);
9936 }
9937 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9938 xmlSchemaPIllegalAttrErr(ctxt,
9939 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9940 NULL, NULL, attr);
9941 }
9942 attr = attr->next;
9943 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009944
9945 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009946
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009947 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009948 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009949 */
9950 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009951 NULL, NULL, node, "base", &(type->baseNs), NULL,
9952 &(type->base)) == 0) && (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009953 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009954 XML_SCHEMAP_S4S_ATTR_MISSING,
9955 NULL, NULL, node, "base", NULL);
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009956 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009957 /*
9958 * And now for the children...
9959 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009960 child = node->children;
9961 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009962 /*
9963 * Add the annotation to the type ancestor.
9964 */
9965 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9966 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009967 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009968 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009969 oldcontainer = ctxt->container;
9970 ctxt->container = container;
9971 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9972 /*
9973 * Corresponds to <complexType><complexContent><extension>... and:
9974 *
9975 * Model groups <all>, <choice>, <sequence> and <group>.
9976 */
9977 if (IS_SCHEMA(child, "all")) {
9978 type->subtypes = (xmlSchemaTypePtr)
9979 xmlSchemaParseModelGroup(ctxt, schema,
9980 child, XML_SCHEMA_TYPE_ALL, 1);
9981 child = child->next;
9982 } else if (IS_SCHEMA(child, "choice")) {
9983 type->subtypes = (xmlSchemaTypePtr)
9984 xmlSchemaParseModelGroup(ctxt, schema,
9985 child, XML_SCHEMA_TYPE_CHOICE, 1);
9986 child = child->next;
9987 } else if (IS_SCHEMA(child, "sequence")) {
9988 type->subtypes = (xmlSchemaTypePtr)
9989 xmlSchemaParseModelGroup(ctxt, schema,
9990 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
9991 child = child->next;
9992 } else if (IS_SCHEMA(child, "group")) {
9993 type->subtypes = (xmlSchemaTypePtr)
9994 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9995 child = child->next;
9996 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009997 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009998 if (child != NULL) {
9999 /*
10000 * Attribute uses/declarations.
10001 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010002 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010003 /*
10004 * Attribute wildcard.
10005 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010006 if (IS_SCHEMA(child, "anyAttribute")) {
10007 ctxt->ctxtType->attributeWildcard =
10008 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10009 child = child->next;
10010 }
10011 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010012 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010013 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10014 /* Complex content extension. */
10015 xmlSchemaPContentErr(ctxt,
10016 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10017 NULL, NULL, node, child, NULL,
10018 "(annotation?, ((group | all | choice | sequence)?, "
10019 "((attribute | attributeGroup)*, anyAttribute?)))");
10020 } else {
10021 /* Simple content extension. */
10022 xmlSchemaPContentErr(ctxt,
10023 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10024 NULL, NULL, node, child, NULL,
10025 "(annotation?, ((attribute | attributeGroup)*, "
10026 "anyAttribute?))");
10027 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010028 }
10029 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010030 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010031}
10032
10033/**
10034 * xmlSchemaParseSimpleContent:
10035 * @ctxt: a schema validation context
10036 * @schema: the schema being built
10037 * @node: a subtree containing XML Schema informations
10038 *
10039 * parse a XML schema SimpleContent definition
10040 * *WARNING* this interface is highly subject to change
10041 *
10042 * Returns the type definition or NULL in case of error
10043 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010044static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010045xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10046 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010047{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010048 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010049 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010050 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010051
10052 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010053 return (-1);
10054 /* Not a component, don't create it. */
10055 type = ctxt->ctxtType;
10056 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10057 /*
10058 * Check for illegal attributes.
10059 */
10060 attr = node->properties;
10061 while (attr != NULL) {
10062 if (attr->ns == NULL) {
10063 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
10064 xmlSchemaPIllegalAttrErr(ctxt,
10065 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10066 NULL, NULL, attr);
10067 }
10068 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10069 xmlSchemaPIllegalAttrErr(ctxt,
10070 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10071 NULL, NULL, attr);
10072 }
10073 attr = attr->next;
10074 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010075
10076 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010077
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010078 /*
10079 * And now for the children...
10080 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010081 child = node->children;
10082 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010083 /*
10084 * Add the annotation to the complex type ancestor.
10085 */
10086 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10087 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010088 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010089 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010090 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010091 xmlSchemaParseRestriction(ctxt, schema, child,
10092 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010093 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010094 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010095 xmlSchemaParseExtension(ctxt, schema, child,
10096 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010097 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010098 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010099 if (child != NULL) {
10100 xmlSchemaPContentErr(ctxt,
10101 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10102 NULL, NULL, node, child, NULL,
10103 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010104 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010105 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010106}
10107
10108/**
10109 * xmlSchemaParseComplexContent:
10110 * @ctxt: a schema validation context
10111 * @schema: the schema being built
10112 * @node: a subtree containing XML Schema informations
10113 *
10114 * parse a XML schema ComplexContent definition
10115 * *WARNING* this interface is highly subject to change
10116 *
10117 * Returns the type definition or NULL in case of error
10118 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010119static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010120xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10121 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010122{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010123 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010124 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010125 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010126
10127 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010128 return (-1);
10129 /* Not a component, don't create it. */
10130 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010131 /*
10132 * Check for illegal attributes.
10133 */
10134 attr = node->properties;
10135 while (attr != NULL) {
10136 if (attr->ns == NULL) {
10137 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10138 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
10139 {
10140 xmlSchemaPIllegalAttrErr(ctxt,
10141 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10142 NULL, NULL, attr);
10143 }
10144 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10145 xmlSchemaPIllegalAttrErr(ctxt,
10146 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10147 NULL, NULL, attr);
10148 }
10149 attr = attr->next;
10150 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010151
10152 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10153
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010154 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010155 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010156 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010157 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10158 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10159 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010160 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010161 child = node->children;
10162 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010163 /*
10164 * Add the annotation to the complex type ancestor.
10165 */
10166 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10167 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010168 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010169 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010170 if (IS_SCHEMA(child, "restriction")) {
10171 xmlSchemaParseRestriction(ctxt, schema, child,
10172 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010173 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010174 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010175 xmlSchemaParseExtension(ctxt, schema, child,
10176 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010177 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010178 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010179 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010180 xmlSchemaPContentErr(ctxt,
10181 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10182 NULL, NULL, node, child,
10183 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010184 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010185 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010186}
10187
10188/**
10189 * xmlSchemaParseComplexType:
10190 * @ctxt: a schema validation context
10191 * @schema: the schema being built
10192 * @node: a subtree containing XML Schema informations
10193 *
10194 * parse a XML schema Complex Type definition
10195 * *WARNING* this interface is highly subject to change
10196 *
10197 * Returns the type definition or NULL in case of error
10198 */
10199static xmlSchemaTypePtr
10200xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010201 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010202{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010203 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010204 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010205 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010206 xmlAttrPtr attr;
10207 const xmlChar *attrValue;
10208 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010209 char buf[40];
10210
Daniel Veillard4255d502002-04-16 15:50:10 +000010211
10212 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10213 return (NULL);
10214
Daniel Veillard01fa6152004-06-29 17:04:39 +000010215 ctxtType = ctxt->ctxtType;
10216
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010217 if (topLevel) {
10218 attr = xmlSchemaGetPropNode(node, "name");
10219 if (attr == NULL) {
10220 xmlSchemaPMissingAttrErr(ctxt,
10221 XML_SCHEMAP_S4S_ATTR_MISSING,
10222 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
10223 "name", NULL);
10224 return (NULL);
10225 } else if (xmlSchemaPValAttrNode(ctxt,
10226 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
10227 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10228 return (NULL);
10229 }
10230 }
10231
10232 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010233 /*
10234 * Parse as local complex type definition.
10235 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010236 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010237 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10238 if (type == NULL)
10239 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010240 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010241 type->node = node;
10242 type->type = XML_SCHEMA_TYPE_COMPLEX;
10243 /*
10244 * TODO: We need the target namespace.
10245 */
10246 } else {
10247 /*
10248 * Parse as global complex type definition.
10249 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010250 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010251 if (type == NULL)
10252 return (NULL);
10253 type->node = node;
10254 type->type = XML_SCHEMA_TYPE_COMPLEX;
10255 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
10256 /*
10257 * Set defaults.
10258 */
10259 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
10260 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010261 }
10262 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010263 /*
10264 * Handle attributes.
10265 */
10266 attr = node->properties;
10267 while (attr != NULL) {
10268 if (attr->ns == NULL) {
10269 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10270 /*
10271 * Attribute "id".
10272 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010273 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10274 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010275 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10276 /*
10277 * Attribute "mixed".
10278 */
10279 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10280 (xmlNodePtr) attr))
10281 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10282 } else if (topLevel) {
10283 /*
10284 * Attributes of global complex type definitions.
10285 */
10286 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10287 /* Pass. */
10288 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10289 /*
10290 * Attribute "abstract".
10291 */
10292 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10293 (xmlNodePtr) attr))
10294 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10295 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10296 /*
10297 * Attribute "final".
10298 */
10299 attrValue = xmlSchemaGetNodeContent(ctxt,
10300 (xmlNodePtr) attr);
10301 if (xmlSchemaPValAttrBlockFinal(attrValue,
10302 &(type->flags),
10303 -1,
10304 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10305 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10306 -1, -1, -1) != 0)
10307 {
10308 xmlSchemaPSimpleTypeErr(ctxt,
10309 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10310 &des, type, (xmlNodePtr) attr,
10311 NULL,
10312 "(#all | List of (extension | restriction))",
10313 attrValue, NULL, NULL, NULL);
10314 }
10315 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10316 /*
10317 * Attribute "block".
10318 */
10319 attrValue = xmlSchemaGetNodeContent(ctxt,
10320 (xmlNodePtr) attr);
10321 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
10322 -1,
10323 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
10324 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
10325 -1, -1, -1) != 0) {
10326 xmlSchemaPSimpleTypeErr(ctxt,
10327 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10328 &des, type, (xmlNodePtr) attr,
10329 NULL,
10330 "(#all | List of (extension | restriction)) ",
10331 attrValue, NULL, NULL, NULL);
10332 }
10333 } else {
10334 xmlSchemaPIllegalAttrErr(ctxt,
10335 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10336 &des, type, attr);
10337 }
10338 } else {
10339 xmlSchemaPIllegalAttrErr(ctxt,
10340 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10341 &des, type, attr);
10342 }
10343 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10344 xmlSchemaPIllegalAttrErr(ctxt,
10345 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10346 &des, type, attr);
10347 }
10348 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010349 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010350 /*
10351 * And now for the children...
10352 */
10353 oldcontainer = ctxt->container;
10354 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010355 child = node->children;
10356 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010357 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10358 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010359 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010360 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010361 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010362 /*
10363 * 3.4.3 : 2.2
10364 * Specifying mixed='true' when the <simpleContent>
10365 * alternative is chosen has no effect
10366 */
William M. Bracke7091952004-05-11 15:09:58 +000010367 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10368 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010369 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010370 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010371 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010372 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10373 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010374 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010375 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010376 /*
10377 * SPEC
10378 * "...the third alternative (neither <simpleContent> nor
10379 * <complexContent>) is chosen. This case is understood as shorthand
10380 * for complex content restricting the ·ur-type definition·, and the
10381 * details of the mappings should be modified as necessary.
10382 */
10383 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10384 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010385 /*
10386 * Parse model groups.
10387 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010388 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010389 type->subtypes = (xmlSchemaTypePtr)
10390 xmlSchemaParseModelGroup(ctxt, schema, child,
10391 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010392 child = child->next;
10393 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010394 type->subtypes = (xmlSchemaTypePtr)
10395 xmlSchemaParseModelGroup(ctxt, schema, child,
10396 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010397 child = child->next;
10398 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010399 type->subtypes = (xmlSchemaTypePtr)
10400 xmlSchemaParseModelGroup(ctxt, schema, child,
10401 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010402 child = child->next;
10403 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010404 type->subtypes = (xmlSchemaTypePtr)
10405 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010406 child = child->next;
10407 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010408 /*
10409 * Parse attribute decls/refs.
10410 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010411 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010412 /*
10413 * Parse attribute wildcard.
10414 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010415 if (IS_SCHEMA(child, "anyAttribute")) {
10416 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10417 child = child->next;
10418 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010419 }
10420 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010421 xmlSchemaPContentErr(ctxt,
10422 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10423 &des, type, node, child,
10424 NULL, "(annotation?, (simpleContent | complexContent | "
10425 "((group | all | choice | sequence)?, ((attribute | "
10426 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010427 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010428 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010429 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010430 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010431 return (type);
10432}
10433
Daniel Veillard4255d502002-04-16 15:50:10 +000010434/**
10435 * xmlSchemaParseSchema:
10436 * @ctxt: a schema validation context
10437 * @node: a subtree containing XML Schema informations
10438 *
10439 * parse a XML schema definition from a node set
10440 * *WARNING* this interface is highly subject to change
10441 *
10442 * Returns the internal XML Schema structure built from the resource or
10443 * NULL in case of error
10444 */
10445static xmlSchemaPtr
10446xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10447{
10448 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010449 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010450 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010451 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010452
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010453 /*
10454 * This one is called by xmlSchemaParse only and is used if
10455 * the schema to be parsed was specified via the API; i.e. not
10456 * automatically by the validated instance document.
10457 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010458 if ((ctxt == NULL) || (node == NULL))
10459 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010460 nberrors = ctxt->nberrors;
10461 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010462 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010463 xmlSchemaImportPtr import;
10464
Daniel Veillard4255d502002-04-16 15:50:10 +000010465 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010466 if (schema == NULL)
10467 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010468 /*
10469 * Disable build of list of items.
10470 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010471 attr = xmlSchemaGetPropNode(node, "targetNamespace");
10472 if (attr != NULL) {
10473 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
10474 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10475 /*
10476 * TODO: Should we proceed with an invalid target namespace?
10477 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010478 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
10479 } else {
10480 schema->targetNamespace = NULL;
10481 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010482 /*
10483 * Add the current ns name and location to the import table;
10484 * this is needed to have a consistent mechanism, regardless
10485 * if all schemata are constructed dynamically fired by the
10486 * instance or if the schema to be used was specified via
10487 * the API.
10488 */
10489 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10490 schema->targetNamespace);
10491 if (import == NULL) {
10492 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10493 NULL, NULL, (xmlNodePtr) ctxt->doc,
10494 "Internal error: xmlSchemaParseSchema, "
10495 "failed to add an import entry", NULL);
10496 xmlSchemaFree(schema);
10497 schema = NULL;
10498 return (NULL);
10499 }
10500 import->schemaLocation = ctxt->URL;
10501 /*
10502 * NOTE: We won't set the doc here, otherwise it will be freed
10503 * if the import struct is freed.
10504 * import->doc = ctxt->doc;
10505 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010506 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010507 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10508 } else {
10509 xmlDocPtr doc;
10510
10511 doc = node->doc;
10512
10513 if ((doc != NULL) && (doc->URL != NULL)) {
10514 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10515 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010516 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010517 } else {
10518 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10519 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010520 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010521 }
10522 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010523 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010524 if (ctxt->nberrors != 0) {
10525 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010526 xmlSchemaFree(schema);
10527 schema = NULL;
10528 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010529 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010530 if (schema != NULL)
10531 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010532 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010533#ifdef DEBUG
10534 if (schema == NULL)
10535 xmlGenericError(xmlGenericErrorContext,
10536 "xmlSchemaParse() failed\n");
10537#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010538 return (schema);
10539}
10540
10541/************************************************************************
10542 * *
10543 * Validating using Schemas *
10544 * *
10545 ************************************************************************/
10546
10547/************************************************************************
10548 * *
10549 * Reading/Writing Schemas *
10550 * *
10551 ************************************************************************/
10552
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010553#if 0 /* Will be enabled if it is clear what options are needed. */
10554/**
10555 * xmlSchemaParserCtxtSetOptions:
10556 * @ctxt: a schema parser context
10557 * @options: a combination of xmlSchemaParserOption
10558 *
10559 * Sets the options to be used during the parse.
10560 *
10561 * Returns 0 in case of success, -1 in case of an
10562 * API error.
10563 */
10564static int
10565xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10566 int options)
10567
10568{
10569 int i;
10570
10571 if (ctxt == NULL)
10572 return (-1);
10573 /*
10574 * WARNING: Change the start value if adding to the
10575 * xmlSchemaParseOption.
10576 */
10577 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10578 if (options & 1<<i) {
10579 return (-1);
10580 }
10581 }
10582 ctxt->options = options;
10583 return (0);
10584}
10585
10586/**
10587 * xmlSchemaValidCtxtGetOptions:
10588 * @ctxt: a schema parser context
10589 *
10590 * Returns the option combination of the parser context.
10591 */
10592static int
10593xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
10594
10595{
10596 if (ctxt == NULL)
10597 return (-1);
10598 else
10599 return (ctxt->options);
10600}
10601
10602 void *curItems; /* used for dynamic addition of schemata */
10603 int nbCurItems; /* used for dynamic addition of schemata */
10604 int sizeCurItems; /* used for dynamic addition of schemata */
10605
10606#endif
10607
Daniel Veillard4255d502002-04-16 15:50:10 +000010608/**
10609 * xmlSchemaNewParserCtxt:
10610 * @URL: the location of the schema
10611 *
10612 * Create an XML Schemas parse context for that file/resource expected
10613 * to contain an XML Schemas file.
10614 *
10615 * Returns the parser context or NULL in case of error
10616 */
10617xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010618xmlSchemaNewParserCtxt(const char *URL)
10619{
Daniel Veillard4255d502002-04-16 15:50:10 +000010620 xmlSchemaParserCtxtPtr ret;
10621
10622 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010623 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010624
10625 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10626 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010627 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010628 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010629 return (NULL);
10630 }
10631 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010632 ret->dict = xmlDictCreate();
10633 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010634 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010635 return (ret);
10636}
10637
10638/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010639 * xmlSchemaNewParserCtxtUseDict:
10640 * @URL: the location of the schema
10641 * @dict: the dictionary to be used
10642 *
10643 * Create an XML Schemas parse context for that file/resource expected
10644 * to contain an XML Schemas file.
10645 *
10646 * Returns the parser context or NULL in case of error
10647 */
10648static xmlSchemaParserCtxtPtr
10649xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
10650{
10651 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010652 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010653 if (URL == NULL)
10654 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010655 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010656
10657 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10658 if (ret == NULL) {
10659 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10660 NULL);
10661 return (NULL);
10662 }
10663 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10664 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010665 xmlDictReference(dict);
10666 if (URL != NULL)
10667 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010668 ret->includes = 0;
10669 return (ret);
10670}
10671
10672
10673/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010674 * xmlSchemaNewMemParserCtxt:
10675 * @buffer: a pointer to a char array containing the schemas
10676 * @size: the size of the array
10677 *
10678 * Create an XML Schemas parse context for that memory buffer expected
10679 * to contain an XML Schemas file.
10680 *
10681 * Returns the parser context or NULL in case of error
10682 */
10683xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010684xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10685{
Daniel Veillard6045c902002-10-09 21:13:59 +000010686 xmlSchemaParserCtxtPtr ret;
10687
10688 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010689 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010690
10691 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10692 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010693 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010694 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010695 return (NULL);
10696 }
10697 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10698 ret->buffer = buffer;
10699 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010700 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010701 return (ret);
10702}
10703
10704/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010705 * xmlSchemaNewDocParserCtxt:
10706 * @doc: a preparsed document tree
10707 *
10708 * Create an XML Schemas parse context for that document.
10709 * NB. The document may be modified during the parsing process.
10710 *
10711 * Returns the parser context or NULL in case of error
10712 */
10713xmlSchemaParserCtxtPtr
10714xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10715{
10716 xmlSchemaParserCtxtPtr ret;
10717
10718 if (doc == NULL)
10719 return (NULL);
10720
10721 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10722 if (ret == NULL) {
10723 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10724 NULL);
10725 return (NULL);
10726 }
10727 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10728 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010729 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010730 /* The application has responsibility for the document */
10731 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010732
10733 return (ret);
10734}
10735
10736/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010737 * xmlSchemaFreeParserCtxt:
10738 * @ctxt: the schema parser context
10739 *
10740 * Free the resources associated to the schema parser context
10741 */
10742void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010743xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10744{
Daniel Veillard4255d502002-04-16 15:50:10 +000010745 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010746 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010747 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010748 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010749 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010750 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010751 xmlFree(ctxt->assemble);
10752 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010753 if (ctxt->vctxt != NULL) {
10754 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10755 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010756 if (ctxt->localImports != NULL)
10757 xmlFree((xmlChar *) ctxt->localImports);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010758 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010759 xmlFree(ctxt);
10760}
10761
10762/************************************************************************
10763 * *
10764 * Building the content models *
10765 * *
10766 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010767
Daniel Veillard4255d502002-04-16 15:50:10 +000010768/**
10769 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000010770 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010771 * @particle: the particle component
10772 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000010773 *
10774 * Generate the automata sequence needed for that type
10775 */
10776static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010777xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt,
10778 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010779 const xmlChar * name)
10780{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010781 if (particle == NULL) {
10782 xmlSchemaPErr(ctxt, NULL,
10783 XML_SCHEMAP_INTERNAL,
10784 "Internal error: xmlSchemaBuildAContentModel, "
10785 "particle is NULL.\n", NULL, NULL);
10786 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010787 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010788 if (particle->children == NULL) {
10789 xmlSchemaPErr(ctxt, GET_NODE(particle),
10790 XML_SCHEMAP_INTERNAL,
10791 "Internal error: xmlSchemaBuildAContentModel, "
10792 "no term on particle.\n", NULL, NULL);
10793 return;
10794 }
10795
10796 switch (particle->children->type) {
10797 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010798 xmlAutomataStatePtr start, end;
10799 xmlSchemaWildcardPtr wild;
10800 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000010801
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010802 wild = (xmlSchemaWildcardPtr) particle->children;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010803
10804 start = ctxt->state;
10805 end = xmlAutomataNewState(ctxt->am);
10806
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010807 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010808 if (wild->any == 1) {
10809 /*
10810 * We need to add both transitions:
10811 *
10812 * 1. the {"*", "*"} for elements in a namespace.
10813 */
10814 ctxt->state =
10815 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010816 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010817 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10818 /*
10819 * 2. the {"*"} for elements in no namespace.
10820 */
10821 ctxt->state =
10822 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010823 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010824 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10825
10826 } else if (wild->nsSet != NULL) {
10827 ns = wild->nsSet;
10828 do {
10829 ctxt->state = start;
10830 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010831 ctxt->state, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010832 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10833 ns = ns->next;
10834 } while (ns != NULL);
10835
10836 } else if (wild->negNsSet != NULL) {
10837 xmlAutomataStatePtr deadEnd;
10838
10839 deadEnd = xmlAutomataNewState(ctxt->am);
10840 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010841 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010842 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010843 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010844 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10845 }
10846 } else {
10847 int counter;
10848 xmlAutomataStatePtr hop;
10849 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010850 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010851 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010852 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010853
10854 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
10855 hop = xmlAutomataNewState(ctxt->am);
10856 if (wild->any == 1) {
10857 ctxt->state =
10858 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010859 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010860 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10861 ctxt->state =
10862 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010863 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010864 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10865 } else if (wild->nsSet != NULL) {
10866 ns = wild->nsSet;
10867 do {
10868 ctxt->state =
10869 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010870 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010871 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10872 ns = ns->next;
10873 } while (ns != NULL);
10874
10875 } else if (wild->negNsSet != NULL) {
10876 xmlAutomataStatePtr deadEnd;
10877
10878 deadEnd = xmlAutomataNewState(ctxt->am);
10879 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010880 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010881 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010882 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010883 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10884 }
10885 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
10886 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
10887 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010888 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010889 xmlAutomataNewEpsilon(ctxt->am, start, end);
10890 }
10891 ctxt->state = end;
10892 break;
10893 }
10894 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010895 xmlAutomataStatePtr oldstate;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010896 xmlSchemaElementPtr elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +000010897
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010898 elemDecl = (xmlSchemaElementPtr) particle->children;
10899
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010900 oldstate = ctxt->state;
10901
10902 if (particle->maxOccurs >= UNBOUNDED) {
10903 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010904 xmlAutomataStatePtr tmp;
10905 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +000010906
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010907 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010908 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010909 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010910 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010911 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000010912 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010913 xmlAutomataNewTransition2(ctxt->am,
10914 ctxt->state, NULL,
10915 elemDecl->name,
10916 elemDecl->targetNamespace,
10917 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010918 tmp = ctxt->state;
10919 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010920 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010921 ctxt->state =
10922 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010923 counter);
Daniel Veillard32370232002-10-16 14:08:14 +000010924
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010925 } else {
10926 ctxt->state =
10927 xmlAutomataNewTransition2(ctxt->am,
10928 ctxt->state, NULL,
10929 elemDecl->name,
10930 elemDecl->targetNamespace,
10931 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010932 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
10933 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010934 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010935 /* basically an elem* */
10936 xmlAutomataNewEpsilon(ctxt->am, oldstate,
10937 ctxt->state);
10938 }
10939 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010940 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010941 xmlAutomataStatePtr tmp;
10942 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +000010943
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010944 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
10945 oldstate, NULL);
10946 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010947 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010948 particle->minOccurs - 1,
10949 particle->maxOccurs - 1);
10950 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
10951 ctxt->state,
10952 NULL,
10953 elemDecl->name,
10954 elemDecl->targetNamespace,
10955 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010956 tmp = ctxt->state;
10957 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010958 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010959 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010960 NULL, counter);
10961 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010962 /* basically an elem? */
10963 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010964 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010965 }
Daniel Veillardb39bc392002-10-26 19:29:51 +000010966
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010967 } else {
10968 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
10969 ctxt->state,
10970 NULL,
10971 elemDecl->name,
10972 elemDecl->targetNamespace,
10973 (xmlSchemaTypePtr) elemDecl);
10974 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010975 /* basically an elem? */
10976 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010977 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010978 }
10979 }
10980 break;
10981 }
10982 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010983 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010984
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010985 /*
10986 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010987 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010988 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010989 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
10990 sub = particle->children->children;
10991 while (sub != NULL) {
10992 xmlSchemaBuildAContentModel(ctxt,
10993 (xmlSchemaParticlePtr) sub, name);
10994 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010995 }
10996 } else {
10997 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010998
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010999 if (particle->maxOccurs >= UNBOUNDED) {
11000 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011001 xmlAutomataStatePtr tmp;
11002 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011003
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011004 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011005 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011006 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011007
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011008 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011009 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011010
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011011 sub = particle->children->children;
11012 while (sub != NULL) {
11013 xmlSchemaBuildAContentModel(ctxt,
11014 (xmlSchemaParticlePtr) sub, name);
11015 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011016 }
11017 tmp = ctxt->state;
11018 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11019 oldstate, counter);
11020 ctxt->state =
11021 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11022 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011023
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011024 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011025 sub = particle->children->children;
11026 while (sub != NULL) {
11027 xmlSchemaBuildAContentModel(ctxt,
11028 (xmlSchemaParticlePtr) sub, name);
11029 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011030 }
11031 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11032 oldstate);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011033 if (particle->minOccurs == 0) {
11034 xmlAutomataNewEpsilon(ctxt->am,
11035 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011036 }
11037 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011038 } else if ((particle->maxOccurs > 1)
11039 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011040 xmlAutomataStatePtr tmp;
11041 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011042
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011043 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011044 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011045 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011046
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011047 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011048 particle->minOccurs - 1,
11049 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011050
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011051 sub = particle->children->children;
11052 while (sub != NULL) {
11053 xmlSchemaBuildAContentModel(ctxt,
11054 (xmlSchemaParticlePtr) sub, name);
11055 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011056 }
11057 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011058 xmlAutomataNewCountedTrans(ctxt->am,
11059 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011060 ctxt->state =
11061 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11062 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011063 if (particle->minOccurs == 0) {
11064 xmlAutomataNewEpsilon(ctxt->am,
11065 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011066 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011067 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011068 sub = particle->children->children;
11069 while (sub != NULL) {
11070 xmlSchemaBuildAContentModel(ctxt,
11071 (xmlSchemaParticlePtr) sub, name);
11072 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011073 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011074 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011075 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11076 ctxt->state);
11077 }
11078 }
11079 }
11080 break;
11081 }
11082 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011083 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011084 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011085
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011086 start = ctxt->state;
11087 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011088
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011089 /*
11090 * iterate over the subtypes and remerge the end with an
11091 * epsilon transition
11092 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011093 if (particle->maxOccurs == 1) {
11094 sub = particle->children->children;
11095 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011096 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011097 xmlSchemaBuildAContentModel(ctxt,
11098 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011099 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011100 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011101 }
11102 } else {
11103 int counter;
11104 xmlAutomataStatePtr hop;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011105 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11106 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011107 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011108 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011109
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011110 /*
11111 * use a counter to keep track of the number of transtions
11112 * which went through the choice.
11113 */
11114 counter =
11115 xmlAutomataNewCounter(ctxt->am, minOccurs,
11116 maxOccurs);
11117 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011118
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011119 sub = particle->children->children;
11120 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011121 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011122 xmlSchemaBuildAContentModel(ctxt,
11123 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011124 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011125 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011126 }
11127 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
11128 counter);
11129 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
11130 counter);
11131 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011132 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011133 xmlAutomataNewEpsilon(ctxt->am, start, end);
11134 }
11135 ctxt->state = end;
11136 break;
11137 }
11138 case XML_SCHEMA_TYPE_ALL:{
11139 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011140 xmlSchemaParticlePtr sub;
11141 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011142 int lax;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011143
11144 sub = (xmlSchemaParticlePtr) particle->children->children;
11145 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011146 break;
11147 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011148 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011149 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011150
11151 elemDecl = (xmlSchemaElementPtr) sub->children;
11152 if (elemDecl == NULL) {
11153 xmlSchemaPErr(ctxt, NULL,
11154 XML_SCHEMAP_INTERNAL,
11155 "Internal error: xmlSchemaBuildAContentModel, "
11156 "<element> particle a NULL term.\n", NULL, NULL);
11157 return;
11158 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011159 /*
11160 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011161 * {particles} of the group must be 0 or 1; this is
11162 * already ensured during the parse of the content of
11163 * <all>.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011164 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011165 if ((sub->minOccurs == 1) &&
11166 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011167 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
11168 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011169 elemDecl->name,
11170 elemDecl->targetNamespace,
11171 1, 1, elemDecl);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011172 } else if ((sub->minOccurs == 0) &&
11173 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011174
11175 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
11176 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011177 elemDecl->name,
11178 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011179 0,
11180 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011181 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011182 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011183 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011184 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011185 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011186 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011187 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011188 break;
11189 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011190 default:
11191 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011192 "Internal error: xmlSchemaBuildAContentModel, found "
11193 "unexpected term of type %d in content model of complex "
11194 "type '%s'.\n",
11195 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011196 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011197 }
11198}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011199
Daniel Veillard4255d502002-04-16 15:50:10 +000011200/**
11201 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011202 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011203 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011204 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011205 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011206 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011207 */
11208static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011209xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011210 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011211 const xmlChar * name)
11212{
Daniel Veillard4255d502002-04-16 15:50:10 +000011213 xmlAutomataStatePtr start;
11214
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011215 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11216 (type->contModel != NULL) ||
11217 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11218 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011219 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011220
11221#ifdef DEBUG_CONTENT
11222 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011223 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011224#endif
11225
Daniel Veillard4255d502002-04-16 15:50:10 +000011226 ctxt->am = xmlNewAutomata();
11227 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011228 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011229 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011230 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011231 }
11232 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011233 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011234 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011235 type->contModel = xmlAutomataCompile(ctxt->am);
11236 if (type->contModel == NULL) {
11237 xmlSchemaPCustomErr(ctxt,
11238 XML_SCHEMAP_INTERNAL,
11239 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011240 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011241 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011242 xmlSchemaPCustomErr(ctxt,
11243 XML_SCHEMAP_NOT_DETERMINISTIC,
11244 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011245 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011246 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011247 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011248#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011249 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011250 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011251 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011252#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011253 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011254 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011255 xmlFreeAutomata(ctxt->am);
11256 ctxt->am = NULL;
11257}
11258
11259/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011260 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011261 * @elem: the schema element context
11262 * @ctxt: the schema parser context
11263 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011264 * Resolves the references of an element declaration
11265 * or particle, which has an element declaration as it's
11266 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011267 */
11268static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011269xmlSchemaElementFixup(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011270 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011271 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011272 const xmlChar * context ATTRIBUTE_UNUSED,
11273 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011274{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011275 if ((ctxt == NULL) || (elem == NULL) ||
11276 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011277 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011278 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011279
11280 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
11281 xmlSchemaTypePtr type;
11282
11283 /* (type definition) ... otherwise the type definition ·resolved·
11284 * to by the ·actual value· of the type [attribute] ...
11285 */
11286 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
11287 elem->namedTypeNs);
11288 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011289 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011290 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011291 NULL, (xmlSchemaTypePtr) elem, elem->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011292 "type", elem->namedType, elem->namedTypeNs,
11293 XML_SCHEMA_TYPE_BASIC, "type definition");
11294 } else
11295 elem->subtypes = type;
11296 }
11297 if (elem->substGroup != NULL) {
11298 xmlSchemaElementPtr substHead;
11299
Daniel Veillardc0826a72004-08-10 14:17:33 +000011300 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011301 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
11302 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011303 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011304 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
11305 elem->substGroupNs);
11306 if (substHead == NULL) {
11307 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011308 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011309 NULL, (xmlSchemaTypePtr) elem, NULL,
11310 "substitutionGroup", elem->substGroup, elem->substGroupNs,
11311 XML_SCHEMA_TYPE_ELEMENT, NULL);
11312 } else {
11313 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
11314 /*
11315 * (type definition)...otherwise the {type definition} of the
11316 * element declaration ·resolved· to by the ·actual value· of
11317 * the substitutionGroup [attribute], if present
11318 */
11319 if (elem->subtypes == NULL)
11320 elem->subtypes = substHead->subtypes;
11321 }
11322 }
11323 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
11324 (elem->substGroup == NULL))
11325 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011326}
11327
11328/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011329 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011330 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011331 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011332 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011333 * Checks and builds the memberTypes of the union simple type.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011334 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011335 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011336static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011337xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11338 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011339{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011340
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011341 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
11342 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011343
Daniel Veillard01fa6152004-06-29 17:04:39 +000011344 /* 1 If the <union> alternative is chosen, then [Definition:]
11345 * define the explicit members as the type definitions ·resolved·
11346 * to by the items in the ·actual value· of the memberTypes [attribute],
11347 * if any, followed by the type definitions corresponding to the
11348 * <simpleType>s among the [children] of <union>, if any.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011349 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011350 /*
11351 * Resolve references.
11352 */
11353 link = type->memberTypes;
11354 lastLink = NULL;
11355 while (link != NULL) {
11356 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011357
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011358 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11359 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11360
11361 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11362 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11363 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
11364 NULL, type, type->node, "memberTypes",
11365 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11366 /*
11367 * Remove the member type link.
11368 */
11369 if (lastLink == NULL)
11370 type->memberTypes = link->next;
11371 else
11372 lastLink->next = link->next;
11373 newLink = link;
11374 link = link->next;
11375 xmlFree(newLink);
11376 } else {
11377 link->type = memberType;
11378 if (IS_NOT_TYPEFIXED(memberType))
11379 xmlSchemaTypeFixup(memberType, ctxt, NULL);
11380
11381 lastLink = link;
11382 link = link->next;
11383 }
11384 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011385 /*
11386 * Add local simple types,
11387 */
11388 memberType = type->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011389 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011390 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11391 if (link == NULL) {
11392 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11393 return (-1);
11394 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011395 if (IS_NOT_TYPEFIXED(memberType))
11396 xmlSchemaTypeFixup(memberType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011397 link->type = memberType;
11398 link->next = NULL;
11399 if (lastLink == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011400 type->memberTypes = link;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011401 else
11402 lastLink->next = link;
11403 lastLink = link;
11404 memberType = memberType->next;
11405 }
11406 /*
11407 * The actual value is then formed by replacing any union type
11408 * definition in the ·explicit members· with the members of their
11409 * {member type definitions}, in order.
11410 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011411 link = type->memberTypes;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011412 while (link != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011413 /* TODO: type-fixup it. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011414 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011415 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011416 if (subLink != NULL) {
11417 link->type = subLink->type;
11418 if (subLink->next != NULL) {
11419 lastLink = link->next;
11420 subLink = subLink->next;
11421 prevLink = link;
11422 while (subLink != NULL) {
11423 newLink = (xmlSchemaTypeLinkPtr)
11424 xmlMalloc(sizeof(xmlSchemaTypeLink));
11425 if (newLink == NULL) {
11426 xmlSchemaPErrMemory(ctxt, "allocating a type link",
11427 NULL);
11428 return (-1);
11429 }
11430 newLink->type = memberType;
11431 prevLink->next = newLink;
11432 prevLink = newLink;
11433 newLink->next = lastLink;
11434
11435 subLink = subLink->next;
11436 }
11437 }
11438 }
11439 }
11440 link = link->next;
11441 }
11442
11443 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011444}
11445
Daniel Veillard4255d502002-04-16 15:50:10 +000011446/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011447 * xmlSchemaIsDerivedFromBuiltInType:
11448 * @ctxt: the schema parser context
11449 * @type: the type definition
11450 * @valType: the value type
11451 *
11452 *
11453 * Returns 1 if the type has the given value type, or
11454 * is derived from such a type.
11455 */
William M. Brack803812b2004-06-03 02:11:24 +000011456static int
Daniel Veillard3646d642004-06-02 19:19:14 +000011457xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
11458 xmlSchemaTypePtr type, int valType)
11459{
11460 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011461 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011462 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011463 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011464 return(1);
11465 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
11466 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
11467 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
11468 ((xmlSchemaAttributePtr) type)->subtypes, valType));
11469 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
11470 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
11471 if (type->baseType != NULL)
11472 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
11473 valType));
11474 } else if ((type->subtypes != NULL) &&
11475 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
11476 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11477 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
11478 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
11479 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
11480 valType));
11481 }
11482
11483 return (0);
11484}
11485
11486/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011487 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011488 * @type: the simpleType definition
11489 *
11490 * Returns the primitive type of the given type or
11491 * NULL in case of error.
11492 */
11493static xmlSchemaTypePtr
11494xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11495{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011496
Daniel Veillard01fa6152004-06-29 17:04:39 +000011497 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011498 /*
11499 * Note that anySimpleType is actually not a primitive type
11500 * but we need that here.
11501 */
11502 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11503 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011504 return (type);
11505 type = type->baseType;
11506 }
11507
11508 return (NULL);
11509}
11510
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011511#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011512/**
11513 * xmlSchemaGetBuiltInTypeAncestor:
11514 * @type: the simpleType definition
11515 *
11516 * Returns the primitive type of the given type or
11517 * NULL in case of error.
11518 */
11519static xmlSchemaTypePtr
11520xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11521{
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011522 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
11523 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))
11524 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011525 while (type != NULL) {
11526 if (type->type == XML_SCHEMA_TYPE_BASIC)
11527 return (type);
11528 type = type->baseType;
11529 }
11530
11531 return (NULL);
11532}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011533#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011534
Daniel Veillard01fa6152004-06-29 17:04:39 +000011535/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011536 * xmlSchemaBuildAttributeUsesOwned:
11537 * @ctxt: the schema parser context
11538 * @type: the complex type definition
11539 * @cur: the attribute declaration list
11540 * @lastUse: the top of the attribute use list
11541 *
11542 * Builds the attribute uses list on the given complex type.
11543 * This one is supposed to be called by
11544 * xmlSchemaBuildAttributeValidation only.
11545 */
11546static int
11547xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
11548 xmlSchemaAttributePtr cur,
11549 xmlSchemaAttributeLinkPtr *uses,
11550 xmlSchemaAttributeLinkPtr *lastUse)
11551{
11552 xmlSchemaAttributeLinkPtr tmp;
11553 while (cur != NULL) {
11554 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
11555 /*
11556 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11557 * to by the ·actual value·s of the ref [attribute] of the
11558 * <attributeGroup> [children], if any."
11559 */
11560 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11561 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
11562 lastUse) == -1) {
11563 return (-1);
11564 }
11565 } else {
11566 /* W3C: "1 The set of attribute uses corresponding to the
11567 * <attribute> [children], if any."
11568 */
11569 tmp = (xmlSchemaAttributeLinkPtr)
11570 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11571 if (tmp == NULL) {
11572 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11573 return (-1);
11574 }
11575 tmp->attr = cur;
11576 tmp->next = NULL;
11577 if (*uses == NULL)
11578 *uses = tmp;
11579 else
11580 (*lastUse)->next = tmp;
11581 *lastUse = tmp;
11582 }
11583 cur = cur->next;
11584 }
11585 return (0);
11586}
11587
Daniel Veillard50355f02004-06-08 17:52:16 +000011588/**
11589 * xmlSchemaCloneWildcardNsConstraints:
11590 * @ctxt: the schema parser context
11591 * @dest: the destination wildcard
11592 * @source: the source wildcard
11593 *
11594 * Clones the namespace constraints of source
11595 * and assignes them to dest.
11596 * Returns -1 on internal error, 0 otherwise.
11597 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011598static int
11599xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11600 xmlSchemaWildcardPtr *dest,
11601 xmlSchemaWildcardPtr source)
11602{
11603 xmlSchemaWildcardNsPtr cur, tmp, last;
11604
11605 if ((source == NULL) || (*dest == NULL))
11606 return(-1);
11607 (*dest)->any = source->any;
11608 cur = source->nsSet;
11609 last = NULL;
11610 while (cur != NULL) {
11611 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11612 if (tmp == NULL)
11613 return(-1);
11614 tmp->value = cur->value;
11615 if (last == NULL)
11616 (*dest)->nsSet = tmp;
11617 else
11618 last->next = tmp;
11619 last = tmp;
11620 cur = cur->next;
11621 }
11622 if ((*dest)->negNsSet != NULL)
11623 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
11624 if (source->negNsSet != NULL) {
11625 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11626 if ((*dest)->negNsSet == NULL)
11627 return(-1);
11628 (*dest)->negNsSet->value = source->negNsSet->value;
11629 } else
11630 (*dest)->negNsSet = NULL;
11631 return(0);
11632}
11633
Daniel Veillard50355f02004-06-08 17:52:16 +000011634/**
11635 * xmlSchemaUnionWildcards:
11636 * @ctxt: the schema parser context
11637 * @completeWild: the first wildcard
11638 * @curWild: the second wildcard
11639 *
11640 * Unions the namespace constraints of the given wildcards.
11641 * @completeWild will hold the resulting union.
11642 * Returns a positive error code on failure, -1 in case of an
11643 * internal error, 0 otherwise.
11644 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011645static int
11646xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
11647 xmlSchemaWildcardPtr completeWild,
11648 xmlSchemaWildcardPtr curWild)
11649{
11650 xmlSchemaWildcardNsPtr cur, curB, tmp;
11651
11652 /*
11653 * 1 If O1 and O2 are the same value, then that value must be the
11654 * value.
11655 */
11656 if ((completeWild->any == curWild->any) &&
11657 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11658 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
11659
11660 if ((completeWild->negNsSet == NULL) ||
11661 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
11662
11663 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011664 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011665
11666 /*
11667 * Check equality of sets.
11668 */
11669 cur = completeWild->nsSet;
11670 while (cur != NULL) {
11671 found = 0;
11672 curB = curWild->nsSet;
11673 while (curB != NULL) {
11674 if (cur->value == curB->value) {
11675 found = 1;
11676 break;
11677 }
11678 curB = curB->next;
11679 }
11680 if (!found)
11681 break;
11682 cur = cur->next;
11683 }
11684 if (found)
11685 return(0);
11686 } else
11687 return(0);
11688 }
11689 }
11690 /*
11691 * 2 If either O1 or O2 is any, then any must be the value
11692 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011693 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011694 if (completeWild->any == 0) {
11695 completeWild->any = 1;
11696 if (completeWild->nsSet != NULL) {
11697 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11698 completeWild->nsSet = NULL;
11699 }
11700 if (completeWild->negNsSet != NULL) {
11701 xmlFree(completeWild->negNsSet);
11702 completeWild->negNsSet = NULL;
11703 }
11704 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011705 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011706 }
11707 /*
11708 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
11709 * then the union of those sets must be the value.
11710 */
11711 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
11712 int found;
11713 xmlSchemaWildcardNsPtr start;
11714
11715 cur = curWild->nsSet;
11716 start = completeWild->nsSet;
11717 while (cur != NULL) {
11718 found = 0;
11719 curB = start;
11720 while (curB != NULL) {
11721 if (cur->value == curB->value) {
11722 found = 1;
11723 break;
11724 }
11725 curB = curB->next;
11726 }
11727 if (!found) {
11728 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11729 if (tmp == NULL)
11730 return (-1);
11731 tmp->value = cur->value;
11732 tmp->next = completeWild->nsSet;
11733 completeWild->nsSet = tmp;
11734 }
11735 cur = cur->next;
11736 }
11737
11738 return(0);
11739 }
11740 /*
11741 * 4 If the two are negations of different values (namespace names
11742 * or ·absent·), then a pair of not and ·absent· must be the value.
11743 */
11744 if ((completeWild->negNsSet != NULL) &&
11745 (curWild->negNsSet != NULL) &&
11746 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11747 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011748
11749 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011750 }
11751 /*
11752 * 5.
11753 */
11754 if (((completeWild->negNsSet != NULL) &&
11755 (completeWild->negNsSet->value != NULL) &&
11756 (curWild->nsSet != NULL)) ||
11757 ((curWild->negNsSet != NULL) &&
11758 (curWild->negNsSet->value != NULL) &&
11759 (completeWild->nsSet != NULL))) {
11760
11761 int nsFound, absentFound = 0;
11762
11763 if (completeWild->nsSet != NULL) {
11764 cur = completeWild->nsSet;
11765 curB = curWild->negNsSet;
11766 } else {
11767 cur = curWild->nsSet;
11768 curB = completeWild->negNsSet;
11769 }
11770 nsFound = 0;
11771 while (cur != NULL) {
11772 if (cur->value == NULL)
11773 absentFound = 1;
11774 else if (cur->value == curB->value)
11775 nsFound = 1;
11776 if (nsFound && absentFound)
11777 break;
11778 cur = cur->next;
11779 }
11780
11781 if (nsFound && absentFound) {
11782 /*
11783 * 5.1 If the set S includes both the negated namespace
11784 * name and ·absent·, then any must be the value.
11785 */
11786 completeWild->any = 1;
11787 if (completeWild->nsSet != NULL) {
11788 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11789 completeWild->nsSet = NULL;
11790 }
11791 if (completeWild->negNsSet != NULL) {
11792 xmlFree(completeWild->negNsSet);
11793 completeWild->negNsSet = NULL;
11794 }
11795 } else if (nsFound && (!absentFound)) {
11796 /*
11797 * 5.2 If the set S includes the negated namespace name
11798 * but not ·absent·, then a pair of not and ·absent· must
11799 * be the value.
11800 */
11801 if (completeWild->nsSet != NULL) {
11802 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11803 completeWild->nsSet = NULL;
11804 }
11805 if (completeWild->negNsSet == NULL) {
11806 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11807 if (completeWild->negNsSet == NULL)
11808 return (-1);
11809 }
11810 completeWild->negNsSet->value = NULL;
11811 } else if ((!nsFound) && absentFound) {
11812 /*
11813 * 5.3 If the set S includes ·absent· but not the negated
11814 * namespace name, then the union is not expressible.
11815 */
11816 xmlSchemaPErr(ctxt, completeWild->node,
11817 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011818 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011819 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011820 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011821 } else if ((!nsFound) && (!absentFound)) {
11822 /*
11823 * 5.4 If the set S does not include either the negated namespace
11824 * name or ·absent·, then whichever of O1 or O2 is a pair of not
11825 * and a namespace name must be the value.
11826 */
11827 if (completeWild->negNsSet == NULL) {
11828 if (completeWild->nsSet != NULL) {
11829 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11830 completeWild->nsSet = NULL;
11831 }
11832 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11833 if (completeWild->negNsSet == NULL)
11834 return (-1);
11835 completeWild->negNsSet->value = curWild->negNsSet->value;
11836 }
11837 }
11838 return (0);
11839 }
11840 /*
11841 * 6.
11842 */
11843 if (((completeWild->negNsSet != NULL) &&
11844 (completeWild->negNsSet->value == NULL) &&
11845 (curWild->nsSet != NULL)) ||
11846 ((curWild->negNsSet != NULL) &&
11847 (curWild->negNsSet->value == NULL) &&
11848 (completeWild->nsSet != NULL))) {
11849
11850 if (completeWild->nsSet != NULL) {
11851 cur = completeWild->nsSet;
11852 } else {
11853 cur = curWild->nsSet;
11854 }
11855 while (cur != NULL) {
11856 if (cur->value == NULL) {
11857 /*
11858 * 6.1 If the set S includes ·absent·, then any must be the
11859 * value.
11860 */
11861 completeWild->any = 1;
11862 if (completeWild->nsSet != NULL) {
11863 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11864 completeWild->nsSet = NULL;
11865 }
11866 if (completeWild->negNsSet != NULL) {
11867 xmlFree(completeWild->negNsSet);
11868 completeWild->negNsSet = NULL;
11869 }
11870 return (0);
11871 }
11872 cur = cur->next;
11873 }
11874 if (completeWild->negNsSet == NULL) {
11875 /*
11876 * 6.2 If the set S does not include ·absent·, then a pair of not
11877 * and ·absent· must be the value.
11878 */
11879 if (completeWild->nsSet != NULL) {
11880 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11881 completeWild->nsSet = NULL;
11882 }
11883 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11884 if (completeWild->negNsSet == NULL)
11885 return (-1);
11886 completeWild->negNsSet->value = NULL;
11887 }
11888 return (0);
11889 }
11890 return (0);
11891
11892}
11893
Daniel Veillard50355f02004-06-08 17:52:16 +000011894/**
11895 * xmlSchemaIntersectWildcards:
11896 * @ctxt: the schema parser context
11897 * @completeWild: the first wildcard
11898 * @curWild: the second wildcard
11899 *
11900 * Intersects the namespace constraints of the given wildcards.
11901 * @completeWild will hold the resulting intersection.
11902 * Returns a positive error code on failure, -1 in case of an
11903 * internal error, 0 otherwise.
11904 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011905static int
11906xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
11907 xmlSchemaWildcardPtr completeWild,
11908 xmlSchemaWildcardPtr curWild)
11909{
William M. Brack803812b2004-06-03 02:11:24 +000011910 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011911
11912 /*
11913 * 1 If O1 and O2 are the same value, then that value must be the
11914 * value.
11915 */
11916 if ((completeWild->any == curWild->any) &&
11917 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11918 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
11919
11920 if ((completeWild->negNsSet == NULL) ||
11921 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
11922
11923 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011924 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011925
11926 /*
11927 * Check equality of sets.
11928 */
11929 cur = completeWild->nsSet;
11930 while (cur != NULL) {
11931 found = 0;
11932 curB = curWild->nsSet;
11933 while (curB != NULL) {
11934 if (cur->value == curB->value) {
11935 found = 1;
11936 break;
11937 }
11938 curB = curB->next;
11939 }
11940 if (!found)
11941 break;
11942 cur = cur->next;
11943 }
11944 if (found)
11945 return(0);
11946 } else
11947 return(0);
11948 }
11949 }
11950 /*
11951 * 2 If either O1 or O2 is any, then the other must be the value.
11952 */
11953 if ((completeWild->any != curWild->any) && (completeWild->any)) {
11954 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
11955 return(-1);
11956 return(0);
11957 }
11958 /*
11959 * 3 If either O1 or O2 is a pair of not and a value (a namespace
11960 * name or ·absent·) and the other is a set of (namespace names or
11961 * ·absent·), then that set, minus the negated value if it was in
11962 * the set, minus ·absent· if it was in the set, must be the value.
11963 */
11964 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
11965 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
11966 const xmlChar *neg;
11967
11968 if (completeWild->nsSet == NULL) {
11969 neg = completeWild->negNsSet->value;
11970 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
11971 return(-1);
11972 } else
11973 neg = curWild->negNsSet->value;
11974 /*
11975 * Remove absent and negated.
11976 */
11977 prev = NULL;
11978 cur = completeWild->nsSet;
11979 while (cur != NULL) {
11980 if (cur->value == NULL) {
11981 if (prev == NULL)
11982 completeWild->nsSet = cur->next;
11983 else
11984 prev->next = cur->next;
11985 xmlFree(cur);
11986 break;
11987 }
11988 prev = cur;
11989 cur = cur->next;
11990 }
11991 if (neg != NULL) {
11992 prev = NULL;
11993 cur = completeWild->nsSet;
11994 while (cur != NULL) {
11995 if (cur->value == neg) {
11996 if (prev == NULL)
11997 completeWild->nsSet = cur->next;
11998 else
11999 prev->next = cur->next;
12000 xmlFree(cur);
12001 break;
12002 }
12003 prev = cur;
12004 cur = cur->next;
12005 }
12006 }
12007
12008 return(0);
12009 }
12010 /*
12011 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
12012 * then the intersection of those sets must be the value.
12013 */
12014 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
12015 int found;
12016
12017 cur = completeWild->nsSet;
12018 prev = NULL;
12019 while (cur != NULL) {
12020 found = 0;
12021 curB = curWild->nsSet;
12022 while (curB != NULL) {
12023 if (cur->value == curB->value) {
12024 found = 1;
12025 break;
12026 }
12027 curB = curB->next;
12028 }
12029 if (!found) {
12030 if (prev == NULL)
12031 completeWild->nsSet = cur->next;
12032 else
12033 prev->next = cur->next;
12034 tmp = cur->next;
12035 xmlFree(cur);
12036 cur = tmp;
12037 continue;
12038 }
12039 prev = cur;
12040 cur = cur->next;
12041 }
12042
12043 return(0);
12044 }
12045 /* 5 If the two are negations of different namespace names,
12046 * then the intersection is not expressible
12047 */
12048 if ((completeWild->negNsSet != NULL) &&
12049 (curWild->negNsSet != NULL) &&
12050 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
12051 (completeWild->negNsSet->value != NULL) &&
12052 (curWild->negNsSet->value != NULL)) {
12053
12054 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012055 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000012056 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012057 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012058 }
12059 /*
12060 * 6 If the one is a negation of a namespace name and the other
12061 * is a negation of ·absent·, then the one which is the negation
12062 * of a namespace name must be the value.
12063 */
12064 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12065 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
12066 (completeWild->negNsSet->value == NULL)) {
12067 completeWild->negNsSet->value = curWild->negNsSet->value;
12068 }
12069 return(0);
12070}
12071
Daniel Veillard50355f02004-06-08 17:52:16 +000012072/**
12073 * xmlSchemaIsWildcardNsConstraintSubset:
12074 * @ctxt: the schema parser context
12075 * @wildA: the first wildcard
12076 * @wildB: the second wildcard
12077 *
12078 * Returns 1 if the namespace constraint of @wildA is an intensional
12079 * subset of @wildB, 0 otherwise.
12080 */
12081static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000012082xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
12083 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000012084{
Daniel Veillard3646d642004-06-02 19:19:14 +000012085
Daniel Veillard50355f02004-06-08 17:52:16 +000012086 /*
12087 * Schema Component Constraint: Wildcard Subset
12088 */
12089 /*
12090 * 1 super must be any.
12091 */
12092 if (wildB->any)
12093 return (1);
12094 /*
12095 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12096 * 2.2 super must be a pair of not and the same value.
12097 */
12098 if ((wildA->negNsSet != NULL) &&
12099 (wildB->negNsSet != NULL) &&
12100 (wildA->negNsSet->value == wildA->negNsSet->value))
12101 return (1);
12102 /*
12103 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
12104 */
12105 if (wildA->nsSet != NULL) {
12106 /*
12107 * 3.2.1 super must be the same set or a superset thereof.
12108 */
12109 if (wildB->nsSet != NULL) {
12110 xmlSchemaWildcardNsPtr cur, curB;
12111 int found = 0;
12112
12113 cur = wildA->nsSet;
12114 while (cur != NULL) {
12115 found = 0;
12116 curB = wildB->nsSet;
12117 while (curB != NULL) {
12118 if (cur->value == curB->value) {
12119 found = 1;
12120 break;
12121 }
12122 curB = curB->next;
12123 }
12124 if (!found)
12125 return (0);
12126 cur = cur->next;
12127 }
12128 if (found)
12129 return (1);
12130 } else if (wildB->negNsSet != NULL) {
12131 xmlSchemaWildcardNsPtr cur;
12132 /*
12133 * 3.2.2 super must be a pair of not and a namespace name or
12134 * ·absent· and that value must not be in sub's set.
12135 */
12136 cur = wildA->nsSet;
12137 while (cur != NULL) {
12138 if (cur->value == wildB->negNsSet->value)
12139 return (0);
12140 cur = cur->next;
12141 }
12142 return (1);
12143 }
12144 }
12145 return (0);
12146}
12147
12148/**
12149 * xmlSchemaBuildCompleteAttributeWildcard:
12150 * @ctxt: the schema parser context
12151 * @attrs: the attribute list
12152 * @completeWild: the resulting complete wildcard
12153 *
12154 * Returns -1 in case of an internal error, 0 otherwise.
12155 */
12156static int
12157xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
12158 xmlSchemaAttributePtr attrs,
12159 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000012160{
12161 while (attrs != NULL) {
12162 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12163 xmlSchemaAttributeGroupPtr group;
12164
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012165 group = (xmlSchemaAttributeGroupPtr) attrs;
12166 /*
12167 * Handle attribute group references.
12168 */
12169 if (group->ref != NULL) {
12170 if (group->refItem == NULL) {
12171 /*
12172 * TODO: Should we raise a warning here?
12173 */
12174 /*
12175 * The referenced attribute group definition could not
12176 * be resolved beforehand, so skip.
12177 */
12178 attrs = attrs->next;
12179 continue;
12180 } else
12181 group = group->refItem;
12182 }
12183 /*
12184 * For every attribute group definition, an intersected wildcard
12185 * will be created (assumed that a wildcard exists on the
12186 * particular attr. gr. def. or on any contained attr. gr. def
12187 * at all).
12188 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12189 * that the intersection will be performed only once.
12190 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012191 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12192 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012193 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
12194 group->attributes, &group->attributeWildcard) == -1)
12195 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012196 }
12197 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
12198 }
12199 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012200 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012201 /*
12202 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012203 *
12204 * Although the complete wildcard might not correspond to any
12205 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012206 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012207 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12208 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12209 group->attributeWildcard->node);
Daniel Veillard50355f02004-06-08 17:52:16 +000012210 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
12211 completeWild, group->attributeWildcard) == -1)
12212 return (-1);
12213 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012214 (*completeWild)->node = group->attributeWildcard->node;
12215 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012216 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012217 }
12218 }
12219 attrs = attrs->next;
12220 }
12221
Daniel Veillard50355f02004-06-08 17:52:16 +000012222 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012223}
12224
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012225static int
12226xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12227 int *fixed,
12228 const xmlChar **value,
12229 xmlSchemaValPtr *val)
12230{
12231 *fixed = 0;
12232 *value = NULL;
12233 if (val != 0)
12234 *val = NULL;
12235
12236 if (item->defValue == NULL)
12237 item = item->refDecl;
12238
12239 if (item == NULL)
12240 return (0);
12241
12242 if (item->defValue != NULL) {
12243 *value = item->defValue;
12244 if (val != 0)
12245 *val = item->defVal;
12246 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12247 *fixed = 1;
12248 return (1);
12249 }
12250 return (0);
12251}
Daniel Veillard3646d642004-06-02 19:19:14 +000012252/**
12253 * xmlSchemaMatchesWildcardNs:
12254 * @wild: the wildcard
12255 * @ns: the namespace
12256 *
12257 *
12258 * Returns 1 if the given namespace matches the wildcard,
12259 * 0 otherwise.
12260 */
12261static int
12262xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
12263{
12264 if (wild == NULL)
12265 return(0);
12266
12267 if (wild->any)
12268 return(1);
12269 else if (wild->nsSet != NULL) {
12270 xmlSchemaWildcardNsPtr cur;
12271
12272 cur = wild->nsSet;
12273 while (cur != NULL) {
12274 if (xmlStrEqual(cur->value, ns))
12275 return(1);
12276 cur = cur->next;
12277 }
12278 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
12279 (!xmlStrEqual(wild->negNsSet->value, ns)))
12280 return(1);
12281
12282 return(0);
12283}
12284
12285/**
12286 * xmlSchemaBuildAttributeValidation:
12287 * @ctxt: the schema parser context
12288 * @type: the complex type definition
12289 *
12290 *
12291 * Builds the wildcard and the attribute uses on the given complex type.
12292 * Returns -1 if an internal error occurs, 0 otherwise.
12293 */
12294static int
12295xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
12296{
12297 xmlSchemaTypePtr baseType = NULL;
12298 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000012299 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012300 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012301 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000012302 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012303 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012304 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012305
Daniel Veillard01fa6152004-06-29 17:04:39 +000012306 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012307 /*
12308 * Complex Type Definition with complex content Schema Component.
12309 *
12310 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012311 * TODO: Add checks for absent referenced attribute declarations and
12312 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012313 */
12314 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012315 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012316 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000012317 "attribute uses already builded.\n",
12318 NULL, NULL);
12319 return (-1);
12320 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012321 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012322 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012323 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012324 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012325 type->name, NULL);
12326 return (-1);
12327 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012328 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012329 if (baseType == anyType)
12330 baseIsAnyType = 1;
12331 /*
12332 * Inherit the attribute uses of the base type.
12333 */
12334 /*
12335 * NOTE: It is allowed to "extend" the anyType complex type.
12336 */
12337 if (!baseIsAnyType) {
12338 if (baseType != NULL) {
12339 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
12340 tmp = (xmlSchemaAttributeLinkPtr)
12341 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12342 if (tmp == NULL) {
12343 xmlSchemaPErrMemory(ctxt,
12344 "building attribute uses of complexType", NULL);
12345 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012346 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012347 tmp->attr = cur->attr;
12348 tmp->next = NULL;
12349 if (type->attributeUses == NULL) {
12350 type->attributeUses = tmp;
12351 } else
12352 lastBaseUse->next = tmp;
12353 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012354 }
12355 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012356 }
12357 if ((type->subtypes != NULL) &&
12358 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
12359 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012360 /*
12361 * type --> (<simpleContent>|<complexContent>)
12362 * --> (<restriction>|<extension>) --> attributes
12363 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012364 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012365 } else {
12366 /* Short hand form of the complexType. */
12367 attrs = type->attributes;
12368 }
12369 /*
12370 * Handle attribute wildcards.
12371 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012372 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
12373 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012374 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012375 * NOTE: During the parse time, the wildcard is created on the complexType
12376 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012377 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012378 if (err == -1) {
12379 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
12380 "Internal error: xmlSchemaBuildAttributeValidation: "
12381 "failed to build an intersected attribute wildcard.\n",
12382 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012383 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012384 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012385
12386 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12387 ((baseIsAnyType) ||
12388 ((baseType != NULL) &&
12389 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12390 (baseType->attributeWildcard != NULL)))) {
12391 if (type->attributeWildcard != NULL) {
12392 /*
12393 * Union the complete wildcard with the base wildcard.
12394 */
12395 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
12396 baseType->attributeWildcard) == -1)
12397 return (-1);
12398 } else {
12399 /*
12400 * Just inherit the wildcard.
12401 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012402 /*
12403 * NOTE: This is the only case where an attribute
12404 * wildcard is shared.
12405 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012406 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012407 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012408 }
12409
12410 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12411 if (type->attributeWildcard != NULL) {
12412 /*
12413 * Derivation Valid (Restriction, Complex)
12414 * 4.1 The {base type definition} must also have one.
12415 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012416 if (baseType->attributeWildcard == NULL) {
12417 xmlSchemaPCustomErr(ctxt,
12418 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
12419 NULL, type, NULL,
12420 "The type has an attribute wildcard, "
12421 "but the base type %s does not have one",
12422 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12423 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012424 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000012425 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012426 type->attributeWildcard, baseType->attributeWildcard) == 0) {
12427 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012428 xmlSchemaPCustomErr(ctxt,
12429 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
12430 NULL, type, NULL,
12431 "The attribute wildcard is not a valid "
12432 "subset of the wildcard in the base type %s",
12433 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12434 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012435 return (1);
12436 }
12437 /* 4.3 Unless the {base type definition} is the ·ur-type
12438 * definition·, the complex type definition's {attribute
12439 * wildcard}'s {process contents} must be identical to or
12440 * stronger than the {base type definition}'s {attribute
12441 * wildcard}'s {process contents}, where strict is stronger
12442 * than lax is stronger than skip.
12443 */
12444 if ((type->baseType != anyType) &&
12445 (type->attributeWildcard->processContents <
12446 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012447 xmlSchemaPCustomErr(ctxt,
12448 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
12449 NULL, type, NULL,
12450 "The 'process contents' of the attribute wildcard is weaker than "
12451 "the one in the base type %s",
12452 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12453 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012454 return (1);
12455 }
12456 }
12457 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12458 /*
12459 * Derivation Valid (Extension)
12460 * At this point the type and the base have both, either
12461 * no wildcard or a wildcard.
12462 */
12463 if ((baseType->attributeWildcard != NULL) &&
12464 (baseType->attributeWildcard != type->attributeWildcard)) {
12465 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012466 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012467 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012468 xmlSchemaPCustomErr(ctxt,
12469 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
12470 NULL, type, NULL,
12471 "The attribute wildcard is not a valid "
12472 "superset of the one in the base type %s",
12473 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12474 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012475 return (1);
12476 }
12477 }
12478 }
12479
Daniel Veillard3646d642004-06-02 19:19:14 +000012480 /*
12481 * Gather attribute uses defined by this type.
12482 */
12483 if (attrs != NULL) {
12484 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
12485 &uses, &lastUse) == -1) {
12486 return (-1);
12487 }
12488 }
12489 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
12490 * "Two distinct attribute declarations in the {attribute uses} must
12491 * not have identical {name}s and {target namespace}s."
12492 *
12493 * For "extension" this is done further down.
12494 */
12495 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
12496 cur = uses;
12497 while (cur != NULL) {
12498 tmp = cur->next;
12499 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012500 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12501 xmlSchemaGetAttrName(tmp->attr))) &&
12502 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
12503 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12504
12505 xmlSchemaPAttrUseErr(ctxt,
12506 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12507 NULL, type, NULL, cur->attr,
12508 "Duplicate attribute use %s specified",
12509 xmlSchemaFormatNsUriLocal(&str,
12510 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12511 xmlSchemaGetAttrName(tmp->attr))
12512 );
12513 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012514 break;
12515 }
12516 tmp = tmp->next;
12517 }
12518 cur = cur->next;
12519 }
12520 }
12521 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12522 /*
12523 * Derive by restriction.
12524 */
12525 if (baseIsAnyType) {
12526 type->attributeUses = uses;
12527 } else {
12528 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012529 const xmlChar *bEffValue;
12530 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012531
12532 cur = uses;
12533 while (cur != NULL) {
12534 found = 0;
12535 base = type->attributeUses;
12536 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012537 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12538 xmlSchemaGetAttrName(base->attr)) &&
12539 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
12540 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012541
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012542 found = 1;
12543
Daniel Veillard3646d642004-06-02 19:19:14 +000012544 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12545 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12546 /*
12547 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000012548 */
12549 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012550 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012551 NULL, type, NULL, cur->attr,
12552 "The 'optional' use is inconsistent with a matching "
12553 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012554 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12555 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12556 /*
12557 * derivation-ok-restriction 3
12558 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012559 xmlSchemaPCustomErr(ctxt,
12560 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12561 NULL, type, NULL,
12562 "A matching attribute use for the 'required' "
12563 "attribute use %s of the base type is missing",
12564 xmlSchemaFormatNsUriLocal(&str,
12565 xmlSchemaGetAttrTargetNsURI(base->attr),
12566 xmlSchemaGetAttrName(base->attr)));
12567 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012568 } else {
12569 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012570 * 2.1.3 [Definition:] Let the effective value
12571 * constraint of an attribute use be its {value
12572 * constraint}, if present, otherwise its {attribute
12573 * declaration}'s {value constraint} .
12574 */
12575 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
12576 &bEffValue, 0);
12577 /*
12578 * 2.1.3 ... one of the following must be true
12579 *
12580 * 2.1.3.1 B's ·effective value constraint· is
12581 * ·absent· or default.
12582 */
12583 if ((bEffValue != NULL) &&
12584 (effFixed == 1)) {
12585 const xmlChar *rEffValue = NULL;
12586
12587 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
12588 &rEffValue, 0);
12589 /*
12590 * 2.1.3.2 R's ·effective value constraint· is
12591 * fixed with the same string as B's.
12592 */
12593 if ((effFixed == 0) ||
12594 (! xmlStrEqual(rEffValue, bEffValue))) {
12595 xmlSchemaPAttrUseErr(ctxt,
12596 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12597 NULL, type, NULL, cur->attr,
12598 "The effective value constraint of the "
12599 "attribute use is inconsistent with "
12600 "its correspondent of the base type",
12601 NULL);
12602 }
12603 }
12604 /*
12605 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
12606 */
12607 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012608 * Override the attribute use.
12609 */
12610 base->attr = cur->attr;
12611 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012612
Daniel Veillard3646d642004-06-02 19:19:14 +000012613 break;
12614 }
12615 base = base->next;
12616 }
12617
12618 if (!found) {
12619 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12620 /*
12621 * derivation-ok-restriction 2.2
12622 */
12623 if ((type->attributeWildcard != NULL) &&
12624 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
12625 cur->attr->targetNamespace))
12626 found = 1;
12627
12628 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012629 xmlSchemaPAttrUseErr(ctxt,
12630 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12631 NULL, type, NULL, cur->attr,
12632 "Neither a matching attribute use, "
12633 "nor a matching wildcard in the base type does exist",
12634 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012635 } else {
12636 /*
12637 * Add the attribute use.
12638 *
12639 * Note that this may lead to funny derivation error reports, if
12640 * multiple equal attribute uses exist; but this is not
12641 * allowed anyway, and it will be reported beforehand.
12642 */
12643 tmp = cur;
12644 if (prev != NULL)
12645 prev->next = cur->next;
12646 else
12647 uses = cur->next;
12648 cur = cur->next;
12649 if (type->attributeUses == NULL) {
12650 type->attributeUses = tmp;
12651 } else
12652 lastBaseUse->next = tmp;
12653 lastBaseUse = tmp;
12654
12655 continue;
12656 }
12657 }
12658 }
12659 prev = cur;
12660 cur = cur->next;
12661 }
12662 if (uses != NULL)
12663 xmlSchemaFreeAttributeUseList(uses);
12664 }
12665 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12666 /*
12667 * The spec allows only appending, and not other kinds of extensions.
12668 *
12669 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
12670 */
12671 if (uses != NULL) {
12672 if (type->attributeUses == NULL) {
12673 type->attributeUses = uses;
12674 } else
12675 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012676 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012677 } else {
12678 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000012679 * Derive implicitely from the ur-type.
12680 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012681 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012682 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012683 /*
12684 * 3.4.6 -> Complex Type Definition Properties Correct
12685 */
12686 if (type->attributeUses != NULL) {
12687 cur = type->attributeUses;
12688 prev = NULL;
12689 while (cur != NULL) {
12690 /*
12691 * 4. Two distinct attribute declarations in the {attribute uses} must
12692 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012693 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012694 * Note that this was already done for "restriction" and types derived from
12695 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012696 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012697 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12698 tmp = cur->next;
12699 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012700 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12701 xmlSchemaGetAttrName(tmp->attr))) &&
12702 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
12703 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012704
Daniel Veillardc0826a72004-08-10 14:17:33 +000012705 xmlSchemaPAttrUseErr(ctxt,
12706 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12707 NULL, type, NULL, tmp->attr,
12708 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012709 break;
12710 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012711 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012712 }
12713 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012714 /*
12715 * 5. Two distinct attribute declarations in the {attribute uses} must
12716 * not have {type definition}s which are or are derived from ID.
12717 */
12718 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012719 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012720 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012721 xmlSchemaPAttrUseErr(ctxt,
12722 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12723 NULL, type, NULL, cur->attr,
12724 "There must not exist more than one attribute use, "
12725 "declared of type 'ID' or derived from it",
12726 NULL);
12727 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000012728 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012729 id = cur;
12730 }
12731 /*
12732 * Remove "prohibited" attribute uses. The reason this is done at this late
12733 * stage is to be able to catch dublicate attribute uses. So we had to keep
12734 * prohibited uses in the list as well.
12735 */
12736 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12737 tmp = cur;
12738 if (prev == NULL)
12739 type->attributeUses = cur->next;
12740 else
12741 prev->next = cur->next;
12742 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012743 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012744 } else {
12745 prev = cur;
12746 cur = cur->next;
12747 }
12748 }
12749 }
12750 /*
12751 * TODO: This check should be removed if we are 100% sure of
12752 * the base type attribute uses already being built.
12753 */
12754 if ((baseType != NULL) && (!baseIsAnyType) &&
12755 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012756 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012757 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012758 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012759 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000012760 baseType->name, NULL);
12761 }
12762 return (0);
12763}
12764
12765/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000012766 * xmlSchemaTypeFinalContains:
12767 * @schema: the schema
12768 * @type: the type definition
12769 * @final: the final
12770 *
12771 * Evaluates if a type definition contains the given "final".
12772 * This does take "finalDefault" into account as well.
12773 *
12774 * Returns 1 if the type does containt the given "final",
12775 * 0 otherwise.
12776 */
12777static int
12778xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
12779{
12780 int tfinal = final, tflags = type->flags;
12781
12782 if (type == NULL)
12783 return (0);
12784 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
12785 switch (final) {
12786 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
12787 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
12788 break;
12789 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
12790 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
12791 break;
12792 case XML_SCHEMAS_TYPE_FINAL_LIST:
12793 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
12794 break;
12795 case XML_SCHEMAS_TYPE_FINAL_UNION:
12796 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
12797 break;
12798 }
12799 tflags = schema->flags;
12800 }
12801 if (tflags & tfinal)
12802 return (1);
12803 else
12804 return (0);
12805
12806}
12807
12808/**
12809 * xmlSchemaGetUnionSimpleTypeMemberTypes:
12810 * @type: the Union Simple Type
12811 *
12812 * Returns a list of member types of @type if existing,
12813 * returns NULL otherwise.
12814 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012815static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000012816xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
12817{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012818 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012819 if (type->memberTypes != NULL)
12820 return (type->memberTypes);
12821 else
12822 type = type->baseType;
12823 }
12824 return (NULL);
12825}
12826
12827/**
12828 * xmlSchemaGetListSimpleTypeItemType:
12829 * @type: the simple type definition
12830 *
12831 * Returns the item type definition of the list simple type.
12832 */
12833static xmlSchemaTypePtr
12834xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
12835{
12836 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
12837 return (NULL);
12838 /*
12839 * Note: In libxml2, the built-in types do not reflect
12840 * the datatype hierarchy (yet?) - we have to treat them
12841 * in a special way.
12842 */
12843 if (type->type == XML_SCHEMA_TYPE_BASIC)
12844 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012845 return (type->subtypes);
12846}
12847
12848
12849static int
12850xmlSchemaGetParticleTotalRangeMin(xmlSchemaTreeItemPtr particle)
12851{
12852 if ((particle->children == NULL) ||
12853 ( ((xmlSchemaParticlePtr) particle)->minOccurs == 0))
12854 return (0);
12855 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
12856 int min = 0, cur;
12857 xmlSchemaTreeItemPtr part = particle->children->children;
12858
12859 if (part == NULL)
12860 return (0);
12861 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
12862 (part->children->type == XML_SCHEMA_TYPE_ANY))
12863 min = ((xmlSchemaParticlePtr) part)->minOccurs;
12864 else
12865 min = xmlSchemaGetParticleTotalRangeMin(part);
12866 if (min == 0)
12867 return (0);
12868 part = part->next;
12869 while (part != NULL) {
12870 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
12871 (part->children->type == XML_SCHEMA_TYPE_ANY))
12872 cur = ((xmlSchemaParticlePtr) part)->minOccurs;
12873 else
12874 cur = xmlSchemaGetParticleTotalRangeMin(part);
12875 if (cur == 0)
12876 return (0);
12877 if (min > cur)
12878 min = cur;
12879 part = part->next;
12880 }
12881 return (((xmlSchemaParticlePtr) particle)->minOccurs * min);
12882 } else {
12883 /* <all> and <sequence> */
12884 int sum = 0;
12885 xmlSchemaTreeItemPtr part = particle->children->children;
12886
12887 if (part == NULL)
12888 return (0);
12889 do {
12890 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
12891 (part->children->type == XML_SCHEMA_TYPE_ANY))
12892 sum += ((xmlSchemaParticlePtr) part)->minOccurs;
12893 else
12894 sum += xmlSchemaGetParticleTotalRangeMin(part);
12895 part = part->next;
12896 } while (part != NULL);
12897 return (((xmlSchemaParticlePtr) particle)->minOccurs * sum);
12898 }
12899}
12900
12901
12902static int
12903xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
12904{
12905 if ((particle == NULL) || (particle->minOccurs == 0) ||
12906 (particle->children == NULL))
12907 return (1);
12908
12909 if (IS_MODEL_GROUP(particle->children)) {
12910 if (xmlSchemaGetParticleTotalRangeMin(
12911 (xmlSchemaTreeItemPtr) particle) == 0)
12912 return (1);
12913 }
12914 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012915}
12916
12917/**
12918 * xmlSchemaCheckCOSSTDerivedOK:
12919 * @type: the derived simple type definition
12920 * @baseType: the base type definition
12921 *
12922 * Checks wheter @type can be validly
12923 * derived from @baseType.
12924 *
12925 * Returns 0 on success, an positive error code otherwise.
12926 */
12927static int
12928xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
12929 xmlSchemaTypePtr type,
12930 xmlSchemaTypePtr baseType,
12931 int subset)
12932{
12933 /*
12934 * Schema Component Constraint: Type Derivation OK (Simple)
12935 *
12936 *
12937 * 1 They are the same type definition.
12938 * TODO: The identy check might have to be more complex than this.
12939 */
12940 if (type == baseType)
12941 return (0);
12942 /*
12943 * 2.1 restriction is not in the subset, or in the {final}
12944 * of its own {base type definition};
12945 */
12946 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
12947 (xmlSchemaTypeFinalContains(schema,
12948 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
12949 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
12950 }
12951 /* 2.2 */
12952 if (type->baseType == baseType) {
12953 /*
12954 * 2.2.1 D's ·base type definition· is B.
12955 */
12956 return (0);
12957 }
12958 /*
12959 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
12960 * and is validly derived from B given the subset, as defined by this
12961 * constraint.
12962 */
12963 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
12964 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
12965 return (0);
12966 }
12967 /*
12968 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
12969 * definition·.
12970 */
12971 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
12972 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
12973 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
12974 return (0);
12975 }
12976 /*
12977 * 2.2.4 B's {variety} is union and D is validly derived from a type
12978 * definition in B's {member type definitions} given the subset, as
12979 * defined by this constraint.
12980 *
12981 * NOTE: This seems not to involve built-in types, since there is no
12982 * built-in Union Simple Type.
12983 */
12984 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12985 xmlSchemaTypeLinkPtr cur;
12986
12987 cur = baseType->memberTypes;
12988 while (cur != NULL) {
12989 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
12990 cur->type, subset) == 0)
12991 return (0);
12992 cur = cur->next;
12993 }
12994 }
12995
12996 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
12997}
12998
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012999/**
13000 * xmlSchemaCheckTypeDefCircularInternal:
13001 * @pctxt: the schema parser context
13002 * @ctxtType: the type definition
13003 * @ancestor: an ancestor of @ctxtType
13004 *
13005 * Checks st-props-correct (2) + ct-props-correct (3).
13006 * Circular type definitions are not allowed.
13007 *
13008 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13009 * circular, 0 otherwise.
13010 */
13011static int
13012xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13013 xmlSchemaTypePtr ctxtType,
13014 xmlSchemaTypePtr ancestor)
13015{
13016 int ret;
13017
13018 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13019 return (0);
13020
13021 if (IS_NOT_TYPEFIXED(ancestor))
13022 xmlSchemaTypeFixup(ancestor, pctxt, NULL);
13023 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13024 /*
13025 * Avoid inifinite recursion on circular types not yet checked.
13026 */
13027 return (0);
13028 }
13029 if (ctxtType == ancestor) {
13030 xmlSchemaPCustomErr(pctxt,
13031 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13032 NULL, ctxtType, GET_NODE(ctxtType),
13033 "The definition is circular", NULL);
13034 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13035 }
13036 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13037 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13038 ancestor->baseType);
13039 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13040 return (ret);
13041}
13042
13043/**
13044 * xmlSchemaCheckGroupDefCircular:
13045 * @item: the complex/simple type definition
13046 * @ctxt: the parser context
13047 * @name: the name
13048 *
13049 * Checks for circular type definitions.
13050 */
13051static void
13052xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
13053 xmlSchemaParserCtxtPtr ctxt,
13054 const xmlChar * name ATTRIBUTE_UNUSED)
13055{
13056 if ((item == NULL) ||
13057 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13058 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13059 return;
13060 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13061
13062}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013063
13064/**
13065 * xmlSchemaCheckSTPropsCorrect:
13066 * @ctxt: the schema parser context
13067 * @type: the simple type definition
13068 *
13069 * Checks st-props-correct.
13070 *
13071 * Returns 0 if the properties are correct,
13072 * if not, a positive error code and -1 on internal
13073 * errors.
13074 */
13075static int
13076xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
13077 xmlSchemaTypePtr type)
13078{
13079 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13080 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013081 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013082
Daniel Veillardc0826a72004-08-10 14:17:33 +000013083 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013084 /*
13085 * Schema Component Constraint: Simple Type Definition Properties Correct
13086 *
13087 * NOTE: This is somehow redundant, since we actually built a simple type
13088 * to have all the needed information; this acts as an self test.
13089 */
13090 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13091 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013092 /* Base type: If the datatype has been ·derived· by ·restriction·
13093 * then the Simple Type Definition component from which it is ·derived·,
13094 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
13095 */
13096 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013097 /*
13098 * TODO: Think about: "modulo the impact of Missing
13099 * Sub-components (§5.3)."
13100 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013101 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013102 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013103 NULL, type, NULL,
13104 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013105 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013106
Daniel Veillard01fa6152004-06-29 17:04:39 +000013107 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013108 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013109 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013110 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013111 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013112 "The base type '%s' is not a simple type",
13113 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013114 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013115 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13116 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013117 if ((baseType->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
13118 ((type->flags &
13119 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13120 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
13121 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013122 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013123 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013124 NULL, type, NULL,
13125 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013126 "the simple ur-type definition as base type, not '%s'",
13127 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013128 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013129 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13130 }
13131 /*
13132 * Variety: One of {atomic, list, union}.
13133 */
13134 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13135 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
13136 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013137 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013138 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013139 NULL, type, NULL,
13140 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013141 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13142 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013143 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013144
13145 /*
13146 * 3 The {final} of the {base type definition} must not contain restriction.
13147 */
13148 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
13149 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13150 xmlSchemaPCustomErr(ctxt,
13151 XML_SCHEMAP_ST_PROPS_CORRECT_3,
13152 NULL, type, NULL,
13153 "The 'final' of its base type '%s' must not contain "
13154 "'restriction'",
13155 xmlSchemaGetComponentQName(&str, baseType));
13156 FREE_AND_NULL(str)
13157 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
13158 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013159
13160 /*
13161 * 2 All simple type definitions must be derived ultimately from the ·simple
13162 * ur-type definition (so· circular definitions are disallowed). That is, it
13163 * must be possible to reach a built-in primitive datatype or the ·simple
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013164 * ur-type definition· by repeatedly following the {base type definition}.
13165 *
13166 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013167 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013168 return (0);
13169}
13170
13171/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013172 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013173 * @ctxt: the schema parser context
13174 * @type: the simple type definition
13175 *
13176 * Checks if the given @type (simpleType) is derived
13177 * validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013178 * STATUS:
13179 * missing:
13180 * (3.3.2.5) facet derivation
13181 * (1.3.2) facet derivation
13182 * (2.3.2.5)
13183 * (3.3.2.5) facet derivation
13184 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000013185 *
13186 * Returns -1 on internal errors, 0 if the type is validly derived,
13187 * a positive error code otherwise.
13188 */
13189static int
13190xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013191 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013192{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013193 xmlChar *str = NULL;
13194
Daniel Veillard01fa6152004-06-29 17:04:39 +000013195 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
13196 xmlSchemaPErr(ctxt, type->node,
13197 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013198 "xmlSchemaCheckCOSSTRestricts: The given "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013199 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013200 type->name, NULL);
13201 return (-1);
13202 }
13203
13204 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
13205 xmlSchemaTypePtr primitive;
13206 /*
13207 * 1.1 The {base type definition} must be an atomic simple
13208 * type definition or a built-in primitive datatype.
13209 */
13210 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013211 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013212 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013213 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013214 "The base type '%s' is not an atomic simple type",
13215 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013216 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013217 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13218 }
13219 /* 1.2 The {final} of the {base type definition} must not contain
13220 * restriction.
13221 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013222 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013223 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13224 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013225 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013226 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013227 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013228 "The final of its base type '%s' must not contain 'restriction'",
13229 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013230 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013231 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13232 }
13233
13234 /*
13235 * 1.3.1 DF must be an allowed constraining facet for the {primitive
13236 * type definition}, as specified in the appropriate subsection of 3.2
13237 * Primitive datatypes.
13238 */
13239 if (type->facets != NULL) {
13240 xmlSchemaFacetPtr facet;
13241 int ok = 1;
13242
13243 primitive = xmlSchemaGetPrimitiveType(type);
13244 if (primitive == NULL) {
13245 xmlSchemaPErr(ctxt, type->node,
13246 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013247 "xmlSchemaCheckCOSSTRestricts: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013248 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013249 type->name, NULL);
13250 return (-1);
13251 }
13252 facet = type->facets;
13253 do {
13254 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013255 ok = 0;
13256 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013257 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013258 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013259 }
13260 facet = facet->next;
13261 } while (facet != NULL);
13262 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000013263 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013264 }
13265 /*
13266 * TODO: 1.3.2 (facet derivation)
13267 */
13268 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13269 xmlSchemaTypePtr itemType = NULL;
13270
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013271 itemType = type->subtypes;
13272 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013273 xmlSchemaPErr(ctxt, type->node,
13274 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013275 "Internal error: xmlSchemaCheckCOSSTRestricts: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013276 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013277 type->name, NULL);
13278 return (-1);
13279 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013280 if (IS_NOT_TYPEFIXED(itemType))
13281 xmlSchemaTypeFixup(itemType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013282 /*
13283 * 2.1 The {item type definition} must have a {variety} of atomic or
13284 * union (in which case all the {member type definitions}
13285 * must be atomic).
13286 */
13287 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13288 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013289 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013290 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013291 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013292 "The item type '%s' does not have a variety of atomic or union",
13293 xmlSchemaGetComponentQName(&str, itemType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013294 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013295 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13296 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13297 xmlSchemaTypeLinkPtr member;
13298
13299 member = itemType->memberTypes;
13300 while (member != NULL) {
13301 if ((member->type->flags &
13302 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013303 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013304 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013305 NULL, type, NULL,
13306 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013307 "member type '%s' of this item type is not atomic",
13308 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013309 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013310 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13311 }
13312 member = member->next;
13313 }
13314 }
13315
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013316 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013317 xmlSchemaFacetPtr facet;
13318 /*
13319 * This is the case if we have: <simpleType><list ..
13320 */
13321 /*
13322 * 2.3.1
13323 * 2.3.1.1 The {final} of the {item type definition} must not
13324 * contain list.
13325 */
13326 if (xmlSchemaTypeFinalContains(ctxt->schema,
13327 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013328 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013329 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013330 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013331 "The final of its item type '%s' must not contain 'list'",
13332 xmlSchemaGetComponentQName(&str, itemType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013333 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013334 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13335 }
13336 /*
13337 * 2.3.1.2 The {facets} must only contain the whiteSpace
13338 * facet component.
13339 */
13340 if (type->facets != NULL) {
13341 facet = type->facets;
13342 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013343 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13344 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013345 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013346 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013347 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13348 }
13349 facet = facet->next;
13350 } while (facet != NULL);
13351 }
13352 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013353 * MABY TODO: (Hmm, not really) Datatypes states:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013354 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13355 * whose ·lexical space· allows space (such as string or anyURI)or
13356 * a ·union· datatype any of whose {member type definitions}'s
13357 * ·lexical space· allows space.
13358 */
13359 } else {
13360 /*
13361 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013362 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013363 */
13364 /*
13365 * 2.3.2
13366 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13367 */
13368 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 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_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013371 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013372 "The base type '%s' must be a list type",
13373 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013374 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013375 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13376 }
13377 /*
13378 * 2.3.2.2 The {final} of the {base type definition} must not
13379 * contain restriction.
13380 */
13381 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13382 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013383 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013384 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013385 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013386 "The 'final' of the base type '%s' must not contain 'restriction'",
13387 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013388 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013389 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13390 }
13391 /*
13392 * 2.3.2.3 The {item type definition} must be validly derived
13393 * from the {base type definition}'s {item type definition} given
13394 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13395 */
13396 {
13397 xmlSchemaTypePtr baseItemType;
13398
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013399 baseItemType = type->baseType->subtypes;
13400 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013401 xmlSchemaPErr(ctxt, type->node,
13402 XML_ERR_INTERNAL_ERROR,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013403 "Internal error: xmlSchemaCheckCOSSTRestricts, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013404 "List simple type '%s': Failed to "
13405 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013406 type->name, type->baseType->name);
13407 return (-1);
13408 }
13409 if ((itemType != baseItemType) &&
13410 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
13411 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013412 xmlChar *strBIT = NULL, *strBT = NULL;
13413 xmlSchemaPCustomErrExt(ctxt,
13414 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
13415 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013416 "The item type '%s' is not validly derived from the "
13417 "item type '%s' of the base type '%s'",
13418 xmlSchemaGetComponentQName(&str, itemType),
13419 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13420 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013421
13422 FREE_AND_NULL(str)
13423 FREE_AND_NULL(strBIT)
13424 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013425 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13426 }
13427 }
13428
13429 if (type->facets != NULL) {
13430 xmlSchemaFacetPtr facet;
13431 int ok = 1;
13432 /*
13433 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
13434 * and enumeration facet components are allowed among the {facets}.
13435 */
13436 facet = type->facets;
13437 do {
13438 switch (facet->type) {
13439 case XML_SCHEMA_FACET_LENGTH:
13440 case XML_SCHEMA_FACET_MINLENGTH:
13441 case XML_SCHEMA_FACET_MAXLENGTH:
13442 case XML_SCHEMA_FACET_WHITESPACE:
13443 /*
13444 * TODO: 2.5.1.2 List datatypes
13445 * The value of ·whiteSpace· is fixed to the value collapse.
13446 */
13447 case XML_SCHEMA_FACET_PATTERN:
13448 case XML_SCHEMA_FACET_ENUMERATION:
13449 break;
13450 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013451 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013452 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013453 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013454 /*
13455 * We could return, but it's nicer to report all
13456 * invalid facets.
13457 */
13458 ok = 0;
13459 }
13460 }
13461 facet = facet->next;
13462 } while (facet != NULL);
13463 if (ok == 0)
13464 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13465 /*
13466 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
13467 * is a facet of the same kind in the {facets} of the {base type
13468 * definition} (call this BF),then the DF's {value} must be a valid
13469 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
13470 */
13471 }
13472
13473
13474 }
13475 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
13476 /*
13477 * 3.1 The {member type definitions} must all have {variety} of
13478 * atomic or list.
13479 */
13480 xmlSchemaTypeLinkPtr member;
13481
13482 member = type->memberTypes;
13483 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013484 if (IS_NOT_TYPEFIXED(member->type))
13485 xmlSchemaTypeFixup(member->type, ctxt, NULL);
13486
Daniel Veillard01fa6152004-06-29 17:04:39 +000013487 if (((member->type->flags &
13488 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
13489 ((member->type->flags &
13490 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013491 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013492 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013493 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013494 "The member type '%s' is neither an atomic, nor a list type",
13495 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013496 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013497 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13498 }
13499 member = member->next;
13500 }
13501 /*
13502 * 3.3.1 If the {base type definition} is the ·simple ur-type
13503 * definition·
13504 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013505 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013506 /*
13507 * 3.3.1.1 All of the {member type definitions} must have a
13508 * {final} which does not contain union.
13509 */
13510 member = type->memberTypes;
13511 while (member != NULL) {
13512 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
13513 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013514 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013515 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013516 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013517 "The 'final' of member type '%s' contains 'union'",
13518 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013519 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013520 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13521 }
13522 member = member->next;
13523 }
13524 /*
13525 * 3.3.1.2 The {facets} must be empty.
13526 */
13527 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013528 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013529 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013530 NULL, type, NULL,
13531 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013532 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13533 }
13534 } else {
13535 /*
13536 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013537 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013538 */
13539 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013540 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013541 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013542 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013543 "The base type '%s' is not a union type",
13544 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013545 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013546 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13547 }
13548 /*
13549 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13550 */
13551 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
13552 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013553 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013554 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013555 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013556 "The 'final' of its base type '%s' must not contain 'restriction'",
13557 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013558 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013559 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13560 }
13561 /*
13562 * 3.3.2.3 The {member type definitions}, in order, must be validly
13563 * derived from the corresponding type definitions in the {base
13564 * type definition}'s {member type definitions} given the empty set,
13565 * as defined in Type Derivation OK (Simple) (§3.14.6).
13566 */
13567 {
13568 xmlSchemaTypeLinkPtr baseMember;
13569
13570 /*
13571 * OPTIMIZE: if the type is restricting, it has no local defined
13572 * member types and inherits the member types of the base type;
13573 * thus a check for equality can be skipped.
13574 */
13575 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013576 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000013577 * union simple type can have other member types as the member
13578 * types of it's base type. This check seems not necessary with
13579 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013580 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013581 */
13582 if (type->memberTypes != NULL) {
13583 member = type->memberTypes;
13584 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
13585 if ((member == NULL) && (baseMember != NULL)) {
13586 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013587 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013588 "Internal error: xmlSchemaCheckCOSSTRestricts, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013589 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013590 "of member types in the base type\n",
13591 type->name, NULL);
13592 }
13593 while (member != NULL) {
13594 if (baseMember == NULL) {
13595 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013596 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013597 "Internal error: "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013598 "xmlSchemaCheckCOSSTRestricts "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013599 "(3.3.2.3), union simple type '%s', unequal number "
13600 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013601 type->name, NULL);
13602 }
13603 if ((member->type != baseMember->type) &&
13604 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
13605 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013606 xmlChar *strBMT = NULL, *strBT = NULL;
13607
13608 xmlSchemaPCustomErrExt(ctxt,
13609 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13610 NULL, type, NULL,
13611 "The member type %s is not validly derived from its "
13612 "corresponding member type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013613 xmlSchemaGetComponentQName(&str, member->type),
13614 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13615 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013616 FREE_AND_NULL(str)
13617 FREE_AND_NULL(strBMT)
13618 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013619 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
13620 }
13621 member = member->next;
13622 baseMember = baseMember->next;
13623 }
13624 }
13625 }
13626 /*
13627 * 3.3.2.4 Only pattern and enumeration facet components are
13628 * allowed among the {facets}.
13629 */
13630 if (type->facets != NULL) {
13631 xmlSchemaFacetPtr facet;
13632 int ok = 1;
13633
13634 facet = type->facets;
13635 do {
13636 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13637 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013638 xmlSchemaPIllegalFacetListUnionErr(ctxt,
13639 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
13640 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013641 ok = 0;
13642 }
13643 facet = facet->next;
13644 } while (facet != NULL);
13645 if (ok == 0)
13646 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
13647
13648 }
13649 /*
13650 * TODO: 3.3.2.5 (facet derivation)
13651 */
13652 }
13653 }
13654
13655 return (0);
13656}
13657
13658/**
13659 * xmlSchemaCheckSRCSimpleType:
13660 * @ctxt: the schema parser context
13661 * @type: the simple type definition
13662 *
13663 * Checks crc-simple-type constraints.
13664 *
13665 * Returns 0 if the constraints are satisfied,
13666 * if not a positive error code and -1 on internal
13667 * errors.
13668 */
13669static int
13670xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
13671 xmlSchemaTypePtr type)
13672{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013673 /*
13674 * src-simple-type.1 The corresponding simple type definition, if any,
13675 * must satisfy the conditions set out in Constraints on Simple Type
13676 * Definition Schema Components (§3.14.6).
13677 */
13678 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
13679 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
13680 /*
13681 * TODO: Removed this, since it got annoying to get an
13682 * extra error report, if anything failed until now.
13683 * Enable this if needed.
13684 */
13685 /*
13686 xmlSchemaPErr(ctxt, type->node,
13687 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013688 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013689 "on simple type definitions.\n",
13690 type->name, NULL);
13691 */
13692 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
13693 }
13694
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013695 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013696 /*
13697 * src-simple-type.2 If the <restriction> alternative is chosen,
13698 * either it must have a base [attribute] or a <simpleType> among its
13699 * [children], but not both.
13700 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013701 /*
13702 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013703 * NOTE: This is checked in the parse function of <restriction>.
William M. Brack2f2a6632004-08-20 23:09:47 +000013704 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013705 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013706 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
13707 * an itemType [attribute] or a <simpleType> among its [children],
13708 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013709 *
13710 * REMOVED: This is checked in the parse function of <list>.
13711 */
13712 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013713 xmlSchemaTypeLinkPtr member;
13714 xmlSchemaTypePtr ancestor, anySimpleType;
13715
13716 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13717
13718 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
13719 * the <union> alternative is chosen, there must not be any entries
13720 * in the memberTypes [attribute] at any depth which resolve to the
13721 * component corresponding to the <simpleType>.
13722 */
13723 member = type->memberTypes;
13724 while (member != NULL) {
13725 ancestor = member->type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013726 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
13727 if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013728 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013729 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013730 NULL, type, NULL,
13731 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013732 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013733 }
13734 if (IS_NOT_TYPEFIXED(ancestor))
13735 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
13736 if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013737 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013738 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000013739 * type as item type, which in turn has a list ST as member
13740 * type, we will assume this here as well, since this check
13741 * was not yet performed.
13742 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013743 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013744
Daniel Veillard01fa6152004-06-29 17:04:39 +000013745 ancestor = ancestor->baseType;
13746 }
13747 member = member->next;
13748 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013749 }
13750
13751 return (0);
13752}
13753
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013754#if 0 /* Not yet used code for ST schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000013755static int
13756xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
13757 const xmlChar * value,
13758 xmlSchemaTypePtr type,
13759 int fireErrors)
13760{
13761 int ret;
13762 /*
13763 * 3.14.4 Simple Type Definition Validation Rules
13764 * Validation Rule: String Valid
13765 */
13766 /*
13767 * 1 It is schema-valid with respect to that definition as defined
13768 * by Datatype Valid in [XML Schemas: Datatypes].
13769 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013770 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
13771 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000013772 return (ret);
13773 /*
13774 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
13775 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
13776 * the string must be a ·declared entity name·.
13777 */
13778 /*
13779 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
13780 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
13781 * then every whitespace-delimited substring of the string must be a ·declared
13782 * entity name·.
13783 */
13784 /*
13785 * 2.3 otherwise no further condition applies.
13786 */
13787
13788 return (0);
13789}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013790#endif
13791
William M. Brack2f2a6632004-08-20 23:09:47 +000013792
13793static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013794xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
13795{
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000013796 if (vctxt->pctxt == NULL) {
13797 if (vctxt->schema != NULL)
13798 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
13799 else
13800 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013801 if (vctxt->pctxt == NULL) {
13802 xmlSchemaVErr(vctxt, NULL,
13803 XML_SCHEMAV_INTERNAL,
13804 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
13805 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000013806 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013807 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013808 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013809 /* TODO: Pass user data. */
13810 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
13811 }
13812 return (0);
13813}
13814
13815static int
13816xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
13817{
13818 if (ctxt->vctxt == NULL) {
13819 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
13820 if (ctxt->vctxt == NULL) {
13821 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013822 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013823 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
13824 "failed to create a temp. validation context.\n",
13825 NULL, NULL);
13826 return (-1);
13827 }
13828 /* TODO: Pass user data. */
13829 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
13830 }
13831 return (0);
13832}
13833
13834/**
13835 * xmlSchemaCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013836 * @pctxt: the schema parser context
13837 * @vctxt: the temporary schema validation context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013838 * @type: the simple type definition
13839 * @value: the default value
13840 * @node: an optional node (the holder of the value)
13841 *
13842 * Checks the "cos-valid-default" constraints.
13843 *
13844 * Returns 0 if the constraints are satisfied,
13845 * if not, a positive error code and -1 on internal
13846 * errors.
13847 */
13848static int
13849xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
13850 xmlSchemaValidCtxtPtr vctxt,
13851 xmlSchemaTypePtr type,
13852 const xmlChar *value,
13853 xmlNodePtr node)
13854{
13855 int ret = 0;
13856
13857 /*
13858 * cos-valid-default:
13859 * Schema Component Constraint: Element Default Valid (Immediate)
13860 * For a string to be a valid default with respect to a type
13861 * definition the appropriate case among the following must be true:
13862 */
13863 /*
13864 * NOTE: This has to work without a given node (the holder of the
13865 * value), since it should work on the component, i.e. an underlying
13866 * DOM must not be mandatory.
13867 */
13868 if ((pctxt == NULL) || (vctxt == NULL)) {
13869 xmlSchemaPErr(pctxt, node,
13870 XML_SCHEMAP_INTERNAL,
13871 "Internal error: xmlSchemaCheckCOSValidDefault, "
13872 "bad arguments: the parser and/or validation context is "
13873 "missing.\n",
13874 NULL, NULL);
13875 return (-1);
13876 }
13877 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013878 /*
13879 * Complex type.
13880 *
13881 * 2.1 its {content type} must be a simple type definition or mixed.
13882 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013883 /*
13884 * TODO: Adjust this when the content type will be computed
13885 * correctly.
13886 */
13887 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
13888 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
13889 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
13890 xmlSchemaPSimpleTypeErr(pctxt,
13891 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
13892 NULL, NULL, node,
13893 type, NULL, NULL,
13894 "If the type of a constraint value is complex, its content "
13895 "type must be mixed or a simple type",
13896 NULL, NULL);
13897 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
13898 }
13899 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013900 /*
13901 * 2.2.2 If the {content type} is mixed, then the {content type}'s
13902 * particle must be ·emptiable· as defined by Particle Emptiable
13903 * (§3.9.6).
13904 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013905
William M. Brack2f2a6632004-08-20 23:09:47 +000013906 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013907 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000013908 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013909 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000013910 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013911 }
13912 /*
13913 * 1 If the type definition is a simple type definition, then the string
13914 * must be ·valid· with respect to that definition as defined by String
13915 * Valid (§3.14.4).
13916 *
13917 * AND
13918 *
13919 * 2.2.1 If the {content type} is a simple type definition, then the
13920 * string must be ·valid· with respect to that simple type definition
13921 * as defined by String Valid (§3.14.4).
13922 */
13923 vctxt->node = node;
13924 vctxt->cur = NULL;
13925 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
13926 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
13927 if (ret < 0) {
13928 xmlSchemaPErr(pctxt, node,
13929 /* NOTNICE: error code: This function will be used during
13930 * schema construction and xsi:type validation.
13931 */
13932 XML_SCHEMAP_INTERNAL,
13933 "Internal error: xmlSchemaCheckCOSValidDefault, "
13934 "while validating a value constaint value.\n",
13935 NULL, NULL);
13936
13937 }
13938 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000013939}
13940
13941/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013942 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000013943 * @ctxt: the schema parser context
13944 * @type: the complex type definition
13945 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013946 *.(4.6) Constraints on Complex Type Definition Schema Components
13947 * Schema Component Constraint:
13948 * Complex Type Definition Properties Correct (ct-props-correct)
13949 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000013950 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013951 * Returns 0 if the constraints are satisfied, a positive
13952 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000013953 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013954static int
13955xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
13956 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000013957{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013958 /*
13959 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
13960 *
13961 * SPEC (1) "The values of the properties of a complex type definition must
13962 * be as described in the property tableau in The Complex Type Definition
13963 * Schema Component (§3.4.1), modulo the impact of Missing
13964 * Sub-components (§5.3)."
13965 */
13966 if ((type->baseType != NULL) &&
13967 (IS_SIMPLE_TYPE(type->baseType)) &&
13968 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
13969 /*
13970 * SPEC (2) "If the {base type definition} is a simple type definition,
13971 * the {derivation method} must be extension."
13972 */
13973 xmlSchemaPCustomErr(pctxt,
13974 XML_SCHEMAP_SRC_CT_1,
13975 NULL, type, NULL,
13976 "If the base type is a simple type, the derivation method must be "
13977 "'extension'", NULL);
13978 return (XML_SCHEMAP_SRC_CT_1);
13979 }
13980 /*
13981 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
13982 * definition·. That is, it must be possible to reach the ·ur-type
13983 * definition by repeatedly following the {base type definition}."
13984 *
13985 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
13986 *
13987 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
13988 * must not have identical {name}s and {target namespace}s."
13989 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
13990 * must not have {type definition}s which are or are derived from ID."
13991 *
13992 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
13993 */
13994 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000013995}
13996
William M. Brack2f2a6632004-08-20 23:09:47 +000013997/**
13998 * xmlSchemaCheckCOSCTExtends:
13999 * @ctxt: the schema parser context
14000 * @type: the complex type definition
14001 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014002 * (3.4.6) Constraints on Complex Type Definition Schema Components
14003 * Schema Component Constraint:
14004 * Derivation Valid (Extension) (cos-ct-extends)
14005 *
14006 * STATUS:
14007 * missing:
14008 * (1.5)
14009 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014010 *
14011 * Returns 0 if the constraints are satisfied, a positive
14012 * error code if not and -1 if an internal error occured.
14013 */
14014static int
14015xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14016 xmlSchemaTypePtr type)
14017{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014018 xmlSchemaTypePtr base = type->baseType;
14019 /*
14020 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14021 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014022 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014023 /*
14024 * SPEC (1) "If the {base type definition} is a complex type definition,
14025 * then all of the following must be true:"
14026 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014027 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14028 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014029 * SPEC (1.1) "The {final} of the {base type definition} must not
14030 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014031 */
14032 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14033 xmlSchemaPCustomErr(ctxt,
14034 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14035 NULL, type, NULL,
14036 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014037 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014038 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14039 }
14040 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014041 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
14042 * uses}
William M. Brack2f2a6632004-08-20 23:09:47 +000014043 * of the complex type definition itself, that is, for every attribute
14044 * use in the {attribute uses} of the {base type definition}, there
14045 * must be an attribute use in the {attribute uses} of the complex
14046 * type definition itself whose {attribute declaration} has the same
14047 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014048 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014049 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014050 * NOTE (1.2): This will be already satisfied by the way the attribute
14051 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14052 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014053 */
14054
14055 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014056 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14057 * definition must also have one, and the base type definition's
14058 * {attribute wildcard}'s {namespace constraint} must be a subset
14059 * of the complex type definition's {attribute wildcard}'s {namespace
14060 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014061 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014062 * NOTE (1.3) This is already checked in
14063 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014064 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014065 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014066 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014067 if ((type->contentTypeDef != NULL) &&
14068 (type->contentTypeDef == base->contentTypeDef)) {
14069 /*
14070 * SPEC (1.4.1) "The {content type} of the {base type definition}
14071 * and the {content type} of the complex type definition itself
14072 * must be the same simple type definition"
14073 * PASS
14074 */
14075 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14076 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14077 /*
14078 * SPEC (1.4.2) "The {content type} of both the {base type
14079 * definition} and the complex type definition itself must
14080 * be empty."
14081 * PASS
14082 */
14083 } else {
14084 /*
14085 * SPEC (1.4.3) "All of the following must be true:"
14086 */
14087 if (type->subtypes == NULL) {
14088 /*
14089 * SPEC 1.4.3.1 The {content type} of the complex type
14090 * definition itself must specify a particle.
14091 */
14092 xmlSchemaPCustomErr(ctxt,
14093 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14094 NULL, type, NULL,
14095 "The content type must specify a particle", NULL);
14096 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14097 }
14098 /*
14099 * SPEC (1.4.3.2) "One of the following must be true:"
14100 */
14101 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14102 /*
14103 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14104 * definition} must be empty.
14105 * PASS
14106 */
14107 } else {
14108 /*
14109 * SPEC (1.4.3.2.2) "All of the following must be true:"
14110 */
14111 if ((type->contentType != base->contentType) ||
14112 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14113 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14114 /*
14115 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14116 * or both must be element-only."
14117 */
14118 xmlSchemaPCustomErr(ctxt,
14119 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14120 NULL, type, NULL,
14121 "The content type of both, the type and its base "
14122 "type, must either 'mixed' or 'element-only'", NULL);
14123 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14124 }
14125 /*
14126 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14127 * complex type definition must be a ·valid extension·
14128 * of the {base type definition}'s particle, as defined
14129 * in Particle Valid (Extension) (§3.9.6)."
14130 *
14131 * NOTE that we won't check "Particle Valid (Extension)",
14132 * since it is ensured by the derivation process in
14133 * xmlSchemaTypeFixup(). We need to implement this when heading
14134 * for a construction API
14135 */
14136 }
14137 /*
14138 * TODO (1.5)
14139 */
14140 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014141 } else {
14142 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014143 * SPEC (2) "If the {base type definition} is a simple type definition,
14144 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014145 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014146 if (type->contentTypeDef != base) {
14147 /*
14148 * SPEC (2.1) "The {content type} must be the same simple type
14149 * definition."
14150 */
14151 xmlSchemaPCustomErr(ctxt,
14152 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14153 NULL, type, NULL,
14154 "The content type must be the simple base type", NULL);
14155 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14156 }
14157 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14158 /*
14159 * SPEC (2.2) "The {final} of the {base type definition} must not
14160 * contain extension"
14161 * NOTE that this is the same as (1.1).
14162 */
14163 xmlSchemaPCustomErr(ctxt,
14164 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14165 NULL, type, NULL,
14166 "The 'final' of the base type definition "
14167 "contains 'extension'", NULL);
14168 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14169 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014170 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014171 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014172}
14173
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014174/**
14175 * xmlSchemaCheckDerivationOKRestriction:
14176 * @ctxt: the schema parser context
14177 * @type: the complex type definition
14178 *
14179 * (3.4.6) Constraints on Complex Type Definition Schema Components
14180 * Schema Component Constraint:
14181 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14182 *
14183 * STATUS:
14184 * missing:
14185 * (5.4.2), (5.2.2.1)
14186 *
14187 * Returns 0 if the constraints are satisfied, a positive
14188 * error code if not and -1 if an internal error occured.
14189 */
14190static int
14191xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14192 xmlSchemaTypePtr type)
14193{
14194 xmlSchemaTypePtr base;
14195
14196 /*
14197 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14198 * temporarily only.
14199 */
14200 base = type->baseType;
14201 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14202 /*
14203 * SPEC (1) "The {base type definition} must be a complex type
14204 * definition whose {final} does not contain restriction."
14205 */
14206 xmlSchemaPCustomErr(ctxt,
14207 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14208 NULL, type, NULL,
14209 "The 'final' of the base type definition "
14210 "contains 'restriction'", NULL);
14211 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14212 }
14213 /*
14214 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14215 *
14216 * SPEC (5) "One of the following must be true:"
14217 */
14218 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14219 /*
14220 * SPEC (5.1) "The {base type definition} must be the
14221 * ·ur-type definition·."
14222 * PASS
14223 */
14224 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14225 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14226 /*
14227 * SPEC (5.2.1) "The {content type} of the complex type definition
14228 * must be a simple type definition"
14229 *
14230 * SPEC (5.2.2) "One of the following must be true:"
14231 */
14232 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14233 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14234 /*
14235 * SPEC (5.2.2.1) "The {content type} of the {base type
14236 * definition} must be a simple type definition from which
14237 * the {content type} is validly derived given the empty
14238 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14239 * URGENT TODO
14240 */
14241 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14242 (xmlSchemaIsParticleEmptiable(
14243 (xmlSchemaParticlePtr) base->subtypes))) {
14244 /*
14245 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14246 * and have a particle which is ·emptiable· as defined in
14247 * Particle Emptiable (§3.9.6)."
14248 * PASS
14249 */
14250 } else {
14251 xmlSchemaPCustomErr(ctxt,
14252 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14253 NULL, type, NULL,
14254 "The content type of the base type must be either "
14255 "a simple type or 'mixed' and an emptiable particle", NULL);
14256 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14257 }
14258 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14259 /*
14260 * SPEC (5.3.1) "The {content type} of the complex type itself must
14261 * be empty"
14262 */
14263 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14264 /*
14265 * SPEC (5.3.2.1) "The {content type} of the {base type
14266 * definition} must also be empty."
14267 * PASS
14268 */
14269 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14270 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14271 xmlSchemaIsParticleEmptiable(
14272 (xmlSchemaParticlePtr) base->subtypes)) {
14273 /*
14274 * SPEC (5.3.2.2) "The {content type} of the {base type
14275 * definition} must be elementOnly or mixed and have a particle
14276 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14277 * PASS
14278 */
14279 } else {
14280 xmlSchemaPCustomErr(ctxt,
14281 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14282 NULL, type, NULL,
14283 "The content type of the base type must be either "
14284 "empty or 'mixed' (or 'elements-only') and an emptiable "
14285 "particle", NULL);
14286 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14287 }
14288 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14289 ((type->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14290 (base->contentType == XML_SCHEMA_CONTENT_MIXED))) {
14291 /*
14292 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14293 * itself must be element-only"
14294 * SPEC (5.4.1.2) "The {content type} of the complex type definition
14295 * itself and of the {base type definition} must be mixed"
14296 */
14297 /*
14298 * SPEC (5.4.2) "The particle of the complex type definition itself
14299 * must be a ·valid restriction· of the particle of the {content
14300 * type} of the {base type definition} as defined in Particle Valid
14301 * (Restriction) (§3.9.6).
14302 * URGENT TODO
14303 */
14304 } else {
14305 xmlSchemaPCustomErr(ctxt,
14306 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14307 NULL, type, NULL,
14308 "The type is not a valid restriction of its base type", NULL);
14309 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14310 }
14311 return (0);
14312}
14313
14314/**
14315 * xmlSchemaCheckCTPropertiesCorrect:
14316 * @ctxt: the schema parser context
14317 * @type: the complex type definition
14318 *
14319 * (3.4.6) Constraints on Complex Type Definition Schema Components
14320 *
14321 * Returns 0 if the constraints are satisfied, a positive
14322 * error code if not and -1 if an internal error occured.
14323 */
14324static int
14325xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14326 xmlSchemaTypePtr type)
14327{
14328 int ret;
14329 /*
14330 * Complex Type Definition Properties Correct
14331 */
14332 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14333 if (ret != 0)
14334 return (ret);
14335 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14336 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14337 else
14338 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14339 return (ret);
14340}
14341
14342/**
14343 * xmlSchemaCheckSRCCT:
14344 * @ctxt: the schema parser context
14345 * @type: the complex type definition
14346 *
14347 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
14348 * Schema Representation Constraint:
14349 * Complex Type Definition Representation OK (src-ct)
14350 *
14351 * Returns 0 if the constraints are satisfied, a positive
14352 * error code if not and -1 if an internal error occured.
14353 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014354static int
14355xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
14356 xmlSchemaTypePtr type)
14357{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014358 xmlSchemaTypePtr base;
14359 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014360
14361 /*
14362 * TODO: Adjust the error codes here, as I used
14363 * XML_SCHEMAP_SRC_CT_1 only yet.
14364 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014365 base = type->baseType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014366 if (type->contentType != XML_SCHEMA_CONTENT_SIMPLE) {
14367 /*
14368 * 1 If the <complexContent> alternative is chosen, the type definition
14369 * ·resolved· to by the ·actual value· of the base [attribute]
14370 * must be a complex type definition;
14371 */
14372 if (! IS_COMPLEX_TYPE(base)) {
14373 xmlChar *str = NULL;
14374 xmlSchemaPCustomErr(ctxt,
14375 XML_SCHEMAP_SRC_CT_1,
14376 NULL, type, type->node,
14377 "If using <complexContent>, the base type is expected to be "
14378 "a complex type. The base type '%s' is a simple type",
14379 xmlSchemaFormatQName(&str, base->targetNamespace,
14380 base->name));
14381 FREE_AND_NULL(str)
14382 return (XML_SCHEMAP_SRC_CT_1);
14383 }
14384 } else {
14385 /*
14386 * SPEC
14387 * 2 If the <simpleContent> alternative is chosen, all of the
14388 * following must be true:
14389 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14390 * base [attribute] must be one of the following:
14391 */
14392 if (IS_SIMPLE_TYPE(base)) {
14393 if ((type->flags &
14394 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14395 xmlChar *str = NULL;
14396 /*
14397 * 2.1.3 only if the <extension> alternative is also
14398 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014399 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014400 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014401 xmlSchemaPCustomErr(ctxt,
14402 XML_SCHEMAP_SRC_CT_1,
14403 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014404 "If using <simpleContent> and <restriction>, the base "
14405 "type must be a complex type. The base type '%s' is "
14406 "a simple type",
14407 xmlSchemaFormatQName(&str, base->targetNamespace,
14408 base->name));
14409 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014410 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014411 }
14412 } else {
14413 /* Base type is a complex type. */
14414 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14415 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14416 /*
14417 * 2.1.1 a complex type definition whose {content type} is a
14418 * simple type definition;
14419 * PASS
14420 */
14421 if (base->contentTypeDef == NULL) {
14422 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014423 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014424 "Internal error: xmlSchemaCheckSRCCT, "
14425 "'%s', base type has no content type",
14426 type->name);
14427 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014428 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014429 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14430 (type->flags &
14431 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014432
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014433 /*
14434 * 2.1.2 only if the <restriction> alternative is also
14435 * chosen, a complex type definition whose {content type}
14436 * is mixed and a particle emptiable.
14437 */
14438 if (! xmlSchemaIsParticleEmptiable(
14439 (xmlSchemaParticlePtr) base->subtypes)) {
14440 ret = XML_SCHEMAP_SRC_CT_1;
14441 } else if ((type->contentTypeDef == NULL) ||
14442 (type->contentTypeDef->baseType == NULL)) {
14443 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014444 /*
14445 * 2.2 If clause 2.1.2 above is satisfied, then there
14446 * must be a <simpleType> among the [children] of
14447 * <restriction>.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014448 */
14449 /* TODO: Change error code to ..._SRC_CT_2_2. */
14450 xmlSchemaPCustomErr(ctxt,
14451 XML_SCHEMAP_SRC_CT_1,
14452 NULL, type, NULL,
14453 "A <simpleType> is expected among the children "
14454 "of <restriction>, if <simpleContent> is used and "
14455 "the base type '%s' is a complex type",
14456 xmlSchemaFormatQName(&str, base->targetNamespace,
14457 base->name));
14458 FREE_AND_NULL(str)
14459 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014460 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014461 } else {
14462 ret = XML_SCHEMAP_SRC_CT_1;
14463 }
14464 }
14465 if (ret > 0) {
14466 xmlChar *str = NULL;
14467 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
14468 xmlSchemaPCustomErr(ctxt,
14469 XML_SCHEMAP_SRC_CT_1,
14470 NULL, type, NULL,
14471 "If <simpleContent> and <restriction> is used, the "
14472 "base type must be a simple type or a complex type with "
14473 "mixed content and particle emptiable. The base type "
14474 "'%s' is none of those",
14475 xmlSchemaFormatQName(&str, base->targetNamespace,
14476 base->name));
14477 } else {
14478 xmlSchemaPCustomErr(ctxt,
14479 XML_SCHEMAP_SRC_CT_1,
14480 NULL, type, NULL,
14481 "If <simpleContent> and <extension> is used, the "
14482 "base type must be a simple type. The base type '%s' "
14483 "is a complex type",
14484 xmlSchemaFormatQName(&str, base->targetNamespace,
14485 base->name));
14486 }
14487 FREE_AND_NULL(str)
14488 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014489 }
14490 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014491 * SPEC (3) "The corresponding complex type definition component must
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014492 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014493 * Definition Schema Components (§3.4.6);"
14494 * NOTE (3) will be done in xmlSchemaTypeFixup().
14495 */
14496 /*
14497 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014498 * above for {attribute wildcard} is satisfied, the intensional
14499 * intersection must be expressible, as defined in Attribute Wildcard
14500 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014501 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014502 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014503 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014504}
William M. Brack2f2a6632004-08-20 23:09:47 +000014505
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014506#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
14507 xmlSchemaPCustomErrExt(pctxt, \
14508 XML_SCHEMAP_INVALID_FACET_VALUE, \
14509 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
14510 "It is an error for both '%s' and '%s' to be specified on the "\
14511 "same type definition", \
14512 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
14513 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
14514
14515#define FACET_RESTR_ERR(fac1, msg) \
14516 xmlSchemaPCustomErr(pctxt, \
14517 XML_SCHEMAP_INVALID_FACET_VALUE, \
14518 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
14519 msg, NULL);
14520
14521#define FACET_RESTR_FIXED_ERR(fac) \
14522 xmlSchemaPCustomErr(pctxt, \
14523 XML_SCHEMAP_INVALID_FACET_VALUE, \
14524 NULL, (xmlSchemaTypePtr) fac, fac->node, \
14525 "The base type's facet is 'fixed', thus the value must not " \
14526 "differ", NULL);
14527
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014528static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014529xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
14530 xmlSchemaFacetPtr facet1,
14531 xmlSchemaFacetPtr facet2,
14532 int lessGreater,
14533 int orEqual,
14534 int ofBase)
14535{
14536 xmlChar *msg = NULL;
14537
14538 msg = xmlStrdup(BAD_CAST "'");
14539 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
14540 msg = xmlStrcat(msg, BAD_CAST "' has to be");
14541 if (lessGreater == 0)
14542 msg = xmlStrcat(msg, BAD_CAST " equal to");
14543 if (lessGreater == 1)
14544 msg = xmlStrcat(msg, BAD_CAST " greater than");
14545 else
14546 msg = xmlStrcat(msg, BAD_CAST " less than");
14547
14548 if (orEqual)
14549 msg = xmlStrcat(msg, BAD_CAST " or equal to");
14550 msg = xmlStrcat(msg, BAD_CAST " '");
14551 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
14552 if (ofBase)
14553 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
14554 else
14555 msg = xmlStrcat(msg, BAD_CAST "'");
14556
14557 xmlSchemaPCustomErr(pctxt,
14558 XML_SCHEMAP_INVALID_FACET_VALUE,
14559 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
14560 (const char *) msg, NULL);
14561
14562 if (msg != NULL)
14563 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014564}
14565
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014566static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014567xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
14568 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014569{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014570 xmlSchemaTypePtr base = type->baseType;
14571 xmlSchemaFacetLinkPtr link, cur, last = NULL;
14572 xmlSchemaFacetPtr facet, bfacet,
14573 flength = NULL, ftotdig = NULL, ffracdig = NULL,
14574 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
14575 fmininc = NULL, fmaxinc = NULL,
14576 fminexc = NULL, fmaxexc = NULL,
14577 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
14578 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
14579 bfmininc = NULL, bfmaxinc = NULL,
14580 bfminexc = NULL, bfmaxexc = NULL;
14581 int res, err = 0, fixedErr;
14582 /*
14583 * 3 The {facets} of R are the union of S and the {facets}
14584 * of B, eliminating duplicates. To eliminate duplicates,
14585 * when a facet of the same kind occurs in both S and the
14586 * {facets} of B, the one in the {facets} of B is not
14587 * included, with the exception of enumeration and pattern
14588 * facets, for which multiple occurrences with distinct values
14589 * are allowed.
14590 */
14591 if ((type->facetSet == NULL) && (base->facetSet == NULL))
14592 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014593
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014594 last = type->facetSet;
14595 if (last != NULL)
14596 while (last->next != NULL)
14597 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014598
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014599 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
14600 facet = cur->facet;
14601 switch (facet->type) {
14602 case XML_SCHEMA_FACET_LENGTH:
14603 flength = facet; break;
14604 case XML_SCHEMA_FACET_MINLENGTH:
14605 fminlen = facet; break;
14606 case XML_SCHEMA_FACET_MININCLUSIVE:
14607 fmininc = facet; break;
14608 case XML_SCHEMA_FACET_MINEXCLUSIVE:
14609 fminexc = facet; break;
14610 case XML_SCHEMA_FACET_MAXLENGTH:
14611 fmaxlen = facet; break;
14612 case XML_SCHEMA_FACET_MAXINCLUSIVE:
14613 fmaxinc = facet; break;
14614 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
14615 fmaxexc = facet; break;
14616 case XML_SCHEMA_FACET_TOTALDIGITS:
14617 ftotdig = facet; break;
14618 case XML_SCHEMA_FACET_FRACTIONDIGITS:
14619 ffracdig = facet; break;
14620 default:
14621 break;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014622 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014623 }
14624 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
14625 facet = cur->facet;
14626 switch (facet->type) {
14627 case XML_SCHEMA_FACET_LENGTH:
14628 bflength = facet; break;
14629 case XML_SCHEMA_FACET_MINLENGTH:
14630 bfminlen = facet; break;
14631 case XML_SCHEMA_FACET_MININCLUSIVE:
14632 bfmininc = facet; break;
14633 case XML_SCHEMA_FACET_MINEXCLUSIVE:
14634 bfminexc = facet; break;
14635 case XML_SCHEMA_FACET_MAXLENGTH:
14636 bfmaxlen = facet; break;
14637 case XML_SCHEMA_FACET_MAXINCLUSIVE:
14638 bfmaxinc = facet; break;
14639 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
14640 bfmaxexc = facet; break;
14641 case XML_SCHEMA_FACET_TOTALDIGITS:
14642 bftotdig = facet; break;
14643 case XML_SCHEMA_FACET_FRACTIONDIGITS:
14644 bffracdig = facet; break;
14645 default:
14646 break;
14647 }
14648 }
14649 err = 0;
14650 /*
14651 * length and minLength or maxLength (2.2) + (3.2)
14652 */
14653 if (flength && (fminlen || fmaxlen)) {
14654 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
14655 "either of 'minLength' or 'maxLength' to be specified on "
14656 "the same type definition")
14657 }
14658 /*
14659 * Mutual exclusions in the same derivation step.
14660 */
14661 if ((fmaxinc) && (fmaxexc)) {
14662 /*
14663 * SCC "maxInclusive and maxExclusive"
14664 */
14665 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
14666 }
14667 if ((fmininc) && (fminexc)) {
14668 /*
14669 * SCC "minInclusive and minExclusive"
14670 */
14671 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014672 }
14673
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014674 if (flength && bflength) {
14675 /*
14676 * SCC "length valid restriction"
14677 * The values have to be equal.
14678 */
14679 res = xmlSchemaCompareValues(flength->val, bflength->val);
14680 if (res == -2)
14681 goto internal_error;
14682 /*
14683 * TODO: Maby a bug in the spec.
14684 */
14685 if (res != 0)
14686 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
14687 if ((res != 0) && (bflength->fixed)) {
14688 FACET_RESTR_FIXED_ERR(flength)
14689 }
14690
14691 }
14692 if (fminlen && bfminlen) {
14693 /*
14694 * SCC "minLength valid restriction"
14695 * minLength >= BASE minLength
14696 */
14697 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
14698 if (res == -2)
14699 goto internal_error;
14700 if (res == -1)
14701 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
14702 if ((res != 0) && (bfminlen->fixed)) {
14703 FACET_RESTR_FIXED_ERR(fminlen)
14704 }
14705 }
14706 if (fmaxlen && bfmaxlen) {
14707 /*
14708 * SCC "maxLength valid restriction"
14709 * maxLength <= BASE minLength
14710 */
14711 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
14712 if (res == -2)
14713 goto internal_error;
14714 if (res == 1)
14715 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
14716 if ((res != 0) && (bfmaxlen->fixed)) {
14717 FACET_RESTR_FIXED_ERR(fmaxlen)
14718 }
14719 }
14720 /*
14721 * SCC "length and minLength or maxLength"
14722 */
14723 if (! flength)
14724 flength = bflength;
14725 if (flength) {
14726 if (! fminlen)
14727 flength = bflength;
14728 if (fminlen) {
14729 /* (1.1) length >= minLength */
14730 res = xmlSchemaCompareValues(flength->val, fminlen->val);
14731 if (res == -2)
14732 goto internal_error;
14733 if (res == -1)
14734 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
14735 }
14736 if (! fmaxlen)
14737 fmaxlen = bfmaxlen;
14738 if (fmaxlen) {
14739 /* (2.1) length <= maxLength */
14740 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
14741 if (res == -2)
14742 goto internal_error;
14743 if (res == 1)
14744 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
14745 }
14746 }
14747 if (fmaxinc) {
14748 /*
14749 * "maxInclusive"
14750 */
14751 if (fmininc) {
14752 /* SCC "maxInclusive >= minInclusive" */
14753 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
14754 if (res == -2)
14755 goto internal_error;
14756 if (res == -1) {
14757 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
14758 }
14759 }
14760 /*
14761 * SCC "maxInclusive valid restriction"
14762 */
14763 if (bfmaxinc) {
14764 /* maxInclusive <= BASE maxInclusive */
14765 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
14766 if (res == -2)
14767 goto internal_error;
14768 if (res == 1)
14769 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
14770 if ((res != 0) && (bfmaxinc->fixed)) {
14771 FACET_RESTR_FIXED_ERR(fmaxinc)
14772 }
14773 }
14774 if (bfmaxexc) {
14775 /* maxInclusive < BASE maxExclusive */
14776 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
14777 if (res == -2)
14778 goto internal_error;
14779 if (res != -1) {
14780 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
14781 }
14782 }
14783 if (bfmininc) {
14784 /* maxInclusive >= BASE minInclusive */
14785 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
14786 if (res == -2)
14787 goto internal_error;
14788 if (res == -1) {
14789 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
14790 }
14791 }
14792 if (bfminexc) {
14793 /* maxInclusive > BASE minExclusive */
14794 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
14795 if (res == -2)
14796 goto internal_error;
14797 if (res != 1) {
14798 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
14799 }
14800 }
14801 }
14802 if (fmaxexc) {
14803 /*
14804 * "maxExclusive >= minExclusive"
14805 */
14806 if (fminexc) {
14807 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
14808 if (res == -2)
14809 goto internal_error;
14810 if (res == -1) {
14811 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
14812 }
14813 }
14814 /*
14815 * "maxExclusive valid restriction"
14816 */
14817 if (bfmaxexc) {
14818 /* maxExclusive <= BASE maxExclusive */
14819 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
14820 if (res == -2)
14821 goto internal_error;
14822 if (res == 1) {
14823 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
14824 }
14825 if ((res != 0) && (bfmaxexc->fixed)) {
14826 FACET_RESTR_FIXED_ERR(fmaxexc)
14827 }
14828 }
14829 if (bfmaxinc) {
14830 /* maxExclusive <= BASE maxInclusive */
14831 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
14832 if (res == -2)
14833 goto internal_error;
14834 if (res == 1) {
14835 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
14836 }
14837 }
14838 if (bfmininc) {
14839 /* maxExclusive > BASE minInclusive */
14840 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
14841 if (res == -2)
14842 goto internal_error;
14843 if (res != 1) {
14844 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
14845 }
14846 }
14847 if (bfminexc) {
14848 /* maxExclusive > BASE minExclusive */
14849 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
14850 if (res == -2)
14851 goto internal_error;
14852 if (res != 1) {
14853 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
14854 }
14855 }
14856 }
14857 if (fminexc) {
14858 /*
14859 * "minExclusive < maxInclusive"
14860 */
14861 if (fmaxinc) {
14862 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
14863 if (res == -2)
14864 goto internal_error;
14865 if (res != -1) {
14866 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
14867 }
14868 }
14869 /*
14870 * "minExclusive valid restriction"
14871 */
14872 if (bfminexc) {
14873 /* minExclusive >= BASE minExclusive */
14874 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
14875 if (res == -2)
14876 goto internal_error;
14877 if (res == -1) {
14878 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
14879 }
14880 if ((res != 0) && (bfminexc->fixed)) {
14881 FACET_RESTR_FIXED_ERR(fminexc)
14882 }
14883 }
14884 if (bfmaxinc) {
14885 /* minExclusive <= BASE maxInclusive */
14886 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
14887 if (res == -2)
14888 goto internal_error;
14889 if (res == 1) {
14890 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
14891 }
14892 }
14893 if (bfmininc) {
14894 /* minExclusive >= BASE minInclusive */
14895 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
14896 if (res == -2)
14897 goto internal_error;
14898 if (res == -1) {
14899 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
14900 }
14901 }
14902 if (bfmaxexc) {
14903 /* minExclusive < BASE maxExclusive */
14904 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
14905 if (res == -2)
14906 goto internal_error;
14907 if (res != -1) {
14908 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
14909 }
14910 }
14911 }
14912 if (fmininc) {
14913 /*
14914 * "minInclusive < maxExclusive"
14915 */
14916 if (fmaxexc) {
14917 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
14918 if (res == -2)
14919 goto internal_error;
14920 if (res != -1) {
14921 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
14922 }
14923 }
14924 /*
14925 * "minExclusive valid restriction"
14926 */
14927 if (bfmininc) {
14928 /* minInclusive >= BASE minInclusive */
14929 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
14930 if (res == -2)
14931 goto internal_error;
14932 if (res == -1) {
14933 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
14934 }
14935 if ((res != 0) && (bfmininc->fixed)) {
14936 FACET_RESTR_FIXED_ERR(fmininc)
14937 }
14938 }
14939 if (bfmaxinc) {
14940 /* minInclusive <= BASE maxInclusive */
14941 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
14942 if (res == -2)
14943 goto internal_error;
14944 if (res == -1) {
14945 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
14946 }
14947 }
14948 if (bfminexc) {
14949 /* minInclusive > BASE minExclusive */
14950 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
14951 if (res == -2)
14952 goto internal_error;
14953 if (res != 1)
14954 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
14955 }
14956 if (bfmaxexc) {
14957 /* minInclusive < BASE maxExclusive */
14958 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
14959 if (res == -2)
14960 goto internal_error;
14961 if (res != -1)
14962 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
14963 }
14964 }
14965 if (ftotdig && bftotdig) {
14966 /*
14967 * SCC " totalDigits valid restriction"
14968 * totalDigits <= BASE totalDigits
14969 */
14970 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
14971 if (res == -2)
14972 goto internal_error;
14973 if (res == 1)
14974 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
14975 -1, 1, 1);
14976 if ((res != 0) && (bftotdig->fixed)) {
14977 FACET_RESTR_FIXED_ERR(ftotdig)
14978 }
14979 }
14980 if (ffracdig && bffracdig) {
14981 /*
14982 * SCC "fractionDigits valid restriction"
14983 * fractionDigits <= BASE fractionDigits
14984 */
14985 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
14986 if (res == -2)
14987 goto internal_error;
14988 if (res == 1)
14989 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
14990 -1, 1, 1);
14991 if ((res != 0) && (bffracdig->fixed)) {
14992 FACET_RESTR_FIXED_ERR(ffracdig)
14993 }
14994 }
14995 /*
14996 * SCC "fractionDigits less than or equal to totalDigits"
14997 */
14998 if (! ftotdig)
14999 ftotdig = bftotdig;
15000 if (! ffracdig)
15001 ffracdig = bffracdig;
15002 if (ftotdig && ffracdig) {
15003 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15004 if (res == -2)
15005 goto internal_error;
15006 if (res == 1)
15007 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15008 -1, 1, 0);
15009 }
15010 /*
15011 * *Enumerations* won' be added here, since only the first set
15012 * of enumerations in the ancestor-or-self axis is used
15013 * for validation, plus we need to use the base type of those
15014 * enumerations for whitespace.
15015 *
15016 * *Patterns*: won't be add here, since they are ORed at
15017 * type level and ANDed at ancestor level. This will
15018 * happed during validation by walking the base axis
15019 * of the type.
15020 */
15021 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15022 bfacet = cur->facet;
15023 /*
15024 * Special handling of enumerations and patterns.
15025 * TODO: hmm, they should not appear in the set, so remove this.
15026 */
15027 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
15028 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
15029 continue;
15030 /*
15031 * Search for a duplicate facet in the current type.
15032 */
15033 link = type->facetSet;
15034 err = 0;
15035 fixedErr = 0;
15036 while (link != NULL) {
15037 facet = link->facet;
15038 if (facet->type == bfacet->type) {
15039 switch (facet->type) {
15040 case XML_SCHEMA_FACET_WHITESPACE:
15041 /*
15042 * The whitespace must be stronger.
15043 */
15044 if (facet->whitespace < bfacet->whitespace) {
15045 FACET_RESTR_ERR(flength,
15046 "The 'whitespace' value has to be equal to "
15047 "or stronger than the 'whitespace' value of "
15048 "the base type")
15049 }
15050 if ((bfacet->fixed) &&
15051 (facet->whitespace != bfacet->whitespace)) {
15052 FACET_RESTR_FIXED_ERR(facet)
15053 }
15054 break;
15055 default:
15056 break;
15057 }
15058 /* Duplicate found. */
15059 break;
15060 }
15061 link = link->next;
15062 }
15063 /*
15064 * If no duplicate was found: add the base types's facet
15065 * to the set.
15066 */
15067 if (link == NULL) {
15068 link = (xmlSchemaFacetLinkPtr)
15069 xmlMalloc(sizeof(xmlSchemaFacetLink));
15070 if (link == NULL) {
15071 xmlSchemaPErrMemory(pctxt,
15072 "deriving facets, creating a facet link", NULL);
15073 return (-1);
15074 }
15075 link->facet = cur->facet;
15076 link->next = NULL;
15077 if (last == NULL)
15078 type->facetSet = link;
15079 else
15080 last->next = link;
15081 last = link;
15082 }
15083
15084 }
15085
15086 return (0);
15087internal_error:
15088 xmlSchemaPCustomErr(pctxt,
15089 XML_SCHEMAP_INVALID_FACET_VALUE,
15090 NULL, type, NULL,
15091 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15092 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015093}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015094
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015095/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015096 * xmlSchemaTypeFixup:
15097 * @typeDecl: the schema type definition
15098 * @ctxt: the schema parser context
15099 *
15100 * Fixes the content model of the type.
15101 */
15102static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015103xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015104 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000015105{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015106 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000015107 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015108 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
15109 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015110 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015111 if (! IS_NOT_TYPEFIXED(type))
15112 return;
15113 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000015114 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015115 name = type->name;
15116
15117 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
15118 xmlSchemaTypePtr baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015119
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015120 /*
15121 * Resolve & type-fix the base type.
15122 */
15123 baseType = type->baseType;
15124 if (baseType == NULL) {
15125 baseType = xmlSchemaGetType(ctxt->schema,
15126 type->base, type->baseNs);
15127 if (baseType == NULL) {
15128 xmlSchemaPResCompAttrErr(ctxt,
15129 XML_SCHEMAP_SRC_RESOLVE,
15130 NULL, type, type->node,
15131 "base", type->base, type->baseNs,
15132 XML_SCHEMA_TYPE_SIMPLE, NULL);
15133 return;
15134 }
15135 type->baseType = baseType;
15136 }
15137 if (IS_NOT_TYPEFIXED(baseType))
15138 xmlSchemaTypeFixup(baseType, ctxt, NULL);
15139 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
15140 /*
15141 * Skip fixup if the base type is invalid.
15142 * TODO: Generate a warning!
15143 */
15144 return;
15145 }
15146 /*
15147 * This basically checks if the base type can be derived.
15148 */
15149 if (xmlSchemaCheckSRCCT(ctxt, type) != 0) {
15150 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
15151 return;
15152 }
15153 /*
15154 * Fixup the content type.
15155 */
15156 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
15157 /*
15158 * Corresponds to <complexType><simpleContent>...
15159 */
15160 if ((IS_COMPLEX_TYPE(baseType)) &&
15161 (baseType->contentTypeDef != NULL) &&
15162 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
15163 /*
15164 * SPEC (1) If <restriction> + base type is <complexType>,
15165 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000015166 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015167 * NOTE (1.1) is handled during parsing of <restriction>.
15168 *
15169 * (1.2) "...otherwise (<restriction> has no <simpleType> among
15170 * its [children]), the simple type definition which is the
15171 * {content type} of the ... base type."
Daniel Veillard01fa6152004-06-29 17:04:39 +000015172 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015173 if (type->contentTypeDef->baseType == NULL) {
15174 /*
15175 * <simpleContent><restriction> has *no* <simpleType>
15176 * child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015177 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015178 type->contentTypeDef->baseType =
15179 baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015180 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015181 } else if ((IS_COMPLEX_TYPE(baseType)) &&
15182 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
15183 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
15184 /*
15185 * SPEC (2) If <restriction> + base is a mixed <complexType> with
15186 * an emptiable particle, then a simple type definition which
15187 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015188 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015189 if ((type->contentTypeDef == NULL) ||
15190 (type->contentTypeDef->baseType == NULL)) {
15191 /*
15192 * TODO: Check if this ever happens.
15193 */
15194 xmlSchemaPCustomErr(ctxt,
15195 XML_SCHEMAP_INTERNAL,
15196 NULL, type, NULL,
15197 "Internal error: xmlSchemaTypeFixup, "
15198 "complex type '%s': the <simpleContent><restriction> "
15199 "is missing a <simpleType> child, but was not catched "
15200 "by xmlSchemaCheckSRCCT()", type->name);
15201 }
15202 } else if ((IS_COMPLEX_TYPE(baseType)) &&
15203 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
15204 /*
15205 * SPEC (3) If <extension> + base is <complexType> with
15206 * <simpleType> content, "...then the {content type} of that
15207 * complex type definition"
15208 */
15209 if (baseType->contentTypeDef == NULL) {
15210 /*
15211 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
15212 * should have catched this already.
15213 */
15214 xmlSchemaPCustomErr(ctxt,
15215 XML_SCHEMAP_INTERNAL,
15216 NULL, type, NULL,
15217 "Internal error: xmlSchemaTypeFixup, "
15218 "complex type '%s': the <extension>ed base type is "
15219 "a complex type with no simple content type",
15220 type->name);
15221 }
15222 type->contentTypeDef = baseType->contentTypeDef;
15223 } else if ((IS_SIMPLE_TYPE(baseType)) &&
15224 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
15225 /*
15226 * SPEC (4) <extension> + base is <simpleType>
15227 * "... then that simple type definition"
15228 */
15229 type->contentTypeDef = baseType;
15230 } else {
15231 /*
15232 * TODO: Check if this ever happens.
15233 */
15234 xmlSchemaPCustomErr(ctxt,
15235 XML_SCHEMAP_INTERNAL,
15236 NULL, type, NULL,
15237 "Internal error: xmlSchemaTypeFixup, "
15238 "complex type '%s' with <simpleContent>: unhandled "
15239 "derivation case", type->name);
15240 }
15241 } else {
15242 int dummySequence = 0;
15243 xmlSchemaParticlePtr particle =
15244 (xmlSchemaParticlePtr) type->subtypes;
15245 /*
15246 * Corresponds to <complexType><complexContent>...
15247 *
15248 * NOTE that the effective mixed was already set during parsing of
15249 * <complexType> and <complexContent>; its flag value is
15250 * XML_SCHEMAS_TYPE_MIXED.
15251 *
15252 * Compute the "effective content":
15253 * (2.1.1) + (2.1.2) + (2.1.3)
15254 */
15255 if ((particle == NULL) ||
15256 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
15257 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
15258 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
15259 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
15260 (particle->minOccurs == 0))) &&
15261 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
15262 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
15263 /*
15264 * SPEC (2.1.4) "If the ·effective mixed· is true, then
15265 * a particle whose properties are as follows:..."
15266 *
15267 * Empty sequence model group with
15268 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
15269 * NOTE that we sill assign it the <complexType> node to
15270 * somehow anchor it in the doc.
15271 */
15272 if ((particle == NULL) ||
15273 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015274 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015275 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015276 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015277 particle = xmlSchemaAddParticle(ctxt, ctxt->schema,
15278 type->node, 1, 1);
15279 if (particle == NULL)
15280 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015281 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015282 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015283 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015284 particle->children = (xmlSchemaTreeItemPtr)
15285 xmlSchemaAddModelGroup(ctxt, ctxt->schema,
15286 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
15287 if (particle->children == NULL)
15288 return;
15289
15290 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015291 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015292 dummySequence = 1;
15293 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
15294 } else {
15295 /*
15296 * SPEC (2.1.5) "otherwise empty"
15297 */
15298 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
15299 }
15300 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015301 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015302 * SPEC (2.2) "otherwise the particle corresponding to the
15303 * <all>, <choice>, <group> or <sequence> among the
15304 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000015305 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015306 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
15307 }
15308 /*
15309 * Compute the "content type".
15310 */
15311 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015312 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015313 * SPEC (3.1) "If <restriction>..."
15314 * (3.1.1) + (3.1.2) */
15315 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
15316 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
15317 type->contentType = XML_SCHEMA_CONTENT_MIXED;
15318 }
15319 } else {
15320 /*
15321 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015322 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015323 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
15324 /*
15325 * SPEC (3.2.1)
15326 */
15327 type->contentType = baseType->contentType;
15328 type->subtypes = baseType->subtypes;
15329 /*
15330 * NOTE that the effective mixed is ignored here.
15331 */
15332 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
15333 /*
15334 * SPEC (3.2.2)
15335 */
15336 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
15337 type->contentType = XML_SCHEMA_CONTENT_MIXED;
15338 } else {
15339 /*
15340 * SPEC (3.2.3)
15341 */
15342 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
15343 type->contentType = XML_SCHEMA_CONTENT_MIXED;
15344 /*
15345 * "A model group whose {compositor} is sequence and whose
15346 * {particles} are..."
15347 */
15348 if (! dummySequence) {
15349 xmlSchemaTreeItemPtr effectiveContent =
15350 (xmlSchemaTreeItemPtr) type->subtypes;
15351 /*
15352 * Create the particle.
15353 */
15354 particle = xmlSchemaAddParticle(ctxt, ctxt->schema,
15355 type->node, 1, 1);
15356 if (particle == NULL)
15357 return;
15358 /*
15359 * Create the "sequence" model group.
15360 */
15361 particle->children = (xmlSchemaTreeItemPtr)
15362 xmlSchemaAddModelGroup(ctxt, ctxt->schema,
15363 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
15364 if (particle->children == NULL)
15365 return;
15366 type->subtypes = (xmlSchemaTypePtr) particle;
15367 /*
15368 * SPEC "the particle of the {content type} of
15369 * the ... base ..."
15370 * Create a duplicate of the base type's particle
15371 * and assign its "term" to it.
15372 */
15373 particle->children->children =
15374 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(ctxt,
15375 ctxt->schema, type->node,
15376 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
15377 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
15378 if (particle->children->children == NULL)
15379 return;
15380 particle = (xmlSchemaParticlePtr)
15381 particle->children->children;
15382 particle->children =
15383 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
15384 /*
15385 * SPEC "followed by the ·effective content·."
15386 */
15387 particle->next = effectiveContent;
15388 } else {
15389 /*
15390 * This is the case when there is already an empty
15391 * <sequence> with minOccurs==maxOccurs==1.
15392 * Just add the base types's content type.
15393 * NOTE that, although we miss to add an intermediate
15394 * <sequence>, this should produce no difference to
15395 * neither the regex compilation of the content model,
15396 * nor to the complex type contraints.
15397 */
15398 particle->children->children =
15399 (xmlSchemaTreeItemPtr) baseType->subtypes;
15400 }
15401 }
15402 }
15403 }
15404 /*
15405 * Apply the complex type component constraints; this will not
15406 * check attributes, since this is done in
15407 * xmlSchemaBuildAttributeValidation().
15408 */
15409 if (xmlSchemaCheckCTComponent(ctxt, type) != 0)
15410 return;
15411 /*
15412 * Inherit & check constraints for attributes.
15413 */
15414 xmlSchemaBuildAttributeValidation(ctxt, type);
15415 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
15416 /*
15417 * Simple Type Definition Schema Component
15418 */
15419 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
15420 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15421 /*
15422 * Corresponds to <simpleType><list>...
15423 * Resolve the itemType.
15424 */
15425 if ((type->subtypes == NULL) && (type->ref != NULL)) {
15426 type->subtypes = xmlSchemaGetType(ctxt->schema,
15427 type->ref, type->refNs);
15428 if ((type->subtypes == NULL) ||
15429 (! IS_SIMPLE_TYPE(type->subtypes))) {
15430 type->subtypes = NULL;
15431 xmlSchemaPResCompAttrErr(ctxt,
15432 XML_SCHEMAP_SRC_RESOLVE,
15433 NULL, type, type->node,
15434 "itemType", type->ref, type->refNs,
15435 XML_SCHEMA_TYPE_SIMPLE, NULL);
15436 }
15437 }
15438 if (type->subtypes == NULL) {
15439 /*
15440 * This one is really needed, so get out.
15441 */
15442 return;
15443 }
15444 if (IS_NOT_TYPEFIXED(type->subtypes))
15445 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
15446 /* Base type:
15447 * 2 If the <list> or <union> alternative is chosen,
15448 * then the ·simple ur-type definition·.
15449 */
15450 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
15451 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
15452 /*
15453 * Corresponds to <simpleType><union>...
15454 * Resolve the member types.
15455 */
15456 xmlSchemaResolveUnionMemberTypes(ctxt, type);
15457 if (type->memberTypes == NULL) {
15458 /*
15459 * This one is really needed, so get out.
15460 */
15461 return;
15462 }
15463 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
15464 } else {
15465 xmlSchemaTypePtr baseType;
15466 /*
15467 * Corresponds to <simpleType><restriction>...
15468 *
15469 * Resolve the base type.
15470 */
15471 if ((type->baseType == NULL) && (type->base != NULL)) {
15472 baseType = xmlSchemaGetType(ctxt->schema,
15473 type->base, type->baseNs);
15474
15475 if (baseType == NULL) {
15476 xmlSchemaPResCompAttrErr(ctxt,
15477 XML_SCHEMAP_SRC_RESOLVE,
15478 NULL, type, type->node,
15479 "base", type->base, type->baseNs,
15480 XML_SCHEMA_TYPE_SIMPLE, NULL);
15481 }
15482 type->baseType = baseType;
15483 } else
15484 baseType = type->baseType;
15485
15486 if (baseType == NULL)
15487 return;
15488
15489 if (IS_NOT_TYPEFIXED(baseType))
15490 xmlSchemaTypeFixup(baseType, ctxt, NULL);
15491 /*
15492 * Variety
15493 * If the <restriction> alternative is chosen, then the
15494 * {variety} of the {base type definition}.
15495 */
15496 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
15497 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
15498 else if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15499 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
15500 /*
15501 * Inherit the itemType.
15502 */
15503 type->subtypes = baseType->subtypes;
15504 } else if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
15505 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
15506 /*
15507 * NOTE that we won't assign the memberTypes of the base,
15508 * since this will make trouble when freeing them; we will
15509 * use a lookup function to access them instead.
15510 */
15511 }
15512
15513 /*
15514 * Some optimization for validation:
15515 * If there are no facets beside the "whitespace" facet,
15516 * then a value needs not to checked against against a
15517 * facet, thus no computed value is needed.
15518 */
15519#if 0
15520 if (baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
15521 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15522 else {
15523 for (cur = type->facetSet; cur != NULL;
15524 cur = cur->next) {
15525 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15526 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15527 break;
15528 }
15529 }
15530 }
15531#endif
15532 }
15533 /*
15534 * Check constraints.
15535 *
15536 * TODO: Split this somehow, we need to know first if we can derive
15537 * from the base type at all!
15538 */
15539 if (type->baseType != NULL) {
15540 /*
15541 * Schema Component Constraint: Simple Type Restriction
15542 * (Facets)
15543 * NOTE: Satisfaction of 1 and 2 arise from the fixup
15544 * applied beforehand.
15545 */
15546 xmlSchemaCheckSRCSimpleType(ctxt, type);
15547 xmlSchemaCheckFacetValues(type, ctxt);
15548 xmlSchemaDeriveAndValidateFacets(ctxt, type);
15549 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015550 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015551
Daniel Veillard8651f532002-04-17 09:06:27 +000015552#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015553 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015554 xmlGenericError(xmlGenericErrorContext,
15555 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015556 type->node->doc->URL,
15557 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000015558 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015559 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000015560 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015561 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
15562 switch (type->contentType) {
15563 case XML_SCHEMA_CONTENT_SIMPLE:
15564 xmlGenericError(xmlGenericErrorContext, "simple\n");
15565 break;
15566 case XML_SCHEMA_CONTENT_ELEMENTS:
15567 xmlGenericError(xmlGenericErrorContext, "elements\n");
15568 break;
15569 case XML_SCHEMA_CONTENT_UNKNOWN:
15570 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
15571 break;
15572 case XML_SCHEMA_CONTENT_EMPTY:
15573 xmlGenericError(xmlGenericErrorContext, "empty\n");
15574 break;
15575 case XML_SCHEMA_CONTENT_MIXED:
15576 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
15577 type->subtypes))
15578 xmlGenericError(xmlGenericErrorContext,
15579 "mixed as emptiable particle\n");
15580 else
15581 xmlGenericError(xmlGenericErrorContext, "mixed\n");
15582 break;
15583 /* Removed, since not used. */
15584 /*
15585 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
15586 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
15587 break;
15588 */
15589 case XML_SCHEMA_CONTENT_BASIC:
15590 xmlGenericError(xmlGenericErrorContext, "basic\n");
15591 break;
15592 default:
15593 xmlGenericError(xmlGenericErrorContext,
15594 "not registered !!!\n");
15595 break;
15596 }
Daniel Veillard8651f532002-04-17 09:06:27 +000015597 }
15598#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015599}
15600
15601/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000015602 * xmlSchemaCheckFacet:
15603 * @facet: the facet
15604 * @typeDecl: the schema type definition
15605 * @ctxt: the schema parser context or NULL
15606 * @name: name of the type
15607 *
15608 * Checks the default values types, especially for facets
15609 *
15610 * Returns 0 if okay or -1 in cae of error
15611 */
15612int
15613xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015614 xmlSchemaTypePtr typeDecl,
15615 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000015616{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000015617 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015618 int ret = 0, reuseValCtxt = 0;
15619
Daniel Veillardce682bc2004-11-05 17:22:25 +000015620 if ((facet == NULL) || (typeDecl == NULL))
15621 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015622 /*
15623 * TODO: will the parser context be given if used from
15624 * the relaxNG module?
15625 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000015626
15627 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015628 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000015629 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000015630 }
15631 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015632 case XML_SCHEMA_FACET_MININCLUSIVE:
15633 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15634 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015635 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15636 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015637 /*
15638 * Okay we need to validate the value
15639 * at that point.
15640 */
15641 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015642 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015643
15644 /* 4.3.5.5 Constraints on enumeration Schema Components
15645 * Schema Component Constraint: enumeration valid restriction
15646 * It is an ·error· if any member of {value} is not in the
15647 * ·value space· of {base type definition}.
15648 *
15649 * minInclusive, maxInclusive, minExclusive, maxExclusive:
15650 * The value ·must· be in the
15651 * ·value space· of the ·base type·.
15652 */
15653 /*
15654 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015655 * on the facet. In this implementation of XML Schemata the
15656 * type holding a facet, won't be a built-in type.
15657 * Thus to ensure that other API
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015658 * calls (relaxng) do work, if the given type is a built-in
15659 * type, we will assume that the given built-in type *is
15660 * already* the base type.
15661 */
15662 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
15663 base = typeDecl->baseType;
15664 if (base == NULL) {
15665 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015666 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015667 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015668 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015669 typeDecl->name, NULL);
15670 return (-1);
15671 }
15672 } else
15673 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015674 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015675 * This avoids perseverative creation of the
15676 * validation context if a parser context is
15677 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015678 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015679 if (ctxt != NULL) {
15680 reuseValCtxt = 1;
15681 if (ctxt->vctxt == NULL) {
15682 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
15683 return (-1);
15684 }
15685 vctxt = ctxt->vctxt;
15686 } else {
15687 vctxt = xmlSchemaNewValidCtxt(NULL);
15688 if (vctxt == NULL) {
15689 xmlSchemaPErr(ctxt, typeDecl->node,
15690 XML_SCHEMAP_INTERNAL,
15691 "Internal error: xmlSchemaCheckFacet, "
15692 "creating a new validation context.\n",
15693 NULL, NULL);
15694 return (-1);
15695 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015696 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015697
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015698 vctxt->node = facet->node;
15699 vctxt->cur = NULL;
15700 /*
15701 * NOTE: This call does not check the content nodes,
15702 * since they are not available:
15703 * facet->node is just the node holding the facet
15704 * definition, *not* the attribute holding the *value*
15705 * of the facet.
15706 */
15707 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015708 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015709 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015710 /* error code */
15711 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015712 xmlChar *str = NULL;
15713
15714 xmlSchemaPCustomErrExt(ctxt,
15715 XML_SCHEMAP_INVALID_FACET_VALUE,
15716 NULL, (xmlSchemaTypePtr) facet, facet->node,
15717 "The value '%s' of the facet does not validate "
15718 "against the base type '%s'",
15719 facet->value,
15720 xmlSchemaFormatQName(&str,
15721 base->targetNamespace, base->name), NULL);
15722 FREE_AND_NULL(str)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015723 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015724 /* xmlSchemaFacetTypeToString(facet->type), */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015725 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015726 } else if (ret < 0) {
15727 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015728 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015729 NULL, NULL, NULL,
15730 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015731 "failed to validate the value '%s' name of the "
15732 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015733 facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015734 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardf4b05d02004-07-05 13:10:37 +000015735 base->name, NULL, NULL);
15736 ret = -1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015737 } else {
15738 if (vctxt->value != NULL) {
15739 facet->val = vctxt->value;
15740 vctxt->value = NULL;
15741 } else {
15742 xmlChar *str;
15743 /*
15744 * Ensure computed values even for type string.
15745 * TODO OPTIMIZE MEMORY: The value will be hold twice,
15746 * by the facet->value and by the computed value.
15747 */
15748 str = xmlStrdup(facet->value);
15749 if (xmlSchemaPostCreateVal(vctxt, typeDecl,
15750 BAD_CAST str, &(facet->val)) == -1) {
15751 FREE_AND_NULL(str)
15752 xmlSchemaPErr(ctxt, typeDecl->node,
15753 XML_SCHEMAP_INTERNAL,
15754 "Internal error: xmlSchemaCheckFacet, "
15755 "post-creating a computed value.\n",
15756 NULL, NULL);
15757 /* Note that we don't return a failure yet.*/
15758 }
15759 }
15760 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015761 if (reuseValCtxt == 0)
15762 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015763 break;
15764 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015765 case XML_SCHEMA_FACET_PATTERN:
15766 facet->regexp = xmlRegexpCompile(facet->value);
15767 if (facet->regexp == NULL) {
15768 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015769 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015770 "Type definition '%s': The value '%s' of the "
15771 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015772 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015773 ret = -1;
15774 }
15775 break;
15776 case XML_SCHEMA_FACET_TOTALDIGITS:
15777 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15778 case XML_SCHEMA_FACET_LENGTH:
15779 case XML_SCHEMA_FACET_MAXLENGTH:
15780 case XML_SCHEMA_FACET_MINLENGTH:{
15781 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000015782
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015783 tmp =
15784 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
15785 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000015786 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015787 if (tmp != 0) {
15788 /* error code */
15789 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015790 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015791 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015792 NULL, (xmlSchemaTypePtr) facet, facet->node,
15793 "The value '%s' of the facet is not a valid "
15794 "nonNegativeInteger", facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015795 }
15796 ret = -1;
15797 }
15798 break;
15799 }
15800 case XML_SCHEMA_FACET_WHITESPACE:{
15801 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
15802 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
15803 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
15804 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
15805 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
15806 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
15807 } else {
15808 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015809 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
15810 xmlSchemaPCustomErr(ctxt,
15811 XML_SCHEMAP_INVALID_FACET_VALUE,
15812 NULL, (xmlSchemaTypePtr) facet, facet->node,
15813 "The value '%s' of the facet is not a valid",
15814 facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015815 }
15816 ret = -1;
15817 }
15818 }
15819 default:
15820 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000015821 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015822 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000015823}
15824
15825/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015826 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000015827 * @typeDecl: the schema type definition
15828 * @ctxt: the schema parser context
15829 *
15830 * Checks the default values types, especially for facets
15831 */
15832static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015833xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
15834 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000015835{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015836 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015837 /*
15838 * NOTE: It is intended to use the facets list, instead
15839 * of facetSet.
15840 */
15841 if (typeDecl->facets != NULL) {
15842 xmlSchemaFacetPtr facet = typeDecl->facets;
15843
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015844 /*
15845 * Temporarily assign the "schema" to the validation context
15846 * of the parser context. This is needed for NOTATION validation.
15847 */
15848 if (ctxt->vctxt == NULL) {
15849 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
15850 return;
15851 }
15852 ctxt->vctxt->schema = ctxt->schema;
15853
Daniel Veillard01fa6152004-06-29 17:04:39 +000015854 while (facet != NULL) {
15855 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
15856 facet = facet->next;
15857 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015858
15859 ctxt->vctxt->schema = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015860 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015861}
15862
15863/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015864 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015865 * @ctxtMGroup: the searched model group
15866 * @selfMGroup: the second searched model group
15867 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015868 *
15869 * This one is intended to be used by
15870 * xmlSchemaCheckGroupDefCircular only.
15871 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015872 * Returns the particle with the circular model group definition reference,
15873 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015874 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015875static xmlSchemaTreeItemPtr
15876xmlSchemaGetCircModelGrDefRef(xmlSchemaTreeItemPtr ctxtMGroup,
15877 xmlSchemaTreeItemPtr selfMGroup,
15878 xmlSchemaTreeItemPtr particle)
15879{
15880 xmlSchemaTreeItemPtr circ = NULL;
15881 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015882
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015883 while (particle != NULL) {
15884 term = particle->children;
15885 if ((term != NULL) &&
15886 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
15887 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
15888 (term->type == XML_SCHEMA_TYPE_ALL))) {
15889 if (term == ctxtMGroup)
15890 return (particle);
15891 /*
15892 * Avoid infinite recursion on circular references not yet
15893 * examined.
15894 */
15895 if (term == selfMGroup)
15896 return (NULL);
15897 circ = xmlSchemaGetCircModelGrDefRef(ctxtMGroup, term,
15898 term->children);
15899 if (circ != NULL)
15900 return (circ);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015901 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015902 particle = particle->next;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015903 }
15904 return (NULL);
15905}
15906
15907/**
15908 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015909 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015910 * @ctxt: the parser context
15911 * @name: the name
15912 *
15913 * Checks for circular references to model group definitions.
15914 */
15915static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015916xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015917 xmlSchemaParserCtxtPtr ctxt,
15918 const xmlChar * name ATTRIBUTE_UNUSED)
15919{
15920 /*
15921 * Schema Component Constraint: Model Group Correct
15922 * 2 Circular groups are disallowed. That is, within the {particles}
15923 * of a group there must not be at any depth a particle whose {term}
15924 * is the group itself.
15925 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015926 if ((item == NULL) ||
15927 (item->type != XML_SCHEMA_TYPE_GROUP) ||
15928 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015929 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015930 {
15931 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015932
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015933 circ = xmlSchemaGetCircModelGrDefRef(item->children, NULL,
15934 item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015935 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015936 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015937 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015938 * TODO: The error report is not adequate: this constraint
15939 * is defined for model groups but not definitions, but since
15940 * there cannot be any circular model groups without a model group
15941 * definition (if not using a construction API), we check those
15942 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015943 */
15944 xmlSchemaPCustomErr(ctxt,
15945 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015946 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015947 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015948 "defined", xmlSchemaFormatQName(&str,
15949 item->targetNamespace, item->name));
15950 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015951 /*
15952 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015953 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015954 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015955 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015956 }
15957 }
15958}
15959
15960
15961/**
15962 * xmlSchemaGetCircAttrGrRef:
15963 * @ctxtGr: the searched attribute group
15964 * @attr: the current attribute list to be processed
15965 *
15966 * This one is intended to be used by
15967 * xmlSchemaCheckSRCAttributeGroupCircular only.
15968 *
15969 * Returns the circular attribute grou reference, otherwise NULL.
15970 */
15971static xmlSchemaAttributeGroupPtr
15972xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
15973 xmlSchemaAttributePtr attr)
15974{
15975 xmlSchemaAttributeGroupPtr circ = NULL, gr;
15976 int marked;
15977 /*
15978 * We will search for an attribute group reference which
15979 * references the context attribute group.
15980 */
15981 while (attr != NULL) {
15982 marked = 0;
15983 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
15984 gr = (xmlSchemaAttributeGroupPtr) attr;
15985 if (gr->refItem != NULL) {
15986 if (gr->refItem == ctxtGr)
15987 return (gr);
15988 else if (gr->refItem->flags &
15989 XML_SCHEMAS_ATTRGROUP_MARKED) {
15990 attr = attr->next;
15991 continue;
15992 } else {
15993 /*
15994 * Mark as visited to avoid infinite recursion on
15995 * circular references not yet examined.
15996 */
15997 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
15998 marked = 1;
15999 }
16000 }
16001 if (gr->attributes != NULL)
16002 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16003 /*
16004 * Unmark the visited group's attributes.
16005 */
16006 if (marked)
16007 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16008 if (circ != NULL)
16009 return (circ);
16010 }
16011 attr = attr->next;
16012 }
16013 return (NULL);
16014}
16015
16016/**
16017 * xmlSchemaCheckSRCAttributeGroupCircular:
16018 * attrGr: the attribute group definition
16019 * @ctxt: the parser context
16020 * @name: the name
16021 *
16022 * Checks for circular references of attribute groups.
16023 */
16024static void
16025xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
16026 xmlSchemaParserCtxtPtr ctxt,
16027 const xmlChar * name ATTRIBUTE_UNUSED)
16028{
16029 /*
16030 * Schema Representation Constraint:
16031 * Attribute Group Definition Representation OK
16032 * 3 Circular group reference is disallowed outside <redefine>.
16033 * That is, unless this element information item's parent is
16034 * <redefine>, then among the [children], if any, there must
16035 * not be an <attributeGroup> with ref [attribute] which resolves
16036 * to the component corresponding to this <attributeGroup>. Indirect
16037 * circularity is also ruled out. That is, when QName resolution
16038 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16039 * any <attributeGroup>s with a ref [attribute] among the [children],
16040 * it must not be the case that a ·QName· is encountered at any depth
16041 * which resolves to the component corresponding to this <attributeGroup>.
16042 */
16043 /*
16044 * Only global components can be referenced.
16045 */
16046 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
16047 (attrGr->attributes == NULL))
16048 return;
16049 else {
16050 xmlSchemaAttributeGroupPtr circ;
16051
16052 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16053 if (circ != NULL) {
16054 /*
16055 * TODO: Report the referenced attr group as QName.
16056 */
16057 xmlSchemaPCustomErr(ctxt,
16058 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16059 NULL, NULL, circ->node,
16060 "Circular reference to the attribute group '%s' "
16061 "defined", attrGr->name);
16062 /*
16063 * NOTE: We will cut the reference to avoid further
16064 * confusion of the processor.
16065 * BADSPEC: The spec should define how to process in this case.
16066 */
16067 circ->attributes = NULL;
16068 circ->refItem = NULL;
16069 }
16070 }
16071}
16072
16073/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000016074 * xmlSchemaAttrGrpFixup:
16075 * @attrgrpDecl: the schema attribute definition
16076 * @ctxt: the schema parser context
16077 * @name: the attribute name
16078 *
16079 * Fixes finish doing the computations on the attributes definitions
16080 */
16081static void
Daniel Veillard3646d642004-06-02 19:19:14 +000016082xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016083 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000016084{
16085 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016086 name = attrgrp->name;
16087 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016088 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000016089 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016090 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000016091
Daniel Veillardc0826a72004-08-10 14:17:33 +000016092 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
16093 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016094 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016095 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016096 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016097 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
16098 "ref", attrgrp->ref, attrgrp->refNs,
16099 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016100 return;
16101 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016102 attrgrp->refItem = ref;
16103 /*
16104 * Check for self reference!
16105 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016106 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000016107 attrgrp->attributes = ref->attributes;
16108 attrgrp->attributeWildcard = ref->attributeWildcard;
16109 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000016110}
16111
16112/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016113 * xmlSchemaAttrCheckValConstr:
16114 * @item: an schema attribute declaration/use
16115 * @ctxt: a schema parser context
16116 * @name: the name of the attribute
16117 *
16118 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000016119 *
16120 * Fixes finish doing the computations on the attributes definitions
16121 */
16122static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016123xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
16124 xmlSchemaParserCtxtPtr ctxt,
16125 const xmlChar * name ATTRIBUTE_UNUSED)
16126{
16127
16128 /*
16129 * a-props-correct
16130 * Schema Component Constraint: Attribute Declaration Properties Correct
16131 *
16132 * 2 if there is a {value constraint}, the canonical lexical
16133 * representation of its value must be ·valid· with respect
16134 * to the {type definition} as defined in String Valid (§3.14.4).
16135 */
16136
16137 if (item->defValue != NULL) {
16138 int ret;
16139 xmlNodePtr node;
16140 xmlSchemaTypePtr type;
16141
16142 if (item->subtypes == NULL) {
16143 xmlSchemaPErr(ctxt, item->node,
16144 XML_SCHEMAP_INTERNAL,
16145 "Internal error: xmlSchemaCheckAttrValConstr, "
16146 "type is missing... skipping validation of "
16147 "value constraint", NULL, NULL);
16148 return;
16149 }
16150
16151 /*
16152 * TODO: Try to avoid creating a new context.
16153 * TODO: This all is not very performant.
16154 */
16155 type = item->subtypes;
16156 /*
16157 * Ensure there's validation context.
16158 */
16159 if (ctxt->vctxt == NULL) {
16160 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
16161 xmlSchemaPErr(ctxt, item->node,
16162 XML_SCHEMAP_INTERNAL,
16163 "Internal error: xmlSchemaCheckAttrValConstr, "
16164 "creating a new validation context.\n",
16165 NULL, NULL);
16166 return;
16167 }
16168 }
16169
16170 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
16171 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
16172 else
16173 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
16174 ctxt->vctxt->node = node;
16175 ctxt->vctxt->cur = NULL;
16176 /*
16177 * NOTE: This call does not check the content nodes,
16178 * since they are not available:
16179 * facet->node is just the node holding the facet
16180 * definition, *not* the attribute holding the *value*
16181 * of the facet.
16182 */
16183 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
16184 item->defValue, 0, 1, 1, 0);
16185 if (ret == 0) {
16186 /*
16187 * Store the computed value.
16188 */
16189 item->defVal = ctxt->vctxt->value;
16190 ctxt->vctxt->value = NULL;
16191 } else if (ret > 0) {
16192 if (ctxt != NULL) {
16193 xmlSchemaPSimpleTypeErr(ctxt,
16194 XML_SCHEMAP_A_PROPS_CORRECT_2,
16195 NULL, NULL, node,
16196 type, NULL, item->defValue,
16197 NULL, NULL, NULL);
16198 }
16199 } else if (ret < 0) {
16200 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16201 NULL, NULL, node,
16202 "Internal error: xmlSchemaAttrCheckValConstr, "
16203 "failed to validate the value constraint of the "
16204 "attribute decl/use against the type '%s'",
16205 type->name);
16206 }
16207 }
16208}
16209
16210#if 0 /* Not used yet. */
16211static int
16212xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
16213 xmlSchemaElementPtr edecl)
16214{
16215 /*
16216 * TODO: 1 The values of the properties of an element declaration must be as
16217 * described in the property tableau in The Element Declaration Schema
16218 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
16219 */
16220 /*
16221 * 2 If there is a {value constraint}, the canonical lexical
16222 * representation of its value must be ·valid· with respect to the {type
16223 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
16224 *
16225 * NOTE: This is done in xmlSchemaCheckElemValConstr.
16226 */
16227 /*
16228 * 3 If there is a non-·absent· {substitution group affiliation},
16229 * then {scope} must be global.
16230 *
16231 * NOTE: This is done in xmlSchemaParseElement.
16232 * TODO: Move it to this layer here.
16233 */
16234 /*
16235 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
16236 * of the element declaration must be validly derived from the {type
16237 * definition} of the {substitution group affiliation}, given the value
16238 * of the {substitution group exclusions} of the {substitution group
16239 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
16240 * (if the {type definition} is complex) or as defined in
16241 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
16242 * simple).
16243 */
16244 /*
16245 * TODO: 5 If the {type definition} or {type definition}'s {content type}
16246 * is or is derived from ID then there must not be a {value constraint}.
16247 * Note: The use of ID as a type definition for elements goes beyond
16248 * XML 1.0, and should be avoided if backwards compatibility is desired
16249 */
16250 /*
16251 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
16252 * be possible to return to an element declaration by repeatedly following
16253 * the {substitution group affiliation} property.
16254 */
16255}
16256#endif
16257
16258/**
16259 * xmlSchemaCheckElemValConstr:
16260 * @item: an schema element declaration/particle
16261 * @ctxt: a schema parser context
16262 * @name: the name of the attribute
16263 *
16264 * Validates the value constraints of an element declaration.
16265 *
16266 * Fixes finish doing the computations on the element declarations.
16267 */
16268static void
16269xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
16270 xmlSchemaParserCtxtPtr ctxt,
16271 const xmlChar * name ATTRIBUTE_UNUSED)
16272{
16273 if (decl->value != NULL) {
16274 int ret;
16275 xmlNodePtr node = NULL;
16276 xmlSchemaTypePtr type;
16277
16278 /*
16279 * 2 If there is a {value constraint}, the canonical lexical
16280 * representation of its value must be ·valid· with respect to the {type
16281 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
16282 */
16283 if (decl->subtypes == NULL) {
16284 xmlSchemaPErr(ctxt, decl->node,
16285 XML_SCHEMAP_INTERNAL,
16286 "Internal error: xmlSchemaCheckElemValConstr, "
16287 "type is missing... skipping validation of "
16288 "the value constraint", NULL, NULL);
16289 return;
16290 }
16291 /*
16292 * Ensure there's a validation context.
16293 */
16294 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16295 return;
16296
16297 type = decl->subtypes;
16298
16299 if (decl->node != NULL) {
16300 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
16301 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
16302 else
16303 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
16304 }
16305 ctxt->vctxt->node = node;
16306 ctxt->vctxt->cur = NULL;
16307 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
16308 node);
16309 if (ret == 0) {
16310 /*
16311 * Consume the computed value.
16312 */
16313 decl->defVal = ctxt->vctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016314 ctxt->vctxt->value = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016315 } else if (ret < 0) {
16316 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16317 NULL, NULL, node,
16318 "Internal error: xmlSchemaElemCheckValConstr, "
16319 "failed to validate the value constraint of the "
16320 "element declaration '%s'",
16321 decl->name);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016322 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016323 }
16324}
16325
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016326
16327/**
16328 * xmlSchemaMiscRefFixup:
16329 * @item: an schema component
16330 * @ctxt: a schema parser context
16331 * @name: the internal name of the component
16332 *
16333 * Resolves references of misc. schema components.
16334 */
16335static void
16336xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
16337 xmlSchemaParserCtxtPtr ctxt,
16338 const xmlChar * name ATTRIBUTE_UNUSED)
16339{
16340 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
16341 if ((item->children != NULL) &&
16342 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
16343 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
16344 xmlSchemaTreeItemPtr refItem;
16345 /*
16346 * Resolve the reference.
16347 */
16348 item->children = NULL;
16349 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
16350 ref->itemType, ref->name, ref->targetNamespace);
16351 if (refItem == NULL) {
16352 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
16353 NULL, NULL, GET_NODE(item), "ref", ref->name,
16354 ref->targetNamespace, ref->itemType, NULL);
16355 } else {
16356 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
16357 /*
16358 * Assign the model group of the model group definition
16359 * to the particle's "term".
16360 */
16361 item->children = refItem->children;
16362 } else
16363 item->children = refItem;
16364 }
16365 }
16366 }
16367}
16368
16369
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016370/**
16371 * xmlSchemaAttrFixup:
16372 * @item: an schema attribute declaration/use.
16373 * @ctxt: a schema parser context
16374 * @name: the name of the attribute
16375 *
16376 * Fixes finish doing the computations on attribute declarations/uses.
16377 */
16378static void
16379xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
16380 xmlSchemaParserCtxtPtr ctxt,
16381 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000016382{
Daniel Veillardc0826a72004-08-10 14:17:33 +000016383 /*
16384 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016385 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000016386 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016387 /*
16388 * The simple type definition corresponding to the <simpleType> element
16389 * information item in the [children], if present, otherwise the simple
16390 * type definition ·resolved· to by the ·actual value· of the type
16391 * [attribute], if present, otherwise the ·simple ur-type definition·.
16392 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016393 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000016394 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016395 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
16396 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016397 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016398 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016399 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000016400
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016401 type = xmlSchemaGetType(ctxt->schema, item->typeName,
16402 item->typeNs);
16403 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016404 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016405 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016406 NULL, (xmlSchemaTypePtr) item, item->node,
16407 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016408 XML_SCHEMA_TYPE_SIMPLE, NULL);
16409 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016410 item->subtypes = type;
16411
16412 } else if (item->ref != NULL) {
16413 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000016414
Daniel Veillardc0826a72004-08-10 14:17:33 +000016415 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016416 * We have an attribute use here; assign the referenced
16417 * attribute declaration.
16418 */
16419 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016420 * TODO: Evaluate, what errors could occur if the declaration is not
16421 * found. It might be possible that the "typefixup" might crash if
16422 * no ref declaration was found.
16423 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016424 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
16425 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016426 xmlSchemaPResCompAttrErr(ctxt,
16427 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016428 NULL, (xmlSchemaTypePtr) item, item->node,
16429 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016430 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016431 return;
16432 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016433 item->refDecl = decl;
16434 xmlSchemaAttrFixup(decl, ctxt, NULL);
16435
16436 item->subtypes = decl->subtypes;
16437 /*
16438 * Attribute Use Correct
16439 * au-props-correct.2: If the {attribute declaration} has a fixed
16440 * {value constraint}, then if the attribute use itself has a
16441 * {value constraint}, it must also be fixed and its value must match
16442 * that of the {attribute declaration}'s {value constraint}.
16443 */
16444 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
16445 (item->defValue != NULL)) {
16446 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
16447 (!xmlStrEqual(item->defValue, decl->defValue))) {
16448 xmlSchemaPCustomErr(ctxt,
16449 XML_SCHEMAP_AU_PROPS_CORRECT_2,
16450 NULL, NULL, item->node,
16451 "The value constraint must be fixed "
16452 "and match the referenced attribute "
16453 "declarations's value constraint '%s'",
16454 decl->defValue);
16455 }
16456 /*
16457 * FUTURE: One should change the values of the attr. use
16458 * if ever validation should be attempted even if the
16459 * schema itself was not fully valid.
16460 */
16461 }
Daniel Veillard3646d642004-06-02 19:19:14 +000016462 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016463 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
16464 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016465}
16466
16467/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016468 * xmlSchemaResolveIDCKeyRef:
16469 * @idc: the identity-constraint definition
16470 * @ctxt: the schema parser context
16471 * @name: the attribute name
16472 *
16473 * Resolve keyRef references to key/unique IDCs.
16474 */
16475static void
16476xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
16477 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000016478 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016479{
16480 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
16481 return;
16482 if (idc->ref->name != NULL) {
16483 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
16484 ctxt->schema->idcDef,
16485 idc->ref->name,
16486 idc->ref->targetNamespace);
16487 if (idc->ref->item == NULL) {
16488 /*
16489 * TODO: It is actually not an error to fail to resolve.
16490 */
16491 xmlSchemaPResCompAttrErr(ctxt,
16492 XML_SCHEMAP_SRC_RESOLVE,
16493 NULL, (xmlSchemaTypePtr) idc, idc->node,
16494 "refer", idc->ref->name,
16495 idc->ref->targetNamespace,
16496 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
16497 return;
16498 }
16499 }
16500}
16501
16502/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016503 * xmlSchemaParse:
16504 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000016505 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000016506 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000016507 * XML Shema struture which can be used to validate instances.
16508 * *WARNING* this interface is highly subject to change
16509 *
16510 * Returns the internal XML Schema structure built from the resource or
16511 * NULL in case of error
16512 */
16513xmlSchemaPtr
16514xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
16515{
16516 xmlSchemaPtr ret = NULL;
16517 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000016518 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000016519 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000016520
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016521 /*
16522 * This one is used if the schema to be parsed was specified via
16523 * the API; i.e. not automatically by the validated instance document.
16524 */
16525
Daniel Veillard4255d502002-04-16 15:50:10 +000016526 xmlSchemaInitTypes();
16527
Daniel Veillard6045c902002-10-09 21:13:59 +000016528 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000016529 return (NULL);
16530
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000016531 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000016532 ctxt->counter = 0;
16533 ctxt->container = NULL;
16534
16535 /*
16536 * First step is to parse the input document into an DOM/Infoset
16537 */
Daniel Veillard6045c902002-10-09 21:13:59 +000016538 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000016539 doc = xmlReadFile((const char *) ctxt->URL, NULL,
16540 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016541 if (doc == NULL) {
16542 xmlSchemaPErr(ctxt, NULL,
16543 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016544 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016545 ctxt->URL, NULL);
16546 return (NULL);
16547 }
Daniel Veillard6045c902002-10-09 21:13:59 +000016548 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000016549 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
16550 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016551 if (doc == NULL) {
16552 xmlSchemaPErr(ctxt, NULL,
16553 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016554 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016555 NULL, NULL);
16556 return (NULL);
16557 }
16558 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000016559 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000016560 } else if (ctxt->doc != NULL) {
16561 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000016562 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000016563 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016564 xmlSchemaPErr(ctxt, NULL,
16565 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016566 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016567 NULL, NULL);
16568 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000016569 }
16570
16571 /*
16572 * Then extract the root and Schema parse it
16573 */
16574 root = xmlDocGetRootElement(doc);
16575 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016576 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
16577 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016578 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000016579 if (!preserve) {
16580 xmlFreeDoc(doc);
16581 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016582 return (NULL);
16583 }
16584
16585 /*
16586 * Remove all the blank text nodes
16587 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000016588 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000016589
16590 /*
16591 * Then do the parsing for good
16592 */
16593 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000016594 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000016595 if (!preserve) {
16596 xmlFreeDoc(doc);
16597 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016598 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000016599 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016600 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000016601 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000016602 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016603 ctxt->ctxtType = NULL;
16604 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016605
16606
16607 if (ret->volatiles != NULL) {
16608 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
16609 int i;
16610 xmlSchemaTreeItemPtr item;
16611
16612 for (i = 0; i < list->nbItems; i++) {
16613 item = (xmlSchemaTreeItemPtr) list->items[i];
16614 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
16615 xmlSchemaMiscRefFixup(item, ctxt, NULL);
16616 /* xmlHashScan(ret->miscComps,
16617 (xmlHashScanner) xmlSchemaMiscRefFixup, ctxt); */
16618 }
16619 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016620 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000016621 * Then fixup all attributes declarations
16622 */
16623 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
16624
16625 /*
16626 * Then fixup all attributes group declarations
16627 */
16628 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
16629 ctxt);
16630
16631 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016632 * Resolve identity-constraint keyRefs.
16633 */
16634 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016635 /*
16636 * Check type defnitions for circular references.
16637 */
16638 xmlHashScan(ret->typeDecl, (xmlHashScanner)
16639 xmlSchemaCheckTypeDefCircular, ctxt);
16640 /*
16641 * Check model groups defnitions for circular references.
16642 */
16643 xmlHashScan(ret->groupDecl, (xmlHashScanner)
16644 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016645
16646 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016647 * Check attribute groups for circular references.
16648 */
16649 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
16650 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016651
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016652 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016653 * Then fix references of element declaration; apply constraints.
16654 */
16655 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016656 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000016657
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000016658 /*
16659 * We will stop here if the schema was not valid to avoid internal errors
16660 * on missing sub-components. This is not conforming to the spec, since it
16661 * allows missing components, but it might make further processing crash.
16662 * So see it as a very strict handling, which might be made more lax in the
16663 * future.
16664 */
16665 if (ctxt->nberrors != 0)
16666 goto exit;
16667 /*
16668 * Then fixup all types properties
16669 */
16670 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016671
Daniel Veillard4255d502002-04-16 15:50:10 +000016672 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016673 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000016674 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016675 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016676 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016677
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016678 /*
16679 * Validate the value constraint of attribute declarations/uses.
16680 */
16681 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
16682
16683 /*
16684 * Validate the value constraint of element declarations.
16685 */
16686 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
16687
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000016688exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000016689 if (ctxt->nberrors != 0) {
16690 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016691 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000016692 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016693 return (ret);
16694}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016695
Daniel Veillard4255d502002-04-16 15:50:10 +000016696/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000016697 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000016698 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000016699 * @err: the error callback
16700 * @warn: the warning callback
16701 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000016702 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000016703 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000016704 */
16705void
16706xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016707 xmlSchemaValidityErrorFunc err,
16708 xmlSchemaValidityWarningFunc warn, void *ctx)
16709{
Daniel Veillard4255d502002-04-16 15:50:10 +000016710 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016711 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000016712 ctxt->error = err;
16713 ctxt->warning = warn;
16714 ctxt->userData = ctx;
16715}
16716
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000016717/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000016718 * xmlSchemaGetParserErrors:
16719 * @ctxt: a XMl-Schema parser context
16720 * @err: the error callback result
16721 * @warn: the warning callback result
16722 * @ctx: contextual data for the callbacks result
16723 *
16724 * Get the callback information used to handle errors for a parser context
16725 *
16726 * Returns -1 in case of failure, 0 otherwise
16727 */
16728int
16729xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
16730 xmlSchemaValidityErrorFunc * err,
16731 xmlSchemaValidityWarningFunc * warn, void **ctx)
16732{
16733 if (ctxt == NULL)
16734 return(-1);
16735 if (err != NULL)
16736 *err = ctxt->error;
16737 if (warn != NULL)
16738 *warn = ctxt->warning;
16739 if (ctx != NULL)
16740 *ctx = ctxt->userData;
16741 return(0);
16742}
16743
16744/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000016745 * xmlSchemaFacetTypeToString:
16746 * @type: the facet type
16747 *
16748 * Convert the xmlSchemaTypeType to a char string.
16749 *
16750 * Returns the char string representation of the facet type if the
16751 * type is a facet and an "Internal Error" string otherwise.
16752 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016753static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000016754xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
16755{
16756 switch (type) {
16757 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016758 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016759 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016760 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016761 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016762 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016763 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016764 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016765 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016766 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016767 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016768 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016769 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016770 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016771 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016772 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016773 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016774 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016775 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016776 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016777 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016778 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016779 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016780 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000016781 default:
16782 break;
16783 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016784 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000016785}
16786
Daniel Veillardc0826a72004-08-10 14:17:33 +000016787static int
16788xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
16789{
16790 xmlSchemaTypePtr anc;
16791
16792 /*
16793 * The normalization type can be changed only for types which are derived
16794 * from xsd:string.
16795 */
16796 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000016797 if (type->builtInType == XML_SCHEMAS_STRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016798 return(XML_SCHEMAS_FACET_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000016799 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016800 return(XML_SCHEMAS_FACET_REPLACE);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000016801 else if (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
16802 /*
16803 * Note that we assume a whitespace of preserve for anySimpleType.
16804 */
16805 return(XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016806 else {
16807 /*
16808 * For all ·atomic· datatypes other than string (and types ·derived·
16809 * by ·restriction· from it) the value of whiteSpace is fixed to
16810 * collapse
16811 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016812 return(XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016813 }
16814 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
16815 /*
16816 * For list types the facet "whiteSpace" is fixed to "collapse".
16817 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016818 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016819 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016820 return (XML_SCHEMAS_FACET_UNKNOWN);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016821 } else if (type->facetSet != NULL) {
16822 xmlSchemaTypePtr anyST;
16823 xmlSchemaFacetLinkPtr lin;
16824
16825 /*
16826 * Atomic types.
16827 */
16828 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
16829 anc = type->baseType;
16830 do {
16831 /*
16832 * For all ·atomic· datatypes other than string (and types ·derived·
16833 * by ·restriction· from it) the value of whiteSpace is fixed to
16834 * collapse
16835 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016836 if ((anc->builtInType == XML_SCHEMAS_STRING) ||
16837 (anc->builtInType == XML_SCHEMAS_NORMSTRING)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016838
16839 lin = type->facetSet;
16840 do {
16841 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016842 return(lin->facet->whitespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016843 }
16844 lin = lin->next;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016845 } while (lin != NULL);
16846 if (anc->builtInType == XML_SCHEMAS_NORMSTRING)
16847 return (XML_SCHEMAS_FACET_REPLACE);
16848 else
16849 return (XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016850 }
16851 anc = anc->baseType;
16852 } while (anc != anyST);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016853 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016854 }
16855 return (-1);
16856}
16857
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000016858/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000016859 * xmlSchemaValidateFacetsInternal:
16860 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000016861 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000016862 * @facets: the list of facets to check
16863 * @value: the lexical repr of the value to validate
16864 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000016865 * @fireErrors: if 0, only internal errors will be fired;
16866 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000016867 *
16868 * Check a value against all facet conditions
16869 *
16870 * Returns 0 if the element is schemas valid, a positive error code
16871 * number otherwise and -1 in case of internal or API error.
16872 */
16873static int
16874xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016875 xmlSchemaTypePtr type,
16876 const xmlChar * value,
16877 unsigned long length,
16878 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000016879{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000016880 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016881 xmlNodePtr node;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016882 xmlSchemaTypePtr biType; /* The build-in type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016883 xmlSchemaTypePtr tmpType;
16884 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000016885 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016886 xmlSchemaFacetPtr facet;
16887 unsigned long len = 0;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016888 xmlSchemaWhitespaceValueType ws;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016889
16890 ws = (xmlSchemaWhitespaceValueType) xmlSchemaGetWhiteSpaceFacetValue(type);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000016891
Daniel Veillardc0826a72004-08-10 14:17:33 +000016892#ifdef DEBUG_UNION_VALIDATION
16893 printf("Facets of type: '%s'\n", (const char *) type->name);
16894 printf(" fireErrors: %d\n", fireErrors);
16895#endif
16896
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016897 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016898 /*
16899 * NOTE: Do not jump away, if the facetSet of the given type is
16900 * empty: until now, "pattern" facets of the *base types* need to
16901 * be checked as well.
16902 */
16903 biType = type->baseType;
16904 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
16905 biType = biType->baseType;
16906 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016907 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016908 "Internal error: xmlSchemaValidateFacetsInternal, "
16909 "the base type axis of the given type '%s' does not resolve to "
16910 "a built-in type.\n",
16911 type->name, NULL);
16912 return (-1);
16913 }
16914
16915 if (type->facetSet != NULL) {
16916 facetLink = type->facetSet;
16917 while (facetLink != NULL) {
16918 facet = facetLink->facet;
16919 /*
16920 * Skip the pattern "whiteSpace": it is used to
16921 * format the character content beforehand.
16922 */
16923 switch (facet->type) {
16924 case XML_SCHEMA_FACET_WHITESPACE:
16925 case XML_SCHEMA_FACET_PATTERN:
16926 case XML_SCHEMA_FACET_ENUMERATION:
16927 break;
16928 case XML_SCHEMA_FACET_LENGTH:
16929 case XML_SCHEMA_FACET_MINLENGTH:
16930 case XML_SCHEMA_FACET_MAXLENGTH:
16931 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
16932 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016933 value, length, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016934 len = length;
16935 } else
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016936 ret = xmlSchemaValidateLengthFacetWhtsp(facet,
16937 (xmlSchemaValType) biType->builtInType,
16938 value, ctxt->value, &len, ws);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016939 break;
16940 default:
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016941 ret = xmlSchemaValidateFacetWhtsp(facet, ws,
16942 biType->builtInType, value, ctxt->value, ws);
16943 /*
16944 * ret = xmlSchemaValidateFacet(biType, facet, value,
16945 * ctxt->value);
16946 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016947 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016948 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016949 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016950 "Internal error: xmlSchemaValidateFacetsInternal, "
16951 "validating facet of type '%s'.\n",
16952 type->name, NULL);
16953 break;
16954 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016955 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016956 type, facet, NULL, NULL, NULL, NULL);
16957 }
16958
16959 facetLink = facetLink->next;
16960 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016961
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016962 }
16963
Daniel Veillardc0826a72004-08-10 14:17:33 +000016964 if (ret >= 0) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016965 xmlSchemaWhitespaceValueType fws;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016966 int found = 0;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016967 /*
16968 * Process enumerations. Facet values are in the value space
16969 * of the defining type's base type. This seems to be a bug in the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016970 * XML Schema 1.0 spec. Use the whitespace type of the base type.
16971 * Only the first set of enumerations in the ancestor-or-self axis
16972 * is used for validation.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016973 */
16974 tmpType = type;
16975 do {
16976 /*
16977 * Use the whitespace type of the base type.
16978 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016979 fws = (xmlSchemaWhitespaceValueType)
16980 xmlSchemaGetWhiteSpaceFacetValue(tmpType->baseType);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016981 retFacet = 0;
16982 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
16983 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016984 continue;
16985 found = 1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016986 retFacet = xmlSchemaValidateFacetWhtsp(facet, fws,
16987 biType->builtInType, value, ctxt->value, ws);
16988 if (retFacet == 0)
16989 break;
16990 else if (retFacet < 0) {
16991 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
16992 "Internal error: xmlSchemaValidateFacetsInternal, "
16993 "validating enumeration facet '%s' of type '%s'.\n",
16994 facet->value, tmpType->name);
16995 ret = -1;
16996 break;
16997 }
16998 }
16999 if (retFacet <= 0)
17000 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017001 tmpType = tmpType->baseType;
17002 } while ((! found) && (tmpType != NULL) &&
17003 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017004 if (retFacet > 0) {
Kasimier T. Buchcik53b5e052005-03-24 11:05:13 +000017005 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017006 if (fireErrors) {
17007 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, NULL,
17008 NULL, NULL, NULL, NULL);
17009 }
17010 }
17011 }
17012
17013 if (ret >= 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017014 /*
17015 * Process patters. Pattern facets are ORed at type level
17016 * and ANDed if derived. Walk the base type axis.
17017 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017018 tmpType = type;
17019 facet = NULL;
17020 do {
17021 retFacet = 0;
17022 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017023 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017024 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
17025 continue;
17026 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
17027 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017028 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017029 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017030 else if (retFacet < 0) {
17031 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
17032 "Internal error: xmlSchemaValidateFacetsInternal, "
17033 "validating 'pattern' facet '%s' of type '%s'.\n",
17034 facetLink->facet->value, tmpType->name);
17035 ret = -1;
17036 break;
17037 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000017038 /* Save the last non-validating facet. */
17039 facet = facetLink->facet;
17040 }
17041 if (retFacet != 0)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017042 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017043 tmpType = tmpType->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017044 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017045 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017046 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
17047 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017048 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017049 NULL, NULL, NULL, NULL);
17050 }
17051 }
17052 }
17053
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017054 return (ret);
17055}
17056
Daniel Veillard4255d502002-04-16 15:50:10 +000017057/************************************************************************
17058 * *
17059 * Simple type validation *
17060 * *
17061 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000017062
Daniel Veillard4255d502002-04-16 15:50:10 +000017063
17064/************************************************************************
17065 * *
17066 * DOM Validation code *
17067 * *
17068 ************************************************************************/
17069
Daniel Veillard4255d502002-04-16 15:50:10 +000017070static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017071 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000017072 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017073static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017074 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017075 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017076 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000017077
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017078static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017079static int xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017080
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017081/**
17082 * xmlSchemaGetFreshElemInfo:
17083 * @vctxt: the schema validation context
17084 *
17085 * Creates/reuses and initializes the element info item for
17086 * the currect tree depth.
17087 *
17088 * Returns the element info item or NULL on API or internal errors.
17089 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017090static xmlSchemaNodeInfoPtr
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017091xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt,
17092 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017093{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017094 xmlSchemaNodeInfoPtr info = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017095
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017096 if (depth > vctxt->sizeElemInfos) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017097 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017098 "Internal error: xmlSchemaGetFreshElemInfo, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017099 "an inconsistent depth encountered.\n",
17100 NULL, NULL);
17101 return (NULL);
17102 }
17103 if (vctxt->elemInfos == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017104 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
17105 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017106 if (vctxt->elemInfos == NULL) {
17107 xmlSchemaVErrMemory(vctxt,
17108 "allocating the element info array", NULL);
17109 return (NULL);
17110 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017111 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017112 vctxt->sizeElemInfos = 10;
17113 } else if (vctxt->sizeElemInfos == vctxt->depth) {
17114 int i = vctxt->sizeElemInfos;
17115
17116 vctxt->sizeElemInfos *= 2;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017117 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017118 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017119 sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017120 if (vctxt->elemInfos == NULL) {
17121 xmlSchemaVErrMemory(vctxt,
17122 "re-allocating the element info array", NULL);
17123 return (NULL);
17124 }
17125 /*
17126 * We need the new memory to be NULLed.
17127 * TODO: Use memset instead?
17128 */
17129 for (; i < vctxt->sizeElemInfos; i++)
17130 vctxt->elemInfos[i] = NULL;
17131 } else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017132 info = vctxt->elemInfos[depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017133
17134 if (info == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017135 info = (xmlSchemaNodeInfoPtr)
17136 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017137 if (info == NULL) {
17138 xmlSchemaVErrMemory(vctxt,
17139 "allocating an element info", NULL);
17140 return (NULL);
17141 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017142 vctxt->elemInfos[depth] = info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017143 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017144 memset(info, 0, sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017145 info->depth = depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017146
17147 return (info);
17148}
Daniel Veillard3646d642004-06-02 19:19:14 +000017149
17150/**
17151 * xmlSchemaFreeAttrStates:
17152 * @state: a list of attribute states
17153 *
17154 * Free the given list of attribute states
17155 *
17156 */
17157static void
17158xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
17159{
17160 xmlSchemaAttrStatePtr tmp;
17161 while (state != NULL) {
17162 tmp = state;
17163 state = state->next;
17164 xmlFree(tmp);
17165 }
17166}
17167
Daniel Veillard4255d502002-04-16 15:50:10 +000017168/**
17169 * xmlSchemaRegisterAttributes:
17170 * @ctxt: a schema validation context
17171 * @attrs: a list of attributes
17172 *
17173 * Register the list of attributes as the set to be validated on that element
17174 *
17175 * Returns -1 in case of error, 0 otherwise
17176 */
17177static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017178xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
17179{
Daniel Veillard3646d642004-06-02 19:19:14 +000017180 xmlSchemaAttrStatePtr tmp;
17181
17182 ctxt->attr = NULL;
17183 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000017184 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017185 if ((attrs->ns != NULL) &&
17186 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
17187 attrs = attrs->next;
17188 continue;
17189 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000017190 tmp = (xmlSchemaAttrStatePtr)
17191 xmlMalloc(sizeof(xmlSchemaAttrState));
17192 if (tmp == NULL) {
17193 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
17194 return (-1);
17195 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017196 tmp->attr = attrs;
17197 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
17198 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017199 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000017200 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017201 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000017202 else
17203 ctxt->attrTop->next = tmp;
17204 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017205 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000017206 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017207 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000017208}
17209
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000017210#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000017211/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017212 * xmlSchemaValidateCheckNodeList
17213 * @nodelist: the list of nodes
17214 *
17215 * Check the node list is only made of text nodes and entities pointing
17216 * to text nodes
17217 *
17218 * Returns 1 if true, 0 if false and -1 in case of error
17219 */
17220static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017221xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
17222{
Daniel Veillard4255d502002-04-16 15:50:10 +000017223 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017224 if (nodelist->type == XML_ENTITY_REF_NODE) {
17225 TODO /* implement recursion in the entity content */
17226 }
17227 if ((nodelist->type != XML_TEXT_NODE) &&
17228 (nodelist->type != XML_COMMENT_NODE) &&
17229 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000017230 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017231 return (0);
17232 }
17233 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000017234 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017235 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000017236}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000017237#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000017238
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017239static void
17240xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
17241{
17242 int i, nbItems;
17243 xmlSchemaTypePtr item, *items;
17244
17245
17246 /*
17247 * During the Assemble of the schema ctxt->curItems has
17248 * been filled with the relevant new items. Fix those up.
17249 */
17250 nbItems = ctxt->assemble->nbItems;
17251 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
17252
17253 for (i = 0; i < nbItems; i++) {
17254 item = items[i];
17255 switch (item->type) {
17256 case XML_SCHEMA_TYPE_ATTRIBUTE:
17257 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
17258 break;
17259 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017260 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017261 NULL, NULL, NULL);
17262 break;
17263 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
17264 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
17265 ctxt, NULL);
17266 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017267 case XML_SCHEMA_TYPE_PARTICLE:
17268 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017269 default:
17270 break;
17271 }
17272 }
17273 /*
17274 * Circularity checks.
17275 */
17276 for (i = 0; i < nbItems; i++) {
17277 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017278 switch (item->type) {
17279 case XML_SCHEMA_TYPE_COMPLEX:
17280 case XML_SCHEMA_TYPE_SIMPLE:
17281 xmlSchemaCheckTypeDefCircular(
17282 (xmlSchemaTypePtr) item, ctxt, NULL);
17283 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017284 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017285 xmlSchemaCheckGroupDefCircular(
17286 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017287 break;
17288 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
17289 xmlSchemaCheckAttributeGroupCircular(
17290 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
17291 break;
17292 default:
17293 break;
17294 }
17295 }
17296 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017297 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017298 */
17299 for (i = 0; i < nbItems; i++) {
17300 item = items[i];
17301 switch (item->type) {
17302 case XML_SCHEMA_TYPE_SIMPLE:
17303 case XML_SCHEMA_TYPE_COMPLEX:
17304 xmlSchemaTypeFixup(item, ctxt, NULL);
17305 break;
17306 default:
17307 break;
17308 }
17309 }
17310 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017311 * Build the content model for complex types.
17312 */
17313 for (i = 0; i < nbItems; i++) {
17314 item = items[i];
17315 switch (item->type) {
17316 case XML_SCHEMA_TYPE_COMPLEX:
17317 xmlSchemaBuildContentModel(item, ctxt, NULL);
17318 break;
17319 default:
17320 break;
17321 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017322 }
17323 /*
17324 * Validate value contraint values.
17325 */
17326 for (i = 0; i < nbItems; i++) {
17327 item = items[i];
17328 switch (item->type) {
17329 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017330 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
17331 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017332 break;
17333 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017334 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item,
17335 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017336 break;
17337 default:
17338 break;
17339 }
17340 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017341}
17342
17343/**
17344 * xmlSchemaAssembleByLocation:
17345 * @pctxt: a schema parser context
17346 * @vctxt: a schema validation context
17347 * @schema: the existing schema
17348 * @node: the node that fired the assembling
17349 * @nsName: the namespace name of the new schema
17350 * @location: the location of the schema
17351 *
17352 * Expands an existing schema by an additional schema.
17353 *
17354 * Returns 0 if the new schema is correct, a positive error code
17355 * number otherwise and -1 in case of an internal or API error.
17356 */
17357static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017358xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
17359 xmlSchemaPtr schema,
17360 xmlNodePtr node,
17361 const xmlChar *nsName,
17362 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017363{
17364 const xmlChar *targetNs, *oldtns;
17365 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017366 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017367 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017368 xmlSchemaParserCtxtPtr pctxt;
17369
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017370 /*
17371 * This should be used:
17372 * 1. on <import>(s)
17373 * 2. if requested by the validated instance
17374 * 3. if requested via the API
17375 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017376 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017377 return (-1);
17378 /*
17379 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017380 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017381 if ((vctxt->pctxt == NULL) &&
17382 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
17383 xmlSchemaVErr(vctxt, node,
17384 XML_SCHEMAV_INTERNAL,
17385 "Internal error: xmlSchemaAssembleByLocation, "
17386 "failed to create a temp. parser context.\n",
17387 NULL, NULL);
17388 return (-1);
17389 }
17390 pctxt = vctxt->pctxt;
17391 /*
17392 * Set the counter to produce unique names for anonymous items.
17393 */
17394 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017395 /*
17396 * Acquire the schema document.
17397 */
17398 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
17399 nsName, location, &doc, &targetNs, 0);
17400 if (ret != 0) {
17401 if (doc != NULL)
17402 xmlFreeDoc(doc);
17403 } else if (doc != NULL) {
17404 docElem = xmlDocGetRootElement(doc);
17405 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017406 * Create new assemble info.
17407 */
17408 if (pctxt->assemble == NULL) {
17409 pctxt->assemble = xmlSchemaNewAssemble();
17410 if (pctxt->assemble == NULL) {
17411 xmlSchemaVErrMemory(vctxt,
17412 "Memory error: xmlSchemaAssembleByLocation, "
17413 "allocating assemble info", NULL);
17414 xmlFreeDoc(doc);
17415 return (-1);
17416 }
17417 }
17418 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017419 * Save and reset the context & schema.
17420 */
17421 oldflags = schema->flags;
17422 oldtns = schema->targetNamespace;
17423 olddoc = schema->doc;
17424
17425 xmlSchemaClearSchemaDefaults(schema);
17426 schema->targetNamespace = targetNs;
17427 /* schema->nbCurItems = 0; */
17428 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017429 pctxt->ctxtType = NULL;
17430 pctxt->parentItem = NULL;
17431
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017432 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
17433 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017434 xmlSchemaPostSchemaAssembleFixup(pctxt);
17435 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017436 * Set the counter of items.
17437 */
17438 schema->counter = pctxt->counter;
17439 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017440 * Free the list of assembled components.
17441 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017442 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017443 /*
17444 * Restore the context & schema.
17445 */
17446 schema->flags = oldflags;
17447 schema->targetNamespace = oldtns;
17448 schema->doc = olddoc;
17449 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017450 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017451 return (ret);
17452}
17453
17454/**
17455 * xmlSchemaAssembleByXSIAttr:
17456 * @vctxt: a schema validation context
17457 * @xsiAttr: an xsi attribute
17458 * @noNamespace: whether a schema with no target namespace is exptected
17459 *
17460 * Expands an existing schema by an additional schema using
17461 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
17462 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
17463 * must be set to 1.
17464 *
17465 * Returns 0 if the new schema is correct, a positive error code
17466 * number otherwise and -1 in case of an internal or API error.
17467 */
17468static int
17469xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
17470 xmlAttrPtr xsiAttr,
17471 int noNamespace)
17472{
17473 xmlChar *value;
17474 const xmlChar *cur, *end;
17475 const xmlChar *nsname = NULL, *location;
17476 int count = 0;
17477 int ret = 0;
17478
17479 if (xsiAttr == NULL) {
17480 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
17481 NULL, NULL,
17482 "Internal error: xmlSchemaAssembleByXSIAttr, "
17483 "bad arguments", NULL);
17484 return (-1);
17485 }
17486 /*
17487 * Parse the value; we will assume an even number of values
17488 * to be given (this is how Xerces and XSV work).
17489 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017490 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017491 cur = value;
17492 do {
17493 if (noNamespace != 1) {
17494 /*
17495 * Get the namespace name.
17496 */
17497 while (IS_BLANK_CH(*cur))
17498 cur++;
17499 end = cur;
17500 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
17501 end++;
17502 if (end == cur)
17503 break;
17504 count++;
17505 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
17506 cur = end;
17507 }
17508 /*
17509 * Get the URI.
17510 */
17511 while (IS_BLANK_CH(*cur))
17512 cur++;
17513 end = cur;
17514 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
17515 end++;
17516 if (end == cur)
17517 break;
17518 count++;
17519 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017520 cur = end;
17521 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017522 xsiAttr->parent, nsname, location);
17523 if (ret == -1) {
17524 xmlSchemaVCustomErr(vctxt,
17525 XML_SCHEMAV_INTERNAL,
17526 (xmlNodePtr) xsiAttr, NULL,
17527 "Internal error: xmlSchemaAssembleByXSIAttr, "
17528 "assembling schemata", NULL);
17529 if (value != NULL)
17530 xmlFree(value);
17531 return (-1);
17532 }
17533 } while (*cur != 0);
17534 if (value != NULL)
17535 xmlFree(value);
17536 return (ret);
17537}
17538
17539/**
17540 * xmlSchemaAssembleByXSIElem:
17541 * @vctxt: a schema validation context
17542 * @elem: an element node possibly holding xsi attributes
17543 * @noNamespace: whether a schema with no target namespace is exptected
17544 *
17545 * Assembles an existing schema by an additional schema using
17546 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
17547 * of the given @elem.
17548 *
17549 * Returns 0 if the new schema is correct, a positive error code
17550 * number otherwise and -1 in case of an internal or API error.
17551 */
17552static int
17553xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
17554 xmlNodePtr elem)
17555{
17556 int ret = 0, retNs = 0;
17557 xmlAttrPtr attr;
17558
17559 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
17560 if (attr != NULL) {
17561 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
17562 if (retNs == -1)
17563 return (-1);
17564 }
17565 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
17566 if (attr != NULL) {
17567 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
17568 if (ret == -1)
17569 return (-1);
17570 }
17571 if (retNs != 0)
17572 return (retNs);
17573 else
17574 return (ret);
17575}
17576
Daniel Veillard4255d502002-04-16 15:50:10 +000017577/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017578 * xmlSchemaValidateCallback:
17579 * @ctxt: a schema validation context
17580 * @name: the name of the element detected (might be NULL)
17581 * @type: the type
17582 *
17583 * A transition has been made in the automata associated to an element
17584 * content model
17585 */
17586static void
17587xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017588 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017589 xmlSchemaBasicItemPtr item, xmlNodePtr node)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017590{
Daniel Veillard4255d502002-04-16 15:50:10 +000017591 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017592
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017593 /*
17594 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
17595 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017596 ctxt->node = node;
17597 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017598
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017599 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017600
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017601 /*
17602 * Assemble new schemata using xsi.
17603 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017604 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017605 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017606
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017607 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
17608 if (ret == -1) {
17609 xmlSchemaVCustomErr(ctxt,
17610 XML_SCHEMAV_INTERNAL,
17611 ctxt->node, NULL,
17612 "Internal error: xmlSchemaValidateElement, "
17613 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017614 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017615 }
17616 /*
17617 * NOTE: We won't react on schema parser errors here.
17618 * TODO: But a warning would be nice.
17619 */
17620 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017621 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017622 case XML_SCHEMA_TYPE_ELEMENT: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017623#ifdef DEBUG_CONTENT
17624 xmlGenericError(xmlGenericErrorContext,
17625 "xmlSchemaValidateCallback: %s, %s, %s\n",
17626 name, ((xmlSchemaElementPtr) item)->name, node->name);
17627#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017628 xmlSchemaValidateElementByDeclaration(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017629 (xmlSchemaElementPtr) item);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017630 break;
17631 }
17632 case XML_SCHEMA_TYPE_ANY:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017633#ifdef DEBUG_CONTENT
17634 xmlGenericError(xmlGenericErrorContext,
17635 "xmlSchemaValidateCallback: %s, <any>, %s\n",
17636 name, node->name);
17637#endif
17638 xmlSchemaValidateElementByWildcard(ctxt,
17639 (xmlSchemaWildcardPtr) item);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017640 break;
17641 default:
17642 break;
17643 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017644leave:
17645
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017646 xmlSchemaEndElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000017647 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017648}
Daniel Veillard4255d502002-04-16 15:50:10 +000017649
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017650static int
17651xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
17652 const xmlChar *value,
17653 xmlSchemaValPtr *val,
17654 xmlNodePtr node)
17655{
17656 int ret;
17657
17658 ret = xmlValidateQName(value, 1);
17659 if (ret != 0)
17660 return (ret);
17661
17662 {
17663 xmlChar *uri = NULL;
17664 xmlChar *local = NULL;
17665 xmlChar *prefix;
17666
17667 local = xmlSplitQName2(value, &prefix);
17668 if (prefix != NULL) {
17669 xmlNsPtr ns;
17670
17671 /*
17672 * TODO: Make this streamable.
17673 */
17674 if ((node == NULL) || (node->doc == NULL)) {
17675 xmlFree(prefix);
17676 xmlFree(local);
17677 return (3);
17678 }
17679
17680 ns = xmlSearchNs(node->doc, node, prefix);
17681 if (ns == NULL) {
17682 xmlFree(prefix);
17683 xmlFree(local);
17684 return (1);
17685 }
17686 }
17687 if (prefix != NULL) {
17688 if (xmlHashLookup2(vctxt->schema->notaDecl, local, uri) == NULL)
17689 ret = 1;
17690 } else if (xmlHashLookup2(vctxt->schema->notaDecl, value,
17691 NULL) == NULL)
17692 ret = 1;
17693
17694 if ((ret == 0) && (val != NULL)) {
17695 if (prefix != NULL) {
17696 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST local,
17697 BAD_CAST xmlStrdup(uri));
17698 local = NULL;
17699 } else
17700 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST xmlStrdup(value),
17701 NULL);
17702 if (*val == NULL)
17703 ret = -1;
17704 }
17705 if (local != NULL)
17706 xmlFree(local);
17707 }
17708
17709 return (ret);
17710}
17711
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017712static xmlSchemaTypePtr
17713xmlSchemaGetSimpleContentType(xmlSchemaTypePtr complexType)
17714{
17715 xmlSchemaTypePtr ret;
17716
17717 if (complexType->type != XML_SCHEMA_TYPE_COMPLEX)
17718 return (NULL);
17719 if (complexType->contentTypeDef != NULL)
17720 return (complexType->contentTypeDef);
17721 /*
17722 * TODO: This is only a workaround until the simple content
17723 * type is computed for complex types with simple content.
17724 */
17725 ret = complexType->baseType;
17726 while (ret != NULL) {
17727 if (IS_SIMPLE_TYPE(ret))
17728 return (ret);
17729 if (ret->builtInType == XML_SCHEMAS_ANYTYPE)
17730 return (NULL);
17731 if ((ret->type == XML_SCHEMA_TYPE_COMPLEX) &&
17732 (ret->contentTypeDef != NULL))
17733 ret = ret->contentTypeDef;
17734 else
17735 ret = ret->baseType;
17736 }
17737 return (ret);
17738}
17739
Daniel Veillard01fa6152004-06-29 17:04:39 +000017740/**
17741 * xmlSchemaValidateSimpleTypeValue:
17742 * @ctxt: a schema validation context
17743 * @value: the value to be validated
17744 * @fireErrors: shall errors be reported?
17745 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000017746 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017747 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000017748 *
17749 * Validates a value by the given type (user derived or built-in).
17750 *
17751 * Returns 0 if the value is valid, a positive error code
17752 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000017753 */
17754static int
17755xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017756 xmlSchemaTypePtr type,
17757 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017758 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017759 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017760 int normalize,
17761 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000017762{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017763 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017764 int ret = 0;
17765 xmlChar *normValue = NULL;
17766 int wtsp;
17767
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017768 node = ctxt->node;
17769 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017770 wtsp = ctxt->valueWS;
17771 /*
17772 * Normalize the value.
17773 */
17774 if (normalize &&
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017775 (ctxt->valueWS != XML_SCHEMAS_FACET_COLLAPSE)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017776 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
17777
17778 if ((norm != -1) && (norm > ctxt->valueWS)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017779 if (norm == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017780 normValue = xmlSchemaCollapseString(value);
17781 else
17782 normValue = xmlSchemaWhiteSpaceReplace(value);
17783 ctxt->valueWS = norm;
17784 if (normValue != NULL)
17785 value = (const xmlChar *) normValue;
17786 }
17787 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017788 /*
17789 * The nodes of a content must be checked only once,
17790 * this is not working since list types will fire this
17791 * multiple times.
17792 */
17793 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
17794 xmlNodePtr cur = ctxt->cur;
17795
17796 do {
17797 switch (cur->type) {
17798 case XML_TEXT_NODE:
17799 case XML_CDATA_SECTION_NODE:
17800 case XML_PI_NODE:
17801 case XML_COMMENT_NODE:
17802 case XML_XINCLUDE_START:
17803 case XML_XINCLUDE_END:
17804 break;
17805 case XML_ENTITY_REF_NODE:
17806 case XML_ENTITY_NODE:
17807 /* TODO: Scour the entities for illegal nodes. */
17808 TODO break;
17809 case XML_ELEMENT_NODE: {
17810 /* NOTE: Changed to an internal error, since the
17811 * existence of an element node will be already checked in
17812 * xmlSchemaValidateElementBySimpleType and in
17813 * xmlSchemaValidateElementByComplexType.
17814 */
17815 xmlSchemaVCustomErr(ctxt,
17816 XML_SCHEMAV_INTERNAL,
17817 /* XML_SCHEMAS_ERR_INVALIDELEM, */
17818 node, type,
17819 "Element '%s' found in simple type content",
17820 cur->name);
17821 return (XML_SCHEMAV_INTERNAL);
17822 }
17823 case XML_ATTRIBUTE_NODE:
17824 case XML_DOCUMENT_NODE:
17825 case XML_DOCUMENT_TYPE_NODE:
17826 case XML_DOCUMENT_FRAG_NODE:
17827 case XML_NOTATION_NODE:
17828 case XML_HTML_DOCUMENT_NODE:
17829 case XML_DTD_NODE:
17830 case XML_ELEMENT_DECL:
17831 case XML_ATTRIBUTE_DECL:
17832 case XML_ENTITY_DECL:
17833 case XML_NAMESPACE_DECL:
17834#ifdef LIBXML_DOCB_ENABLED
17835 case XML_DOCB_DOCUMENT_NODE:
17836#endif
17837 xmlSchemaVCustomErr(ctxt,
17838 XML_SCHEMAV_INTERNAL,
17839 /* XML_SCHEMAS_ERR_INVALIDELEM, */
17840 node, NULL,
17841 "Node of unexpected type found in simple type content",
17842 NULL);
17843 return (XML_SCHEMAV_INTERNAL);
17844 }
17845 cur = cur->next;
17846 } while (cur != NULL);
17847 }
17848
William M. Brack2f2a6632004-08-20 23:09:47 +000017849 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017850 xmlSchemaTypePtr simpType, anyType;
William M. Brack2f2a6632004-08-20 23:09:47 +000017851
17852 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
17853
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017854 simpType = xmlSchemaGetSimpleContentType(type);
17855 if (simpType == NULL) {
17856 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
17857 "Internal error: xmlSchemaValidateSimpleTypeValue, "
17858 "failed to obtain the simple content type of the complex "
17859 "type '%s'\n",
17860 type->name, NULL);
17861 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000017862 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017863 ret = xmlSchemaValidateSimpleTypeValue(ctxt, simpType, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000017864 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017865 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000017866 "Internal error: xmlSchemaValidateSimpleTypeValue, "
17867 "validating complex type '%s'\n",
17868 type->name, NULL);
17869 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
17870 /*
17871 * Check facets.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017872 *
17873 * TODO: This is somehow not nice, since if an error occurs
William M. Brack2f2a6632004-08-20 23:09:47 +000017874 * the reported type will be the complex type; the spec
17875 * wants a simple type to be created on the complex type
17876 * if it has a simple content. For now we have to live with
17877 * it.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017878 */
17879 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000017880 value, 0, fireErrors);
17881 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017882 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000017883 "Internal error: xmlSchemaValidateSimpleTypeValue, "
17884 "validating facets of complex type '%s'\n",
17885 type->name, NULL);
17886 } else if (ret > 0) {
17887 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000017888 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017889 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000017890 }
17891 }
17892 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000017893
17894 if (ctxt->value != NULL) {
17895 xmlSchemaFreeValue(ctxt->value);
17896 ctxt->value = NULL;
17897 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017898 /*
17899 * STREAM-READ-CHILDREN.
17900 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017901 if ((type->builtInType == XML_SCHEMAS_NOTATION) &&
17902 (ctxt->schema != NULL)) {
17903 /*
17904 * NOTATIONs need to be processed here, since they need
17905 * to lookup in the hashtable of NOTATION declarations.
17906 */
17907 ret = xmlSchemaValidateNotation(ctxt, value, &(ctxt->value), node);
17908 } else
17909 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017910 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000017911 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
17912 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
17913 else
17914 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017915 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017916 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000017917 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017918 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017919 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000017920 "validating built-in type '%s'\n", type->name, NULL);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017921 } else if ((ctxt->value == NULL) &&
17922 (type->builtInType == XML_SCHEMAS_STRING) &&
17923 (ctxt->nodeInfo != NULL) &&
17924 (ctxt->nodeInfo->flags & XML_SCHEMA_ELEM_INFO_VALUE_NEEDED)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017925 xmlChar *valdup;
17926 /*
17927 * Create a precomputed string value for "string" as well if
17928 * requested.
17929 */
17930 valdup = xmlStrdup(value);
17931 ctxt->value = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
17932 BAD_CAST valdup);
17933 if ((valdup != NULL) && (ctxt->value == NULL))
17934 xmlFree(valdup);
Daniel Veillard01fa6152004-06-29 17:04:39 +000017935 }
17936 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
17937 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
17938 * a literal in the ·lexical space· of {base type definition}
17939 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017940 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000017941 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017942 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017943 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000017944 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000017945 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017946 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000017947 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017948 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017949 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017950 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000017951 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017952 * Check facets.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017953 */
17954 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017955 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000017956 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017957 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017958 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000017959 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000017960 type->name, NULL);
17961 } else if (ret > 0) {
17962 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017963 /*
17964 Disabled, since the facet validation already reports errors.
17965 if (fireErrors)
17966 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
17967 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017968 }
17969 }
17970 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
17971
17972 xmlSchemaTypePtr tmpType;
17973 const xmlChar *cur, *end;
17974 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017975 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000017976
17977 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
17978 * of white space separated tokens, each of which ·match·es a literal
17979 * in the ·lexical space· of {item type definition}
17980 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000017981
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000017982 if (value == NULL)
17983 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000017984 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000017985 cur = value;
17986 do {
17987 while (IS_BLANK_CH(*cur))
17988 cur++;
17989 end = cur;
17990 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
17991 end++;
17992 if (end == cur)
17993 break;
17994 tmp = xmlStrndup(cur, end - cur);
17995 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017996 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000017997 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017998 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017999 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018000 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18001 "validating an item of list simple type '%s'\n",
18002 type->name, NULL);
18003 break;
18004 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018005 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018006 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018007 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018008 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018009 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018010 cur = end;
18011 } while (*cur != 0);
18012 /*
18013 * Check facets.
18014 */
18015 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018016 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018017 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018018 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018019 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018020 } else if ((ret == 0) && (applyFacets)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018021 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018022 value, len, fireErrors);
18023 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018024 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018025 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18026 "validating facets of list simple type '%s'\n",
18027 type->name, NULL);
18028 } else if (ret > 0) {
18029 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018030 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000018031 Disabled, since the facet validation already reports errors.
18032 if (fireErrors)
18033 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018034 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018035 }
18036
Daniel Veillard01fa6152004-06-29 17:04:39 +000018037 }
18038 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
18039 xmlSchemaTypeLinkPtr memberLink;
18040
18041 /*
18042 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
18043 * not apply directly; however, the normalization behavior of ·union·
18044 * types is controlled by the value of whiteSpace on that one of the
18045 * ·memberTypes· against which the ·union· is successfully validated.
18046 *
18047 * This means that the value is normalized by the first validating
18048 * member type, then the facets of the union type are applied. This
18049 * needs changing of the value!
18050 */
18051
18052 /*
18053 * 1.2.3 if {variety} is ·union· then the string must ·match· a
18054 * literal in the ·lexical space· of at least one member of
18055 * {member type definitions}
18056 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018057#ifdef DEBUG_UNION_VALIDATION
18058 printf("Union ST : '%s'\n", (const char *) type->name);
18059 printf(" fireErrors : %d\n", fireErrors);
18060 printf(" applyFacets: %d\n", applyFacets);
18061#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000018062 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
18063 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018064 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018065 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018066 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018067 type->name, NULL);
18068 ret = -1;
18069 }
18070 if (ret == 0) {
18071 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018072 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
18073 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018074 if ((ret <= 0) || (ret == 0))
18075 break;
18076 memberLink = memberLink->next;
18077 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018078 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018079 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018080 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018081 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000018082 type->name, NULL);
18083 } else if (ret > 0) {
18084 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018085 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018086 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018087 }
18088 }
18089 /*
18090 * Apply facets (pattern, enumeration).
18091 */
18092 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
18093 int mws;
18094 /*
18095 * The normalization behavior of ·union· types is controlled by
18096 * the value of whiteSpace on that one of the ·memberTypes·
18097 * against which the ·union· is successfully validated.
18098 */
18099 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018100 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018101 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18102 "the value was already normalized for the union simple "
18103 "type '%s'.\n", type->name, NULL);
18104 }
18105 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
18106 if (mws > ctxt->valueWS) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018107 if (mws == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018108 normValue = xmlSchemaCollapseString(value);
18109 else
18110 normValue = xmlSchemaWhiteSpaceReplace(value);
18111 if (normValue != NULL)
18112 value = (const xmlChar *) normValue;
18113 }
18114
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018115 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018116 value, 0, fireErrors);
18117 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018118 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018119 "Internal error: xmlSchemaValidateSimpleTypeValue, "
18120 "validating facets of union simple type '%s'\n",
18121 type->name, NULL);
18122 } else if (ret > 0) {
18123 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
18124 /*
18125 if (fireErrors)
18126 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
18127 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018128 }
18129 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018130 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018131 ctxt->valueWS = wtsp;
18132 if (normValue != NULL)
18133 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018134 return (ret);
18135}
18136
18137/**
18138 * xmlSchemaValidateSimpleTypeElement:
18139 * @ctxt: a schema validation context
18140 * @node: the element node to be validated.
18141 *
18142 * Validate the element against a simple type.
18143 *
18144 * Returns 0 if the element is valid, a positive error code
18145 * number otherwise and -1 in case of an internal or API error.
18146 */
18147static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018148xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018149 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018150 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018151 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000018152{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018153 xmlSchemaTypePtr oldtype;
18154 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018155 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018156 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018157 int ret = 0, retval = 0;
18158
Daniel Veillard01fa6152004-06-29 17:04:39 +000018159 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018160 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
18161 "Internal error: xmlSchemaValidateElementBySimpleType, "
18162 "bad arguments", NULL);
18163 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018164 }
18165
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018166 oldtype = ctxt->type;
18167 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018168 /*
18169 * cvc-type: 3.1.2 The element information item must have no element
18170 * information item [children].
18171 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018172 /*
18173 * STREAM: Child nodes are processed.
18174 */
18175 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018176 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018177 /*
18178 * TODO: Entities, will they produce elements as well?
18179 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018180 if (cur->type == XML_ELEMENT_NODE) {
18181 xmlSchemaVCustomErr(ctxt,
18182 XML_SCHEMAV_CVC_TYPE_3_1_2,
18183 node, type,
18184 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018185 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018186 }
18187 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018188 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018189
Daniel Veillard01fa6152004-06-29 17:04:39 +000018190 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018191 * cvc-type 3.1.1:
18192 *
18193 * The attributes of must be empty, excepting those whose namespace name
18194 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
18195 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018196 */
18197 /*
18198 * STREAM: Attribute nodes are processed.
18199 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018200 attr = node->properties;
18201 while (attr != NULL) {
18202 if ((attr->ns == NULL) ||
18203 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
18204 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
18205 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
18206 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
18207 (!xmlStrEqual
18208 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018209 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018210 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
18211 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018212 }
18213 attr = attr->next;
18214 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018215 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018216 * This will skip validation if the type is 'anySimpleType' and
18217 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018218 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018219 if ((! isNil) &&
18220 (valSimpleContent == 1) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018221 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
18222 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018223 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018224
18225 value = xmlNodeGetContent(node);
18226 /*
18227 * NOTE: This call will not check the content nodes, since
18228 * this should be checked here already.
18229 */
18230 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
18231 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000018232 if (value != NULL)
18233 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018234 if (retval != 0)
18235 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000018236 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018237 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018238 return (ret);
18239}
Daniel Veillard4255d502002-04-16 15:50:10 +000018240
18241/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018242 * xmlSchemaValQNameAcquire:
18243 * @value: the lexical represantation of the QName value
18244 * @node: the node to search for the corresponding namespace declaration
18245 * @nsName: the resulting namespace name if found
18246 *
18247 * Checks that a value conforms to the lexical space of the type QName;
18248 * if valid, the corresponding namespace name is searched and retured
18249 * as a copy in @nsName. The local name is returned in @localName as
18250 * a copy.
18251 *
18252 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
18253 * namespace declaration was found in scope; -1 in case of an internal or
18254 * API error.
18255 */
18256static int
18257xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
18258 xmlChar **nsName, xmlChar **localName)
18259{
18260 int ret;
18261 xmlChar *local = NULL;
18262
18263 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
18264 return (-1);
18265 *nsName = NULL;
18266 *localName = NULL;
18267 ret = xmlValidateQName(value, 1);
18268 if (ret == 0) {
18269 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018270 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018271
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018272 /*
18273 * NOTE: xmlSplitQName2 will return a duplicated
18274 * string.
18275 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018276 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018277 if (local == NULL)
18278 local = xmlStrdup(value);
18279 ns = xmlSearchNs(node->doc, node, prefix);
18280 /*
18281 * A namespace need not to be found if the prefix is NULL.
18282 */
18283 if (ns != NULL) {
18284 /*
18285 * TODO: Is it necessary to duplicate the URI here?
18286 */
18287 *nsName = xmlStrdup(ns->href);
18288 } else if (prefix != NULL) {
18289 xmlFree(prefix);
18290 if (local != NULL)
18291 xmlFree(local);
18292 return (2);
18293 }
18294 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018295 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018296 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018297 } else
18298 return (1);
18299 return (ret);
18300}
18301
18302/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018303 * xmlSchemaHasElemContent:
18304 * @node: the node
18305 *
18306 * Scours the content of the given node for element
18307 * nodes.
18308 *
18309 * Returns 1 if an element node is found,
18310 * 0 otherwise.
18311 */
18312static int
18313xmlSchemaHasElemContent(xmlNodePtr node)
18314{
18315 if (node == NULL)
18316 return (0);
18317 node = node->children;
18318 while (node != NULL) {
18319 if (node->type == XML_ELEMENT_NODE)
18320 return (1);
18321 node = node->next;
18322 }
18323 return (0);
18324}
18325/**
18326 * xmlSchemaHasElemOrCharContent:
18327 * @node: the node
18328 *
18329 * Scours the content of the given node for element
18330 * and character nodes.
18331 *
18332 * Returns 1 if an element or character node is found,
18333 * 0 otherwise.
18334 */
18335static int
18336xmlSchemaHasElemOrCharContent(xmlNodePtr node)
18337{
18338 if (node == NULL)
18339 return (0);
18340 node = node->children;
18341 while (node != NULL) {
18342 switch (node->type) {
18343 case XML_ELEMENT_NODE:
18344 /*
18345 * TODO: Ask Daniel if these are all character nodes.
18346 */
18347 case XML_TEXT_NODE:
18348 case XML_CDATA_SECTION_NODE:
18349 /*
18350 * TODO: How XML_ENTITY_NODEs evaluated?
18351 */
18352 case XML_ENTITY_REF_NODE:
18353 case XML_ENTITY_NODE:
18354 return (1);
18355 break;
18356 default:
18357 break;
18358 }
18359 node = node->next;
18360 }
18361 return (0);
18362}
18363
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018364/************************************************************************
18365 * *
18366 * Identity-constraints (IDC) *
18367 * *
18368 ************************************************************************/
18369
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018370/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018371 * xmlSchemaAugmentIDC:
18372 * @idcDef: the IDC definition
18373 *
18374 * Creates an augmented IDC definition item.
18375 *
18376 * Returns the item, or NULL on internal errors.
18377 */
18378static void
18379xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18380 xmlSchemaValidCtxtPtr vctxt)
18381{
18382 xmlSchemaIDCAugPtr aidc;
18383
18384 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18385 if (aidc == NULL) {
18386 xmlSchemaVErrMemory(vctxt,
18387 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18388 NULL);
18389 return;
18390 }
18391 aidc->bubbleDepth = -1;
18392 aidc->def = idcDef;
18393 aidc->next = NULL;
18394 if (vctxt->aidcs == NULL)
18395 vctxt->aidcs = aidc;
18396 else {
18397 aidc->next = vctxt->aidcs;
18398 vctxt->aidcs = aidc;
18399 }
18400}
18401
18402/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018403 * xmlSchemaIDCNewBinding:
18404 * @idcDef: the IDC definition of this binding
18405 *
18406 * Creates a new IDC binding.
18407 *
18408 * Returns the new binding in case of succeeded, NULL on internal errors.
18409 */
18410static xmlSchemaPSVIIDCBindingPtr
18411xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18412{
18413 xmlSchemaPSVIIDCBindingPtr ret;
18414
18415 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18416 sizeof(xmlSchemaPSVIIDCBinding));
18417 if (ret == NULL) {
18418 xmlSchemaVErrMemory(NULL,
18419 "allocating a PSVI IDC binding item", NULL);
18420 return (NULL);
18421 }
18422 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18423 ret->definition = idcDef;
18424 return (ret);
18425}
18426
18427/**
18428 * xmlSchemaIDCStoreNodeTableItem:
18429 * @vctxt: the WXS validation context
18430 * @item: the IDC node table item
18431 *
18432 * The validation context is used to store an IDC node table items.
18433 * They are stored to avoid copying them if IDC node-tables are merged
18434 * with corresponding parent IDC node-tables (bubbling).
18435 *
18436 * Returns 0 if succeeded, -1 on internal errors.
18437 */
18438static int
18439xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
18440 xmlSchemaPSVIIDCNodePtr item)
18441{
18442 /*
18443 * Add to gobal list.
18444 */
18445 if (vctxt->idcNodes == NULL) {
18446 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18447 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18448 if (vctxt->idcNodes == NULL) {
18449 xmlSchemaVErrMemory(vctxt,
18450 "allocating the IDC node table item list", NULL);
18451 return (-1);
18452 }
18453 vctxt->sizeIdcNodes = 20;
18454 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18455 vctxt->sizeIdcNodes *= 2;
18456 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18457 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
18458 sizeof(xmlSchemaPSVIIDCNodePtr));
18459 if (vctxt->idcNodes == NULL) {
18460 xmlSchemaVErrMemory(vctxt,
18461 "re-allocating the IDC node table item list", NULL);
18462 return (-1);
18463 }
18464 }
18465 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
18466
18467 return (0);
18468}
18469
18470/**
18471 * xmlSchemaIDCStoreKey:
18472 * @vctxt: the WXS validation context
18473 * @item: the IDC key
18474 *
18475 * The validation context is used to store an IDC key.
18476 *
18477 * Returns 0 if succeeded, -1 on internal errors.
18478 */
18479static int
18480xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
18481 xmlSchemaPSVIIDCKeyPtr key)
18482{
18483 /*
18484 * Add to gobal list.
18485 */
18486 if (vctxt->idcKeys == NULL) {
18487 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18488 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18489 if (vctxt->idcKeys == NULL) {
18490 xmlSchemaVErrMemory(vctxt,
18491 "allocating the IDC key storage list", NULL);
18492 return (-1);
18493 }
18494 vctxt->sizeIdcKeys = 40;
18495 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18496 vctxt->sizeIdcKeys *= 2;
18497 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18498 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
18499 sizeof(xmlSchemaPSVIIDCKeyPtr));
18500 if (vctxt->idcKeys == NULL) {
18501 xmlSchemaVErrMemory(vctxt,
18502 "re-allocating the IDC key storage list", NULL);
18503 return (-1);
18504 }
18505 }
18506 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
18507
18508 return (0);
18509}
18510
18511/**
18512 * xmlSchemaIDCAppendNodeTableItem:
18513 * @bind: the IDC binding
18514 * @ntItem: the node-table item
18515 *
18516 * Appends the IDC node-table item to the binding.
18517 *
18518 * Returns 0 on success and -1 on internal errors.
18519 */
18520static int
18521xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
18522 xmlSchemaPSVIIDCNodePtr ntItem)
18523{
18524 if (bind->nodeTable == NULL) {
18525 bind->sizeNodes = 10;
18526 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18527 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
18528 if (bind->nodeTable == NULL) {
18529 xmlSchemaVErrMemory(NULL,
18530 "allocating an array of IDC node-table items", NULL);
18531 return(-1);
18532 }
18533 } else if (bind->sizeNodes <= bind->nbNodes) {
18534 bind->sizeNodes *= 2;
18535 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18536 xmlRealloc(bind->nodeTable, bind->sizeNodes *
18537 sizeof(xmlSchemaPSVIIDCNodePtr));
18538 if (bind->nodeTable == NULL) {
18539 xmlSchemaVErrMemory(NULL,
18540 "re-allocating an array of IDC node-table items", NULL);
18541 return(-1);
18542 }
18543 }
18544 bind->nodeTable[bind->nbNodes++] = ntItem;
18545 return(0);
18546}
18547
18548/**
18549 * xmlSchemaIDCAquireBinding:
18550 * @vctxt: the WXS validation context
18551 * @matcher: the IDC matcher
18552 *
18553 * Looks up an PSVI IDC binding, for the IDC definition and
18554 * of the given matcher. If none found, a new one is created
18555 * and added to the IDC table.
18556 *
18557 * Returns an IDC binding or NULL on internal errors.
18558 */
18559static xmlSchemaPSVIIDCBindingPtr
18560xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
18561 xmlSchemaIDCMatcherPtr matcher)
18562{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018563 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018564
18565 info = vctxt->elemInfos[matcher->depth];
18566
18567 if (info->idcTable == NULL) {
18568 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
18569 if (info->idcTable == NULL)
18570 return (NULL);
18571 return(info->idcTable);
18572 } else {
18573 xmlSchemaPSVIIDCBindingPtr bind = NULL;
18574
18575 bind = info->idcTable;
18576 do {
18577 if (bind->definition == matcher->aidc->def)
18578 return(bind);
18579 if (bind->next == NULL) {
18580 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
18581 if (bind->next == NULL)
18582 return (NULL);
18583 return(bind->next);
18584 }
18585 bind = bind->next;
18586 } while (bind != NULL);
18587 }
18588 return (NULL);
18589}
18590
18591/**
18592 * xmlSchemaIDCFreeKey:
18593 * @key: the IDC key
18594 *
18595 * Frees an IDC key together with its compiled value.
18596 */
18597static void
18598xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
18599{
18600 if (key->compValue != NULL)
18601 xmlSchemaFreeValue(key->compValue);
18602 xmlFree(key);
18603}
18604
18605/**
18606 * xmlSchemaIDCFreeBinding:
18607 *
18608 * Frees an IDC binding. Note that the node table-items
18609 * are not freed.
18610 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018611static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018612xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
18613{
18614 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018615 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18616 int i;
18617 /*
18618 * Node-table items for keyrefs are not stored globally
18619 * to the validation context, since they are not bubbled.
18620 * We need to free them here.
18621 */
18622 for (i = 0; i < bind->nbNodes; i++) {
18623 xmlFree(bind->nodeTable[i]->keys);
18624 xmlFree(bind->nodeTable[i]);
18625 }
18626 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018627 xmlFree(bind->nodeTable);
18628 }
18629 xmlFree(bind);
18630}
18631
18632/**
18633 * xmlSchemaIDCFreeIDCTable:
18634 * @bind: the first IDC binding in the list
18635 *
18636 * Frees an IDC table, i.e. all the IDC bindings in the list.
18637 */
18638static void
18639xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
18640{
18641 xmlSchemaPSVIIDCBindingPtr prev;
18642
18643 while (bind != NULL) {
18644 prev = bind;
18645 bind = bind->next;
18646 xmlSchemaIDCFreeBinding(prev);
18647 }
18648}
18649
18650/**
18651 * xmlSchemaIDCFreeMatcherList:
18652 * @matcher: the first IDC matcher in the list
18653 *
18654 * Frees a list of IDC matchers.
18655 */
18656static void
18657xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
18658{
18659 xmlSchemaIDCMatcherPtr next;
18660
18661 while (matcher != NULL) {
18662 next = matcher->next;
18663 if (matcher->keySeqs != NULL) {
18664 int i;
18665 for (i = 0; i < matcher->sizeKeySeqs; i++)
18666 if (matcher->keySeqs[i] != NULL)
18667 xmlFree(matcher->keySeqs[i]);
18668 xmlFree(matcher->keySeqs);
18669 }
18670 xmlFree(matcher);
18671 matcher = next;
18672 }
18673}
18674
18675/**
18676 * xmlSchemaAreValuesEqual:
18677 * @ta: the first type
18678 * @a: the first value
18679 * @tb: the second type
18680 * @b: the second value
18681 *
18682 * Compares two values.
18683 *
18684 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
18685 */
18686static int
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018687xmlSchemaAreValuesEqual(xmlSchemaValidCtxtPtr vctxt,
18688 xmlSchemaTypePtr ta,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018689 xmlSchemaValPtr a,
18690 xmlSchemaTypePtr tb,
18691 xmlSchemaValPtr b)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018692{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018693 /* Same user derived/built-in derived/built-in primitive types. */
18694 if (ta == tb)
18695 goto compareValue;
18696
18697 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018698 * Note that comparison with anySimpleTypes with be supported for
18699 * string based types as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018700 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018701#if 0
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018702 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
18703 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
18704 return(0);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018705#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018706
18707 /*
18708 * 4.2.1 equal (data-types)
18709 *
18710 * the ·value space·s of all ·primitive· datatypes are disjoint
18711 * (they do not share any values)
18712 */
18713 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
18714 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
18715 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
18716 return(0);
18717
18718 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
18719 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
18720 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
18721 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
18722 TODO
18723 return(0);
18724 }
18725 /*
18726 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
18727 * T then the ·value space· of T' is a subset of the ·value space· of T.
18728 */
18729 /*
18730 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
18731 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
18732 */
18733
18734 {
18735 xmlSchemaTypePtr pta = ta, ptb = tb;
18736
18737 /* Note that we will compare the primitives here. */
18738 while ((pta->builtInType == 0) ||
18739 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
18740 pta = pta->baseType;
18741 while ((ptb->builtInType == 0) ||
18742 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
18743 ptb = ptb->baseType;
18744 if (pta == ptb)
18745 goto compareValue;
18746 return(0);
18747 }
18748compareValue:
18749 {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018750 int ret;
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018751 int aws, bws;
18752
18753 aws = xmlSchemaGetWhiteSpaceFacetValue(ta);
18754 bws = xmlSchemaGetWhiteSpaceFacetValue(tb);
18755
18756 ret = xmlSchemaCompareValuesWhtsp(
18757 a, (xmlSchemaWhitespaceValueType) aws,
18758 b, (xmlSchemaWhitespaceValueType) bws);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018759 if (ret == 0)
18760 return(1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018761 else if (ret == -2) {
18762 xmlSchemaVErr(vctxt, vctxt->node,
18763 XML_SCHEMAV_INTERNAL,
18764 "Internal error: xmlSchemaAreValuesEqual, "
18765 "failed to compare the values.\n",
18766 NULL, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018767 return(-1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018768 } else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018769 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018770 }
18771}
18772
18773/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018774 * xmlSchemaIDCAddStateObject:
18775 * @vctxt: the WXS validation context
18776 * @matcher: the IDC matcher
18777 * @sel: the XPath information
18778 * @parent: the parent "selector" state object if any
18779 * @type: "selector" or "field"
18780 *
18781 * Creates/reuses and activates state objects for the given
18782 * XPath information; if the XPath expression consists of unions,
18783 * multiple state objects are created for every unioned expression.
18784 *
18785 * Returns 0 on success and -1 on internal errors.
18786 */
18787static int
18788xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
18789 xmlSchemaIDCMatcherPtr matcher,
18790 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018791 int type)
18792{
18793 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018794
18795 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018796 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018797 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018798 if (vctxt->xpathStatePool != NULL) {
18799 sto = vctxt->xpathStatePool;
18800 vctxt->xpathStatePool = sto->next;
18801 sto->next = NULL;
18802 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018803 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018804 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018805 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018806 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
18807 if (sto == NULL) {
18808 xmlSchemaVErrMemory(NULL,
18809 "allocating an IDC state object", NULL);
18810 return (-1);
18811 }
18812 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
18813 }
18814 /*
18815 * Add to global list.
18816 */
18817 if (vctxt->xpathStates != NULL)
18818 sto->next = vctxt->xpathStates;
18819 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018820
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018821 /*
18822 * Free the old xpath validation context.
18823 */
18824 if (sto->xpathCtxt != NULL)
18825 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
18826
18827 /*
18828 * Create a new XPath (pattern) validation context.
18829 */
18830 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
18831 (xmlPatternPtr) sel->xpathComp);
18832 if (sto->xpathCtxt == NULL) {
18833 xmlSchemaVErr(vctxt, vctxt->node,
18834 XML_SCHEMAV_INTERNAL,
18835 "Internal error: xmlSchemaIDCAddStateObject, "
18836 "failed to create the XPath validation context.\n",
18837 NULL, NULL);
18838 return (-1);
18839 }
18840 sto->type = type;
18841 sto->depth = vctxt->depth;
18842 sto->matcher = matcher;
18843 sto->sel = sel;
18844 sto->nbHistory = 0;
18845
18846#if DEBUG_IDC
18847 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
18848 sto->sel->xpath);
18849#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018850 return (0);
18851}
18852
18853/**
18854 * xmlSchemaXPathEvaluate:
18855 * @vctxt: the WXS validation context
18856 * @nodeType: the nodeType of the current node
18857 *
18858 * Evaluates all active XPath state objects.
18859 *
18860 * Returns the number of IC "field" state objects which resolved to
18861 * this node, 0 if none resolved and -1 on internal errors.
18862 */
18863static int
18864xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018865 xmlElementType nodeType)
18866{
18867 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018868 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018869
18870 if (vctxt->xpathStates == NULL)
18871 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018872
18873 if (nodeType == XML_ATTRIBUTE_NODE)
18874 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018875#if DEBUG_IDC
18876 {
18877 xmlChar *str = NULL;
18878 xmlGenericError(xmlGenericErrorContext,
18879 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018880 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
18881 vctxt->nodeInfo->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018882 FREE_AND_NULL(str)
18883 }
18884#endif
18885 /*
18886 * Process all active XPath state objects.
18887 */
18888 first = vctxt->xpathStates;
18889 sto = first;
18890 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018891#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018892 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018893 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
18894 sto->matcher->aidc->def->name, sto->sel->xpath);
18895 else
18896 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
18897 sto->matcher->aidc->def->name, sto->sel->xpath);
18898#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018899 if (nodeType == XML_ELEMENT_NODE)
18900 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
18901 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
18902 else
18903 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
18904 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
18905
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018906 if (res == -1) {
18907 xmlSchemaVErr(vctxt, vctxt->node,
18908 XML_SCHEMAV_INTERNAL,
18909 "Internal error: xmlSchemaXPathEvaluate, "
18910 "failed to evaluate a node.\n",
18911 NULL, NULL);
18912 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018913 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018914 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018915 goto next_sto;
18916 /*
18917 * Full match.
18918 */
18919#if DEBUG_IDC
18920 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018921 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018922#endif
18923 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018924 * Register a match in the state object history.
18925 */
18926 if (sto->history == NULL) {
18927 sto->history = (int *) xmlMalloc(5 * sizeof(int));
18928 if (sto->history == NULL) {
18929 xmlSchemaVErrMemory(NULL,
18930 "allocating the state object history", NULL);
18931 return(-1);
18932 }
18933 sto->sizeHistory = 10;
18934 } else if (sto->sizeHistory <= sto->nbHistory) {
18935 sto->sizeHistory *= 2;
18936 sto->history = (int *) xmlRealloc(sto->history,
18937 sto->sizeHistory * sizeof(int));
18938 if (sto->history == NULL) {
18939 xmlSchemaVErrMemory(NULL,
18940 "re-allocating the state object history", NULL);
18941 return(-1);
18942 }
18943 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018944 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018945
18946#ifdef DEBUG_IDC
18947 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
18948 vctxt->depth);
18949#endif
18950
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018951 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
18952 xmlSchemaIDCSelectPtr sel;
18953 /*
18954 * Activate state objects for the IDC fields of
18955 * the IDC selector.
18956 */
18957#if DEBUG_IDC
18958 xmlGenericError(xmlGenericErrorContext, "IDC: "
18959 "activating field states\n");
18960#endif
18961 sel = sto->matcher->aidc->def->fields;
18962 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018963 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
18964 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
18965 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018966 sel = sel->next;
18967 }
18968 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
18969 /*
18970 * An IDC key node was found.
18971 */
18972#if DEBUG_IDC
18973 xmlGenericError(xmlGenericErrorContext,
18974 "IDC: key found\n");
18975#endif
18976 /*
18977 * Notify that the character value of this node is
18978 * needed.
18979 */
18980 if (resolved == 0)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018981 vctxt->nodeInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018982 resolved++;
18983 }
18984next_sto:
18985 if (sto->next == NULL) {
18986 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018987 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018988 */
18989 head = first;
18990 sto = vctxt->xpathStates;
18991 } else
18992 sto = sto->next;
18993 }
18994 return (resolved);
18995}
18996
18997/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018998 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018999 * @vctxt: the WXS validation context
19000 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019001 * @compValue: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019002 *
19003 * Processes and pops the history items of the IDC state objects.
19004 * IDC key-sequences are validated/created on IDC bindings.
19005 *
19006 * Returns 0 on success and -1 on internal errors.
19007 */
19008static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019009xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019010 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019011{
19012 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019013 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019014 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019015 xmlSchemaTypePtr type = vctxt->nodeInfo->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019016
19017 if (vctxt->xpathStates == NULL)
19018 return (0);
19019 sto = vctxt->xpathStates;
19020
19021#if DEBUG_IDC
19022 {
19023 xmlChar *str = NULL;
19024 xmlGenericError(xmlGenericErrorContext,
19025 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019026 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
19027 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019028 FREE_AND_NULL(str)
19029 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019030#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019031 /*
19032 * Evaluate the state objects.
19033 */
19034 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019035 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019036#if DEBUG_IDC
19037 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19038 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019039#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019040 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019041 goto deregister_check;
19042
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019043 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019044
19045 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019046 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019047 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019048 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019049 sto = sto->next;
19050 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019051 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019052 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19053 if (! IS_SIMPLE_TYPE(type)) {
19054 /*
19055 * Not qualified if the field resolves to a node of non
19056 * simple type.
19057 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019058 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019059 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019060 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019061 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19062 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019063 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019064
19065 sto->nbHistory--;
19066 goto deregister_check;
19067 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019068 if ((key == NULL) && (vctxt->nodeInfo->value == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019069 /*
19070 * Failed to provide the normalized value; maby
19071 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019072 */
19073 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019074 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019075 vctxt->nodeInfo,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019076 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19077 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019078 "was either invalid or something strange happend",
19079 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019080 /*
19081 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019082 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019083 "Internal error: xmlSchemaXPathProcessHistory, "
19084 "computed value not available.\n",
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019085 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019086 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019087 sto->nbHistory--;
19088 goto deregister_check;
19089 } else {
19090 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19091 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019092 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019093
19094 /*
19095 * The key will be anchored on the matcher's list of
19096 * key-sequences. The position in this list is determined
19097 * by the target node's depth relative to the matcher's
19098 * depth of creation (i.e. the depth of the scope element).
19099 */
19100 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019101 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019102
19103 /*
19104 * Create/grow the array of key-sequences.
19105 */
19106 if (matcher->keySeqs == NULL) {
19107 if (pos > 9)
19108 matcher->sizeKeySeqs = pos * 2;
19109 else
19110 matcher->sizeKeySeqs = 10;
19111 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19112 xmlMalloc(matcher->sizeKeySeqs *
19113 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19114 if (matcher->keySeqs == NULL) {
19115 xmlSchemaVErrMemory(NULL,
19116 "allocating an array of key-sequences",
19117 NULL);
19118 return(-1);
19119 }
19120 memset(matcher->keySeqs, 0,
19121 matcher->sizeKeySeqs *
19122 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19123 } else if (pos >= matcher->sizeKeySeqs) {
19124 int i = matcher->sizeKeySeqs;
19125
19126 matcher->sizeKeySeqs *= 2;
19127 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19128 xmlRealloc(matcher->keySeqs,
19129 matcher->sizeKeySeqs *
19130 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019131 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019132 xmlSchemaVErrMemory(NULL,
19133 "reallocating an array of key-sequences",
19134 NULL);
19135 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019136 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019137 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019138 * The array needs to be NULLed.
19139 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019140 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019141 for (; i < matcher->sizeKeySeqs; i++)
19142 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019143 }
19144
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019145 /*
19146 * Get/create the key-sequence.
19147 */
19148 keySeq = matcher->keySeqs[pos];
19149 if (keySeq == NULL) {
19150 goto create_sequence;
19151 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019152 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019153 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019154 * cvc-identity-constraint:
19155 * 3 For each node in the ·target node set· all
19156 * of the {fields}, with that node as the context
19157 * node, evaluate to either an empty node-set or
19158 * a node-set with exactly one member, which must
19159 * have a simple type.
19160 *
19161 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019162 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019163 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019164 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019165 vctxt->nodeInfo,
19166 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019167 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019168 "with more than one member",
19169 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019170 sto->nbHistory--;
19171 goto deregister_check;
19172 } else {
19173 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019174 }
19175 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019176
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019177create_sequence:
19178 /*
19179 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019180 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019181 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19182 matcher->aidc->def->nbFields *
19183 sizeof(xmlSchemaPSVIIDCKeyPtr));
19184 if (keySeq == NULL) {
19185 xmlSchemaVErrMemory(NULL,
19186 "allocating an IDC key-sequence", NULL);
19187 return(-1);
19188 }
19189 memset(keySeq, 0, matcher->aidc->def->nbFields *
19190 sizeof(xmlSchemaPSVIIDCKeyPtr));
19191 matcher->keySeqs[pos] = keySeq;
19192create_key:
19193 /*
19194 * Created a key once per node only.
19195 */
19196 if (key == NULL) {
19197 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19198 sizeof(xmlSchemaPSVIIDCKey));
19199 if (key == NULL) {
19200 xmlSchemaVErrMemory(NULL,
19201 "allocating a IDC key", NULL);
19202 xmlFree(keySeq);
19203 matcher->keySeqs[pos] = NULL;
19204 return(-1);
19205 }
19206 /*
19207 * Consume the compiled value.
19208 */
19209 key->type = type;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019210 key->compValue = vctxt->nodeInfo->value;
19211 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019212 /*
19213 * Store the key in a global list.
19214 */
19215 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19216 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019217 return (-1);
19218 }
19219 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019220 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019221 }
19222 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019223
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019224 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19225 xmlSchemaPSVIIDCBindingPtr bind;
19226 xmlSchemaPSVIIDCNodePtr ntItem;
19227 xmlSchemaIDCMatcherPtr matcher;
19228 xmlSchemaIDCPtr idc;
19229 int pos, i, j, nbKeys;
19230 /*
19231 * Here we have the following scenario:
19232 * An IDC 'selector' state object resolved to a target node,
19233 * during the time this target node was in the
19234 * ancestor-or-self axis, the 'field' state object(s) looked
19235 * out for matching nodes to create a key-sequence for this
19236 * target node. Now we are back to this target node and need
19237 * to put the key-sequence, together with the target node
19238 * itself, into the node-table of the corresponding IDC
19239 * binding.
19240 */
19241 matcher = sto->matcher;
19242 idc = matcher->aidc->def;
19243 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019244 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019245 /*
19246 * Check if the matcher has any key-sequences at all, plus
19247 * if it has a key-sequence for the current target node.
19248 */
19249 if ((matcher->keySeqs == NULL) ||
19250 (matcher->sizeKeySeqs <= pos)) {
19251 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19252 goto selector_key_error;
19253 else
19254 goto selector_leave;
19255 }
19256
19257 keySeq = &(matcher->keySeqs[pos]);
19258 if (*keySeq == NULL) {
19259 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19260 goto selector_key_error;
19261 else
19262 goto selector_leave;
19263 }
19264
19265 for (i = 0; i < nbKeys; i++) {
19266 if ((*keySeq)[i] == NULL) {
19267 /*
19268 * Not qualified, if not all fields did resolve.
19269 */
19270 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19271 /*
19272 * All fields of a "key" IDC must resolve.
19273 */
19274 goto selector_key_error;
19275 }
19276 goto selector_leave;
19277 }
19278 }
19279 /*
19280 * All fields did resolve.
19281 */
19282
19283 /*
19284 * 4.1 If the {identity-constraint category} is unique(/key),
19285 * then no two members of the ·qualified node set· have
19286 * ·key-sequences· whose members are pairwise equal, as
19287 * defined by Equal in [XML Schemas: Datatypes].
19288 *
19289 * Get the IDC binding from the matcher and check for
19290 * duplicate key-sequences.
19291 */
19292 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19293 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19294 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019295 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019296
19297 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019298 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019299 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019300 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019301 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019302 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019303 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019304 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019305 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019306 bkey = bkeySeq[j];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019307 res = xmlSchemaAreValuesEqual(vctxt, ckey->type,
19308 ckey->compValue, bkey->type, bkey->compValue);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019309 if (res == -1) {
19310 return (-1);
19311 } else if (res == 0)
19312 break;
19313 }
19314 if (res == 1) {
19315 /*
19316 * Duplicate found.
19317 */
19318 break;
19319 }
19320 i++;
19321 } while (i < bind->nbNodes);
19322 if (i != bind->nbNodes) {
19323 /*
19324 * TODO: Try to report the key-sequence.
19325 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019326 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019327 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019328 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019329 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019330 "Duplicate key-sequence found", NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019331
19332 goto selector_leave;
19333 }
19334 }
19335 /*
19336 * Add a node-table item to the IDC binding.
19337 */
19338 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19339 sizeof(xmlSchemaPSVIIDCNode));
19340 if (ntItem == NULL) {
19341 xmlSchemaVErrMemory(NULL,
19342 "allocating an IDC node-table item", NULL);
19343 xmlFree(*keySeq);
19344 *keySeq = NULL;
19345 return(-1);
19346 }
19347 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19348
19349 /*
19350 * Store the node-table item on global list.
19351 */
19352 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19353 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19354 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019355 xmlFree(*keySeq);
19356 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019357 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019358 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019359 }
19360 /*
19361 * Init the node-table item. Consume the key-sequence.
19362 */
19363 ntItem->node = vctxt->node;
19364 ntItem->keys = *keySeq;
19365 *keySeq = NULL;
19366 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19367 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19368 /*
19369 * Free the item, since keyref items won't be
19370 * put on a global list.
19371 */
19372 xmlFree(ntItem->keys);
19373 xmlFree(ntItem);
19374 }
19375 return (-1);
19376 }
19377
19378 goto selector_leave;
19379selector_key_error:
19380 /*
19381 * 4.2.1 (KEY) The ·target node set· and the
19382 * ·qualified node set· are equal, that is, every
19383 * member of the ·target node set· is also a member
19384 * of the ·qualified node set· and vice versa.
19385 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019386 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019387 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019388 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019389 (xmlSchemaTypePtr) idc,
19390 "All 'key' fields must evaluate to a node",
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019391 NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019392selector_leave:
19393 /*
19394 * Free the key-sequence if not added to the IDC table.
19395 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019396 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019397 xmlFree(*keySeq);
19398 *keySeq = NULL;
19399 }
19400 } /* if selector */
19401
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019402 sto->nbHistory--;
19403
19404deregister_check:
19405 /*
19406 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019407 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019408 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019409#if DEBUG_IDC
19410 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19411 sto->sel->xpath);
19412#endif
19413 if (vctxt->xpathStates != sto) {
19414 xmlSchemaVErr(vctxt, vctxt->node,
19415 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019416 "Internal error: xmlSchemaXPathProcessHistory, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019417 "The state object to be removed is not the first "
19418 "in the list.\n",
19419 NULL, NULL);
19420 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019421 nextsto = sto->next;
19422 /*
19423 * Unlink from the list of active XPath state objects.
19424 */
19425 vctxt->xpathStates = sto->next;
19426 sto->next = vctxt->xpathStatePool;
19427 /*
19428 * Link it to the pool of reusable state objects.
19429 */
19430 vctxt->xpathStatePool = sto;
19431 sto = nextsto;
19432 } else
19433 sto = sto->next;
19434 } /* while (sto != NULL) */
19435 return (0);
19436}
19437
19438/**
19439 * xmlSchemaIDCRegisterMatchers:
19440 * @vctxt: the WXS validation context
19441 * @elemDecl: the element declaration
19442 *
19443 * Creates helper objects to evaluate IDC selectors/fields
19444 * successively.
19445 *
19446 * Returns 0 if OK and -1 on internal errors.
19447 */
19448static int
19449xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19450 xmlSchemaElementPtr elemDecl)
19451{
19452 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19453 xmlSchemaIDCPtr idc, refIdc;
19454 xmlSchemaIDCAugPtr aidc;
19455
19456 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19457 if (idc == NULL)
19458 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019459
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019460#if DEBUG_IDC
19461 {
19462 xmlChar *str = NULL;
19463 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019464 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019465 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
19466 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019467 FREE_AND_NULL(str)
19468 }
19469#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019470 if (vctxt->nodeInfo->idcMatchers != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019471 xmlSchemaVErr(vctxt, vctxt->node,
19472 XML_SCHEMAV_INTERNAL,
19473 "Internal error: xmlSchemaIDCRegisterMatchers: "
19474 "The chain of IDC matchers is expected to be empty.\n",
19475 NULL, NULL);
19476 return (-1);
19477 }
19478 do {
19479 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19480 /*
19481 * Since IDCs bubbles are expensive we need to know the
19482 * depth at which the bubbles should stop; this will be
19483 * the depth of the top-most keyref IDC. If no keyref
19484 * references a key/unique IDC, the bubbleDepth will
19485 * be -1, indicating that no bubbles are needed.
19486 */
19487 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19488 if (refIdc != NULL) {
19489 /*
19490 * Lookup the augmented IDC.
19491 */
19492 aidc = vctxt->aidcs;
19493 while (aidc != NULL) {
19494 if (aidc->def == refIdc)
19495 break;
19496 aidc = aidc->next;
19497 }
19498 if (aidc == NULL) {
19499 xmlSchemaVErr(vctxt, vctxt->node,
19500 XML_SCHEMAV_INTERNAL,
19501 "Internal error: xmlSchemaIDCRegisterMatchers: "
19502 "Could not find an augmented IDC item for an IDC "
19503 "definition.\n",
19504 NULL, NULL);
19505 return (-1);
19506 }
19507 if ((aidc->bubbleDepth == -1) ||
19508 (vctxt->depth < aidc->bubbleDepth))
19509 aidc->bubbleDepth = vctxt->depth;
19510 }
19511 }
19512 /*
19513 * Lookup the augmented IDC item for the IDC definition.
19514 */
19515 aidc = vctxt->aidcs;
19516 while (aidc != NULL) {
19517 if (aidc->def == idc)
19518 break;
19519 aidc = aidc->next;
19520 }
19521 if (aidc == NULL) {
19522 xmlSchemaVErr(vctxt, vctxt->node,
19523 XML_SCHEMAV_INTERNAL,
19524 "Internal error: xmlSchemaIDCRegisterMatchers: "
19525 "Could not find an augmented IDC item for an IDC definition.\n",
19526 NULL, NULL);
19527 return (-1);
19528 }
19529 /*
19530 * Create an IDC matcher for every IDC definition.
19531 */
19532 matcher = (xmlSchemaIDCMatcherPtr)
19533 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
19534 if (matcher == NULL) {
19535 xmlSchemaVErrMemory(vctxt,
19536 "allocating an IDC matcher", NULL);
19537 return (-1);
19538 }
19539 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
19540 if (last == NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019541 vctxt->nodeInfo->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019542 else
19543 last->next = matcher;
19544 last = matcher;
19545
19546 matcher->type = IDC_MATCHER;
19547 matcher->depth = vctxt->depth;
19548 matcher->aidc = aidc;
19549#if DEBUG_IDC
19550 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
19551#endif
19552 /*
19553 * Init the automaton state object.
19554 */
19555 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019556 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019557 return (-1);
19558
19559 idc = idc->next;
19560 } while (idc != NULL);
19561 return (0);
19562}
19563
19564/**
19565 * xmlSchemaBubbleIDCNodeTables:
19566 * @depth: the current tree depth
19567 *
19568 * Merges IDC bindings of an element at @depth into the corresponding IDC
19569 * bindings of its parent element. If a duplicate note-table entry is found,
19570 * both, the parent node-table entry and child entry are discarded from the
19571 * node-table of the parent.
19572 *
19573 * Returns 0 if OK and -1 on internal errors.
19574 */
19575static int
19576xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
19577{
19578 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019579 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
19580 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019581 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
19582 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019583 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019584 int duplTop;
19585
19586 /*
19587 * The node table has the following sections:
19588 *
19589 * O --> old node-table entries (first)
19590 * O
19591 * + --> new node-table entries
19592 * +
19593 * % --> new duplicate node-table entries
19594 * %
19595 * # --> old duplicate node-table entries
19596 * # (last)
19597 *
19598 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019599 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019600 if (bind == NULL) {
19601 /* Fine, no table, no bubbles. */
19602 return (0);
19603 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019604
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019605 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
19606 /*
19607 * Walk all bindings; create new or add to existing bindings.
19608 * Remove duplicate key-sequences.
19609 */
19610start_binding:
19611 while (bind != NULL) {
19612 /*
19613 * Skip keyref IDCs.
19614 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019615 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19616 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019617 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019618 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019619 /*
19620 * Check if the key/unique IDC table needs to be bubbled.
19621 */
19622 aidc = vctxt->aidcs;
19623 do {
19624 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019625 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019626 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019627 bind = bind->next;
19628 goto start_binding;
19629 }
19630 break;
19631 }
19632 aidc = aidc->next;
19633 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019634
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019635 if (parTable != NULL)
19636 parBind = *parTable;
19637 while (parBind != NULL) {
19638 /*
19639 * Search a matching parent binding for the
19640 * IDC definition.
19641 */
19642 if (parBind->definition == bind->definition) {
19643
19644 /*
19645 * Compare every node-table entry of the child node,
19646 * i.e. the key-sequence within, ...
19647 */
19648 oldNum = parBind->nbNodes; /* Skip newly added items. */
19649 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019650 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019651
19652 for (i = 0; i < bind->nbNodes; i++) {
19653 node = bind->nodeTable[i];
19654 if (node == NULL)
19655 continue;
19656 /*
19657 * ...with every key-sequence of the parent node, already
19658 * evaluated to be a duplicate key-sequence.
19659 */
19660 if (parBind->nbDupls != 0) {
19661 j = bind->nbNodes + newDupls;
19662 while (j < duplTop) {
19663 parNode = parBind->nodeTable[j];
19664 for (k = 0; k < bind->definition->nbFields; k++) {
19665 key = node->keys[k];
19666 parKey = parNode->keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019667 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019668 key->compValue,
19669 parKey->type, parKey->compValue);
19670 if (ret == -1) {
19671 /* TODO: Internal error */
19672 return(-1);
19673 } else if (ret == 0)
19674 break;
19675
19676 }
19677 if (ret == 1)
19678 /* Duplicate found. */
19679 break;
19680 j++;
19681 }
19682 if (j != duplTop) {
19683 /* Duplicate found. */
19684 continue;
19685 }
19686 }
19687 /*
19688 * ... and with every key-sequence of the parent node.
19689 */
19690 j = 0;
19691 while (j < oldNum) {
19692 parNode = parBind->nodeTable[j];
19693 /*
19694 * Compare key by key.
19695 */
19696 for (k = 0; k < parBind->definition->nbFields; k++) {
19697 key = node->keys[k];
19698 parKey = parNode->keys[k];
19699
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019700 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019701 key->compValue,
19702 parKey->type, parKey->compValue);
19703 if (ret == -1) {
19704 /* TODO: Internal error */
19705 } else if (ret == 0)
19706 break;
19707
19708 }
19709 if (ret == 1)
19710 /*
19711 * The key-sequences are equal.
19712 */
19713 break;
19714 j++;
19715 }
19716 if (j != oldNum) {
19717 /*
19718 * Handle duplicates.
19719 */
19720 newDupls++;
19721 oldNum--;
19722 parBind->nbNodes--;
19723 /*
19724 * Move last old item to pos of duplicate.
19725 */
19726 parBind->nodeTable[j] =
19727 parBind->nodeTable[oldNum];
19728
19729 if (parBind->nbNodes != oldNum) {
19730 /*
19731 * If new items exist, move last new item to
19732 * last of old items.
19733 */
19734 parBind->nodeTable[oldNum] =
19735 parBind->nodeTable[parBind->nbNodes];
19736 }
19737 /*
19738 * Move duplicate to last pos of new/old items.
19739 */
19740 parBind->nodeTable[parBind->nbNodes] = parNode;
19741
19742 } else {
19743 /*
19744 * Add the node-table entry (node and key-sequence) of
19745 * the child node to the node table of the parent node.
19746 */
19747 if (parBind->nodeTable == NULL) {
19748 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019749 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019750 if (parBind->nodeTable == NULL) {
19751 xmlSchemaVErrMemory(NULL,
19752 "allocating IDC list of node-table items", NULL);
19753 return(-1);
19754 }
19755 parBind->sizeNodes = 1;
19756 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019757 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019758 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19759 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
19760 sizeof(xmlSchemaPSVIIDCNodePtr));
19761 if (parBind->nodeTable == NULL) {
19762 xmlSchemaVErrMemory(NULL,
19763 "re-allocating IDC list of node-table items", NULL);
19764 return(-1);
19765 }
19766 }
19767
19768 /*
19769 * Move first old duplicate to last position
19770 * of old duplicates +1.
19771 */
19772 if (parBind->nbDupls != 0) {
19773 parBind->nodeTable[duplTop] =
19774 parBind->nodeTable[parBind->nbNodes + newDupls];
19775 }
19776 /*
19777 * Move first new duplicate to last position of
19778 * new duplicates +1.
19779 */
19780 if (newDupls != 0) {
19781 parBind->nodeTable[parBind->nbNodes + newDupls] =
19782 parBind->nodeTable[parBind->nbNodes];
19783 }
19784 /*
19785 * Append the new node-table entry to the 'new node-table
19786 * entries' section.
19787 */
19788 parBind->nodeTable[parBind->nbNodes] = node;
19789 parBind->nbNodes++;
19790 duplTop++;
19791 }
19792 }
19793 parBind->nbDupls += newDupls;
19794 break;
19795 }
19796 if (parBind->next == NULL)
19797 lastParBind = parBind;
19798 parBind = parBind->next;
19799 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019800 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019801 /*
19802 * No binding for the IDC was found: create a new one and
19803 * copy all node-tables.
19804 */
19805 parBind = xmlSchemaIDCNewBinding(bind->definition);
19806 if (parBind == NULL)
19807 return(-1);
19808
19809 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19810 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
19811 if (parBind->nodeTable == NULL) {
19812 xmlSchemaVErrMemory(NULL,
19813 "allocating an array of IDC node-table items", NULL);
19814 xmlSchemaIDCFreeBinding(parBind);
19815 return(-1);
19816 }
19817 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019818 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019819 memcpy(parBind->nodeTable, bind->nodeTable,
19820 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019821 if (*parTable == NULL)
19822 *parTable = parBind;
19823 else
19824 lastParBind->next = parBind;
19825 }
19826 bind = bind->next;
19827 }
19828 return (0);
19829}
19830
19831/**
19832 * xmlSchemaCheckCVCIDCKeyRef:
19833 * @vctxt: the WXS validation context
19834 * @elemDecl: the element declaration
19835 *
19836 * Check the cvc-idc-keyref constraints.
19837 */
19838static int
19839xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
19840{
19841 xmlSchemaPSVIIDCBindingPtr refbind, bind;
19842
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019843 refbind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019844 /*
19845 * Find a keyref.
19846 */
19847 while (refbind != NULL) {
19848 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19849 int i, j, k, res;
19850 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
19851 xmlSchemaPSVIIDCKeyPtr refKey, key;
19852
19853 /*
19854 * Find the referred key/unique.
19855 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019856 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019857 do {
19858 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
19859 bind->definition)
19860 break;
19861 bind = bind->next;
19862 } while (bind != NULL);
19863
19864 /*
19865 * Search for a matching key-sequences.
19866 */
19867 for (i = 0; i < refbind->nbNodes; i++) {
19868 res = 0;
19869 if (bind != NULL) {
19870 refKeys = refbind->nodeTable[i]->keys;
19871 for (j = 0; j < bind->nbNodes; j++) {
19872 keys = bind->nodeTable[j]->keys;
19873 for (k = 0; k < bind->definition->nbFields; k++) {
19874 refKey = refKeys[k];
19875 key = keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019876 res = xmlSchemaAreValuesEqual(vctxt,
19877 key->type, key->compValue,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019878 refKey->type, refKey->compValue);
19879 if (res == 0)
19880 break;
19881 else if (res == -1) {
19882 return (-1);
19883 }
19884 }
19885 if (res == 1) {
19886 /*
19887 * Match found.
19888 */
19889 break;
19890 }
19891 }
19892 }
19893 if (res == 0) {
19894 /* TODO: Report the key-sequence. */
19895 xmlSchemaVCustomErr(vctxt,
19896 XML_SCHEMAV_CVC_IDC,
19897 refbind->nodeTable[i]->node,
19898 (xmlSchemaTypePtr) refbind->definition,
19899 "No matching key-sequence found", NULL);
19900 }
19901 }
19902 }
19903 refbind = refbind->next;
19904 }
19905 return (0);
19906}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019907
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019908/**
19909 * xmlSchemaBeginElement:
19910 * @vctxt: the WXS validation context
19911 *
19912 * Just a temporary workaround to simulate streaming validation
19913 * a bit.
19914 */
19915static void
19916xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
19917{
19918 vctxt->depth++;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019919 vctxt->nodeInfo = xmlSchemaGetFreshElemInfo(vctxt, vctxt->depth);
19920 vctxt->nodeInfo->node = vctxt->node;
19921 vctxt->nodeInfo->localName = vctxt->node->name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019922 if (vctxt->node->ns != NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019923 vctxt->nodeInfo->namespaceName = vctxt->node->ns->href;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019924 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019925 vctxt->nodeInfo->namespaceName = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019926}
19927
19928/**
19929 * xmlSchemaEndElement:
19930 * @vctxt: the WXS validation context
19931 *
19932 * Just a temporary workaround to simulate streaming validation
19933 * a bit.
19934 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019935static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019936xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
19937{
19938 if (vctxt->depth < 0) {
19939 /* TODO: raise error? */
19940 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019941 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019942 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019943 /*
19944 * Evaluate the history of changes of active state objects.
19945 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019946 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
19947 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019948
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019949 if (vctxt->nodeInfo->value != NULL) {
19950 xmlSchemaFreeValue(vctxt->nodeInfo->value);
19951 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019952 }
19953 /*
19954 * TODO: 6 The element information item must be ·valid· with respect to each of
19955 * the {identity-constraint definitions} as per Identity-constraint
19956 * Satisfied (§3.11.4).
19957 */
19958 /*
19959 * Validate IDC keyrefs.
19960 */
19961 xmlSchemaCheckCVCIDCKeyRef(vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019962
19963 /*
19964 * Merge/free the IDC table.
19965 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019966 if (vctxt->nodeInfo->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019967#ifdef DEBUG_IDC
19968 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019969 vctxt->nodeInfo->namespaceName,
19970 vctxt->nodeInfo->localName,
19971 vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019972#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019973 if (vctxt->depth > 0) {
19974 /*
19975 * Merge the IDC node table with the table of the parent node.
19976 */
19977 xmlSchemaBubbleIDCNodeTables(vctxt);
19978 }
19979 /*
19980 * TODO: Don't free the PSVI IDC tables if they are
19981 * requested for the PSVI.
19982 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019983 xmlSchemaIDCFreeIDCTable(vctxt->nodeInfo->idcTable);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019984 vctxt->nodeInfo->idcTable = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019985 }
19986
19987 /*
19988 * Cleanup IDC matchers.
19989 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019990 if (vctxt->nodeInfo->idcMatchers != NULL) {
19991 xmlSchemaIDCFreeMatcherList(vctxt->nodeInfo->idcMatchers);
19992 vctxt->nodeInfo->idcMatchers = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019993 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019994
19995 /*
19996 * Skip further processing if we are on the validation root.
19997 */
19998 if (vctxt->depth == 0) {
19999 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020000 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020001 }
20002
20003 /*
20004 * Reset the bubbleDepth if needed.
20005 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020006 if (vctxt->aidcs != NULL) {
20007 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
20008 do {
20009 if (aidc->bubbleDepth == vctxt->depth) {
20010 /*
20011 * A bubbleDepth of a key/unique IDC matches the current
20012 * depth, this means that we are leaving the scope of the
20013 * top-most keyref IDC.
20014 */
20015 aidc->bubbleDepth = -1;
20016 }
20017 aidc = aidc->next;
20018 } while (aidc != NULL);
20019 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020020 vctxt->depth--;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020021 /*
20022 * Clear the current elemInfo.
20023 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020024 if (vctxt->nodeInfo->value != NULL) {
20025 xmlSchemaFreeValue(vctxt->nodeInfo->value);
20026 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020027 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020028 vctxt->nodeInfo = vctxt->elemInfos[vctxt->depth];
20029 vctxt->node = vctxt->nodeInfo->node;
20030
20031 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020032}
20033
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020034/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020035 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000020036 * @ctxt: a schema validation context
20037 * @node: the top node.
20038 *
20039 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020040 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000020041 *
20042 * Returns 0 if the element is schemas valid, a positive error code
20043 * number otherwise and -1 in case of internal or API error.
20044 */
20045static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020046xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
20047 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020048{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020049 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020050 int ret = 0;
20051 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020052 xmlAttrPtr attr;
20053 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020054 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000020055
20056 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020057 * This one is called by xmlSchemaValidateElementByWildcardInternal,
20058 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020059 * Note that @elemDecl will be the declaration and never the
20060 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020061 */
Daniel Veillard3646d642004-06-02 19:19:14 +000020062
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020063 if (ctxt == NULL) {
20064 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
20065 "Internal error: xmlSchemaValidateElementByDeclaration, "
20066 "bad arguments.\n",
20067 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020068 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020069 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020070
20071 elem = ctxt->node;
20072
20073 /*
20074 * cvc-elt (3.3.4) : 1
20075 */
20076 if (elemDecl == NULL) {
20077 xmlSchemaVCustomErr(ctxt,
20078 XML_SCHEMAV_CVC_ELT_1,
20079 elem, NULL,
20080 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020081 /*
20082 * Evaluate IDCs even if an error occured.
20083 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020084 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020085 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020086 return (ctxt->err);
20087 }
20088 /*
20089 * cvc-elt (3.3.4) : 2
20090 */
20091 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
20092 xmlSchemaVCustomErr(ctxt,
20093 XML_SCHEMAV_CVC_ELT_2,
20094 elem, NULL,
20095 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020096 /*
20097 * Evaluate IDCs even if an error occured.
20098 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020099 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020100 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020101 return (ctxt->err);
20102 }
20103
20104 /*
20105 * cvc-elt (3.3.4) : 3
20106 * Handle 'xsi:nil'.
20107 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020108
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020109 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020110 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020111 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
20112 ctxt->node = (xmlNodePtr) attr;
20113 ctxt->cur = attr->children;
20114 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
20115 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
20116 BAD_CAST attrValue, 1, 1, 1, 1);
20117 ctxt->node = elem;
20118 ctxt->type = (xmlSchemaTypePtr) elemDecl;
20119 if (ret < 0) {
20120 xmlSchemaVCustomErr(ctxt,
20121 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020122 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020123 "Internal error: xmlSchemaValidateElementByDeclaration, "
20124 "validating the attribute 'xsi:nil'", NULL);
20125 if (attrValue != NULL)
20126 xmlFree(attrValue);
20127 return (-1);
20128 }
20129 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020130 /*
20131 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020132 */
20133 xmlSchemaVCustomErr(ctxt,
20134 XML_SCHEMAV_CVC_ELT_3_1,
20135 elem, NULL,
20136 "The element is not 'nillable'", NULL);
20137 } else {
20138 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020139 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020140 ret = 0;
20141 /*
20142 * cvc-elt (3.3.4) : 3.2.1
20143 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020144 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
20145 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020146 xmlSchemaVCustomErr(ctxt,
20147 XML_SCHEMAV_CVC_ELT_3_2_1,
20148 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020149 elem, (xmlSchemaTypePtr) elemDecl,
20150 "The 'nilled' element must have no character or "
20151 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020152 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
20153 }
20154 /*
20155 * cvc-elt (3.3.4) : 3.2.2
20156 */
20157 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
20158 (elemDecl->value != NULL)) {
20159 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
20160 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020161 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020162 "There is a fixed value constraint defined for "
20163 "the 'nilled' element", NULL);
20164 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
20165 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020166 if (ret == 0)
20167 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020168 }
20169 }
20170 if (attrValue != NULL)
20171 xmlFree(attrValue);
20172 }
20173
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020174
20175 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020176 /*
20177 * cvc-elt (3.3.4) : 4
20178 * Handle 'xsi:type'.
20179 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020180
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020181 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
20182 if (attr != NULL) {
20183 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020184
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020185 /*
20186 * TODO: We should report a *warning* that the type was overriden
20187 * by the instance.
20188 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020189
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020190 /*
20191 * cvc-elt (3.3.4) : 4.1
20192 */
20193 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
20194 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
20195 &nsName, &local);
20196 if (ret < 0) {
20197 xmlSchemaVCustomErr(ctxt,
20198 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020199 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020200 "Internal error: xmlSchemaValidateElementByDeclaration, "
20201 "validating the attribute 'xsi:type'", NULL);;
20202 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020203 FREE_AND_NULL(nsName)
20204 FREE_AND_NULL(local)
20205 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020206 } else if (ret == 1) {
20207 xmlSchemaVSimpleTypeErr(ctxt,
20208 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
20209 (xmlNodePtr) attr, attrValue,
20210 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
20211 } else if (ret == 2) {
20212 xmlSchemaVCustomErr(ctxt,
20213 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
20214 (xmlNodePtr) attr,
20215 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20216 "The QName value '%s' has no "
20217 "corresponding namespace declaration in scope",
20218 attrValue);
20219 } else {
20220 /*
20221 * cvc-elt (3.3.4) : 4.2
20222 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020223 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
20224 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020225 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020226
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020227 xmlSchemaVCustomErr(ctxt,
20228 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020229 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020230 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20231 "The value %s does not resolve to a type "
20232 "definition",
20233 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
20234 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020235 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020236 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020237 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020238 */
20239 }
20240 }
20241 FREE_AND_NULL(attrValue)
20242 FREE_AND_NULL(nsName)
20243 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020244 }
20245 /* TODO: Change the handling of missing types according to
20246 * the spec.
20247 */
20248 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000020249 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020250 XML_SCHEMAV_CVC_TYPE_1,
20251 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000020252 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020253 /*
20254 * Evaluate IDCs even if an error occured.
20255 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020256 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020257 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020258 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020259 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020260
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020261 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020262 * Remember the actual-type definition.
20263 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020264 ctxt->nodeInfo->typeDef = actualType;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020265
20266 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020267 * TODO: Since this should be already checked by the content model automaton,
20268 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
20269 * has been changed to XML_SCHEMAV_INTERNAL.
20270 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020271 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000020272 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020273 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020274 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020275 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020276 "Element %s: missing child %s\n",
20277 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020278 }
20279 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020280 }
20281 */
Daniel Veillard4255d502002-04-16 15:50:10 +000020282 /*
20283 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020284 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020285 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000020286 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020287 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020288 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020289 "Element %s: missing child %s found %s\n",
20290 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020291 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000020292 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020293 */
20294 if (elemHasContent == -1)
20295 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020296
20297 /*
20298 * IDC: Register identity-constraint XPath matchers.
20299 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020300 if (elemDecl->idcs != NULL)
20301 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
20302 /*
20303 * Evaluate IDCs.
20304 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020305 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020306 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020307 /*
20308 * cvc-elt (3.3.4) : 5
20309 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020310 */
Daniel Veillard4255d502002-04-16 15:50:10 +000020311 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020312 * cvc-elt (3.3.4) : 5.1
20313 * If the declaration has a {value constraint},
20314 * the item has neither element nor character [children] and
20315 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020316 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020317 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
20318 /*
20319 * cvc-elt (3.3.4) : 5.1.1
20320 * If the ·actual type definition· is a ·local type definition·
20321 * then the canonical lexical representation of the {value constraint}
20322 * value must be a valid default for the ·actual type definition· as
20323 * defined in Element Default Valid (Immediate) (§3.3.6).
20324 */
20325 /*
20326 * NOTE: 'local' above means types aquired by xsi:type.
20327 */
20328 ret = 0;
20329 if (actualType != elemDecl->subtypes) {
20330 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
20331 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020332 elemDecl->value, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020333 if (ret < 0) {
20334 xmlSchemaVCustomErr(ctxt,
20335 XML_SCHEMAV_INTERNAL,
20336 elem, actualType,
20337 "Internal error: xmlSchemaValidateElementByDeclaration, "
20338 "validating a default value", NULL);
20339 return (-1);
20340 }
20341 }
20342 /*
20343 * cvc-elt (3.3.4) : 5.1.2
20344 * The element information item with the canonical lexical
20345 * representation of the {value constraint} value used as its
20346 * ·normalized value· must be ·valid· with respect to the
20347 * ·actual type definition· as defined by Element Locally Valid (Type)
20348 * (§3.3.4).
20349 */
20350 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020351 * Disable validation of the simple content, if it was already
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020352 * done above.
20353 */
20354 if (ret == 0) {
20355 if (actualType != elemDecl->subtypes)
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020356 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020357 else
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020358 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020359 ctxt->node = elem;
20360 if (ret < 0) {
20361 xmlSchemaVCustomErr(ctxt,
20362 XML_SCHEMAV_INTERNAL,
20363 elem, actualType,
20364 "Internal error: xmlSchemaValidateElementByDeclaration, "
20365 "validating against the type", NULL);
20366 return (-1);
20367 }
20368 /*
20369 * PSVI: Create a text node on the instance element.
20370 */
20371 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
20372 xmlNodePtr textChild;
20373
20374 textChild = xmlNewText(elemDecl->value);
20375 if (textChild == NULL) {
20376 xmlSchemaVCustomErr(ctxt,
20377 XML_SCHEMAV_INTERNAL,
20378 elem, actualType,
20379 "Internal error: xmlSchemaValidateElementByDeclaration, "
20380 "could not create a default text node for the instance",
20381 NULL);
20382 } else
20383 xmlAddChild(elem, textChild);
20384 }
20385 }
20386
20387 } else {
20388 /*
20389 * 5.2.1 The element information item must be ·valid· with respect
20390 * to the ·actual type definition· as defined by Element Locally
20391 * Valid (Type) (§3.3.4).
20392 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020393 ret = xmlSchemaValidateElementByType(ctxt, actualType, nilled, 1);
20394 /*
20395 * Consume the computed value for IDCs, ect. Note that default
20396 * values are not supported yet.
20397 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020398 if (ctxt->value != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020399 ctxt->nodeInfo->value = ctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020400 ctxt->value = NULL;
20401 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020402 ctxt->node = elem;
20403 if (ret < 0) {
20404 xmlSchemaVCustomErr(ctxt,
20405 XML_SCHEMAV_INTERNAL,
20406 elem, actualType,
20407 "Internal error: xmlSchemaValidateElementByDeclaration, "
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000020408 "calling validation by type", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020409 return (-1);
20410 }
20411 /*
20412 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
20413 * not applied, all of the following must be true:
20414 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020415 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
20416 /*
20417 * 5.2.2.1 The element information item must have no element
20418 * information item [children].
20419 *
20420 * TODO REDUNDANT: If the actual type exists, the above call to
20421 * xmlSchemaValidateElementByType will already check for element
20422 * nodes.
20423 */
20424 if (xmlSchemaHasElemContent(elem)) {
20425 xmlSchemaVCustomErr(ctxt,
20426 XML_SCHEMAV_CVC_ELT_5_2_2_1,
20427 elem, (xmlSchemaTypePtr) elemDecl,
20428 "Elements in the content are not allowed if it is "
20429 "constrained by a fixed value", NULL);
20430 } else {
20431 /*
20432 * 5.2.2.2 The appropriate case among the following must
20433 * be true:
20434 */
20435
20436 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
20437 xmlChar *value;
20438 /*
20439 * 5.2.2.2.1 If the {content type} of the ·actual type
20440 * definition· is mixed, then the *initial value* of the
20441 * item must match the canonical lexical representation
20442 * of the {value constraint} value.
20443 *
20444 * ... the *initial value* of an element information
20445 * item is the string composed of, in order, the
20446 * [character code] of each character information item in
20447 * the [children] of that element information item.
20448 */
20449 value = xmlNodeListGetString(elem->doc, elem->children, 1);
20450 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
20451 /*
20452 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020453 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020454 */
20455 xmlSchemaVCustomErr(ctxt,
20456 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
20457 elem, (xmlSchemaTypePtr) elemDecl,
20458 "The value does not match the cononical "
20459 "lexical representation of the fixed constraint",
20460 NULL);
20461 }
20462 if (value != NULL)
20463 xmlFree(value);
20464 } else if ((actualType->contentType ==
20465 XML_SCHEMA_CONTENT_SIMPLE) ||
20466 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
20467 xmlChar *value;
20468
20469 /*
20470 * 5.2.2.2.2 If the {content type} of the ·actual type
20471 * definition· is a simple type definition, then the
20472 * *actual value* of the item must match the canonical
20473 * lexical representation of the {value constraint} value.
20474 */
20475 /*
20476 * TODO: *actual value* is the normalized value, impl. this.
20477 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020478 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020479 *
20480 */
20481 value = xmlNodeListGetString(elem->doc, elem->children, 1);
20482 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
20483 xmlSchemaVCustomErr(ctxt,
20484 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
20485 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020486 "The normalized value does not match the canonical "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020487 "lexical representation of the fixed constraint",
20488 NULL);
20489 }
20490 if (value != NULL)
20491 xmlFree(value);
20492
20493 }
20494 /*
20495 * TODO: What if the content type is not 'mixed' or simple?
20496 */
20497
20498 }
20499
20500 }
20501 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020502 /*
20503 * TODO: 7 If the element information item is the ·validation root·, it must be
20504 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
20505 */
20506
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020507 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000020508}
20509
Daniel Veillard4255d502002-04-16 15:50:10 +000020510/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020511 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000020512 * @ctxt: a schema validation context
20513 * @node: the top node.
20514 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020515 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
20516 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000020517 *
20518 * Returns 0 if the element is valid, a positive error code
20519 * number otherwise and -1 in case of an internal error.
20520 */
20521static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020522xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
20523 xmlSchemaWildcardPtr wild,
20524 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000020525{
20526 const xmlChar *uri;
20527 int ret = 0;
20528 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020529
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020530 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020531 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
20532 if (ret == -1) {
20533 xmlSchemaVCustomErr(ctxt,
20534 XML_SCHEMAV_INTERNAL,
20535 ctxt->node, NULL,
20536 "Internal error: xmlSchemaValidateElement, "
20537 "assembling schema by xsi", NULL);
20538 return (-1);
20539 }
20540 /*
20541 * NOTE: We won't react on schema parser errors here.
20542 * TODO: But a warning would be nice.
20543 */
20544 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000020545 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
20546 xmlSchemaElementPtr decl = NULL;
20547
20548 if (node->ns != NULL)
20549 decl = xmlHashLookup3(ctxt->schema->elemDecl,
20550 node->name, node->ns->href, NULL);
20551 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020552 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
20553 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000020554 if (decl != NULL) {
20555 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020556 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000020557 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020558 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000020559 "Internal error: xmlSchemaValidateAnyInternal, "
20560 "validating an element in the context of a wildcard.",
20561 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000020562 }
20563 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000020564 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
20565 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020566 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020567 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020568 /*
20569 * Evaluate IDCs even if a validation error occured.
20570 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020571 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020572 return(-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020573
Daniel Veillardc0826a72004-08-10 14:17:33 +000020574 return (ctxt->err);
20575 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020576 /*
20577 * Evaluate IDCs; we need to know if an IDC field resolves to
20578 * such a node. This node has no type definition and will
20579 * definitely result in an IDC validation error if an IDC field
20580 * resolves.
20581 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020582 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020583 return(-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000020584 }
20585 if (node->children != NULL) {
20586 child = node->children;
20587 do {
20588 if (child->type == XML_ELEMENT_NODE) {
20589 if (child->ns != NULL)
20590 uri = child->ns->href;
20591 else
20592 uri = NULL;
20593 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020594 /* TODO: error code. */
20595 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000020596 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020597 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000020598 return (ctxt->err);
20599 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020600
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020601 ctxt->node = child;
20602 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020603
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020604 /*
20605 * Recurse over the children.
20606 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020607 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
20608 wild, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020609 if (ret == -1)
20610 return (-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020611
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020612 if (xmlSchemaEndElement(ctxt) == -1)
20613 return (-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020614
Daniel Veillardc0826a72004-08-10 14:17:33 +000020615 if (ret != 0)
20616 return (ret);
20617 }
20618 child = child->next;
20619 } while (child != NULL);
20620 }
20621 return (0);
20622}
20623
20624/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020625 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000020626 * @ctxt: a schema validation context
20627 *
20628 * Returns 0 if the element is valid, a positive error code
20629 * number otherwise and -1 in case of an internal or API error.
20630 */
20631static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020632xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020633 xmlSchemaWildcardPtr wild)
Daniel Veillardc0826a72004-08-10 14:17:33 +000020634{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020635
20636 if ((wild == NULL) || (wild->type != XML_SCHEMA_TYPE_ANY) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020637 (ctxt->node == NULL)) {
20638 xmlSchemaVCustomErr(ctxt,
20639 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
20640 "Internal error: xmlSchemaValidateElementByWildcard, "
20641 "bad arguments", NULL);
20642 return (-1);
20643 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020644 if (wild->negNsSet != NULL) {
20645 /*
20646 * Workaround for negated namespaces.
20647 */
20648 if (ctxt->node->ns != NULL) {
20649 if (xmlSchemaMatchesWildcardNs(wild, ctxt->node->ns->href) == 0) {
20650 ctxt->flags |= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD;
20651 return (XML_SCHEMAV_ELEMENT_CONTENT);
20652 }
20653 } else if (xmlSchemaMatchesWildcardNs(wild, NULL) == 0) {
20654 ctxt->flags |= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD;
20655 return (XML_SCHEMAV_ELEMENT_CONTENT);
20656 }
20657 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020658 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020659 wild, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000020660}
20661
20662/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020663 * xmlSchemaValidateElementByAnyType:
William M. Brack2f2a6632004-08-20 23:09:47 +000020664 * @ctxt: a schema validation context
20665 * @node: the current element
20666 *
20667 * This one validates the content of an element of the type
20668 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
20669 * thus elements in the subtree will be validated, if a corresponding
20670 * declaration in the schema exists.
20671 *
20672 * Returns 0 if the element and its subtree is valid, a positive error code
20673 * otherwise and -1 in case of an internal or API error.
20674 */
20675static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020676xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
20677 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000020678{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020679 xmlSchemaTypePtr oldtype;
20680 xmlNodePtr top, cur;
20681 xmlSchemaElementPtr decl;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020682 int skipContent, ret, insub = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020683
20684 if ((type == NULL) || (ctxt->node == NULL))
20685 return (-1);
20686
20687 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000020688 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020689
20690 oldtype = ctxt->type;
20691 top = ctxt->node;
20692 /*
20693 * STREAM: Child nodes are processed.
20694 */
20695 cur = ctxt->node->children;
20696 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000020697 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020698 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000020699 /*
20700 * The process contents of the wildcard is "lax", thus
20701 * we need to validate the element if a declaration
20702 * exists.
20703 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020704 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000020705 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020706 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000020707 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020708 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
20709 ctxt->node = cur;
20710
20711 if (insub) {
20712 /*
20713 * BEGIN element.
20714 */
20715 xmlSchemaBeginElement(ctxt);
20716 } else
20717 insub = 1;
20718
20719 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020720 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
20721 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000020722 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020723 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000020724 "Internal error: xmlSchemaValidateAnyTypeContent, "
20725 "validating an element in the context of a wildcard.",
20726 NULL, NULL);
20727 return (ret);
20728 } else if (ret > 0)
20729 return (ret);
20730 skipContent = 1;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020731 } else {
20732 /*
20733 * IDCs.
20734 */
20735 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
20736 return(-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000020737 }
20738 }
20739 /*
20740 * Browse the full subtree, deep first.
20741 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020742 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000020743 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020744 cur = cur->children;
20745 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000020746 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020747 cur = cur->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020748 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000020749 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020750 while (cur != top) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020751 if (cur->type == XML_ELEMENT_NODE) {
20752 /*
20753 * END element.
20754 */
20755 xmlSchemaEndElement(ctxt);
20756 }
20757 if (cur->parent != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020758 cur = cur->parent;
20759 if ((cur != top) && (cur->next != NULL)) {
20760 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000020761 break;
20762 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020763 if (cur->parent == NULL) {
20764 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000020765 break;
20766 }
20767 }
20768 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020769 if (cur == top)
20770 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000020771 } else
20772 break;
20773 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020774 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000020775 return (0);
20776}
20777
20778/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020779 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000020780 * @ctxt: a schema validation context
20781 * @node: the top node.
20782 *
20783 * Validate the content of an element expected to be a complex type type
20784 * xmlschema-1.html#cvc-complex-type
20785 * Validation Rule: Element Locally Valid (Complex Type)
20786 *
20787 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000020788 * number otherwise and -1 in case of internal or API error.
20789 * Note on reported errors: Although it might be nice to report
20790 * the name of the simple/complex type, used to validate the content
20791 * of a node, it is quite unnecessary: for global defined types
20792 * the local name of the element is equal to the NCName of the type,
20793 * for local defined types it makes no sense to output the internal
20794 * computed name of the type. TODO: Instead, one should attach the
20795 * struct of the type involved to the error handler - this allows
20796 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000020797 */
20798static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020799xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020800 xmlSchemaTypePtr type,
20801 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020802{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020803 xmlSchemaTypePtr oldtype;
20804 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000020805 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000020806 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020807 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000020808
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020809 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
20810 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020811
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020812 oldtype = ctxt->type;
20813 ctxt->type = type;
20814 elem = ctxt->node;
20815
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020816 /*
20817 * Verify the attributes
20818 */
20819 /*
20820 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020821 */
20822 /* NOTE: removed, since a check for abstract is
20823 * done in the cvc-type constraint.
20824 *
20825 *
20826 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
20827 * xmlSchemaVComplexTypeErr(ctxt,
20828 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
20829 * elem, type,
20830 * "The type definition is abstract");
20831 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
20832 *}
20833 */
20834
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020835 attrs = ctxt->attr;
20836 attrTop = ctxt->attrTop;
20837 /*
20838 * STREAM: Attribute nodes are processed.
20839 */
20840 xmlSchemaRegisterAttributes(ctxt, elem->properties);
20841 xmlSchemaValidateAttributes(ctxt, elem, type);
20842 if (ctxt->attr != NULL)
20843 xmlSchemaFreeAttributeStates(ctxt->attr);
20844 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020845 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020846
20847 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020848 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020849 * model was defined. Somehow ->contModel is always not NULL
20850 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020851 * TODO: Check if the obove still occurs.
20852 */
Daniel Veillard4255d502002-04-16 15:50:10 +000020853 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000020854 case XML_SCHEMA_CONTENT_EMPTY: {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020855 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020856 * 1 If the {content type} is empty, then the element information
20857 * item has no character or element information item [children].
20858 */
20859 /*
20860 * TODO: Is the entity stuff correct?
20861 */
20862 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
20863 xmlSchemaVComplexTypeErr(ctxt,
20864 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
20865 elem, type,
20866 "Character or element content is not allowed, "
20867 "because the content type is empty");
20868 }
20869 break;
20870 }
20871 case XML_SCHEMA_CONTENT_MIXED:
20872 /*
20873 * Some speedups for anyType or types derived directly from it.
20874 */
20875 if (IS_ANYTYPE(type)) {
20876 /*
20877 * Corresponds to <element name="foo" [type="xsd:anyType"]/>.
20878 */
20879 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
20880 /* TODO: Handle -1. */
20881 break;
20882 }
20883 if (IS_ANYTYPE(type->baseType) &&
20884 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
20885 (type->subtypes == type->baseType->subtypes)) {
20886 /*
20887 * Corresponds to an <extension> of anyType.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020888 */
20889 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
20890 /* TODO: Handle -1. */
20891 break;
20892 }
20893 /* No break on purpose. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020894 case XML_SCHEMA_CONTENT_ELEMENTS: {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020895 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000020896 xmlChar *values[10];
20897 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020898 /*
20899 * SPEC (2.4) If the {content type} is element-only or mixed,
20900 * then the sequence of the element information item's
20901 * element information item [children], if any, taken in
20902 * order, is ·valid· with respect to the {content type}'s
20903 * particle, as defined in Element Sequence Locally Valid
20904 * (Particle) (§3.9.4).
20905 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020906 /*
20907 * Content model check initialization.
20908 */
20909 if (type->contModel != NULL) {
20910 oldregexp = ctxt->regexp;
20911 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
20912 (xmlRegExecCallbacks)
20913 xmlSchemaValidateCallback, ctxt);
20914#ifdef DEBUG_AUTOMATA
20915 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
20916#endif
20917 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020918 /*
20919 * STREAM: Children are processed.
20920 */
20921 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000020922 while (child != NULL) {
20923 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020924 if (child->ns != NULL)
20925 nsUri = child->ns->href;
20926 else
20927 nsUri = NULL;
20928 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020929 child->name, nsUri, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020930 if (ctxt->err == XML_SCHEMAV_INTERNAL)
20931 return (-1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020932 if (ctxt->flags & XML_SCHEMA_VALID_INVALID_NEG_WILDCARD) {
20933 ctxt->flags ^= XML_SCHEMA_VALID_INVALID_NEG_WILDCARD;
20934 ret = -1;
20935 }
20936 /*
20937 * URGENT TODO: Could we anchor an error report
20938 * here to notify of invalid elements?
20939 * TODO: Perhaps it would be better to report
20940 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020941 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000020942#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000020943 if (ret < 0)
20944 xmlGenericError(xmlGenericErrorContext,
20945 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000020946 else
20947 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000020948 " --> %s\n", child->name);
20949#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000020950 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000020951 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
20952 &values[0], &terminal);
20953 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000020954 XML_SCHEMAV_ELEMENT_CONTENT,
20955 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000020956 "This element is not expected",
20957 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000020958 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000020959 /*
20960 * Note that this will skip further validation of the
20961 * content.
20962 */
20963 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000020964 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000020965 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
20966 /*
20967 * TODO: Ask Daniel if this are all character nodes.
20968 */
20969 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
20970 (child->type == XML_ENTITY_NODE) ||
20971 (child->type == XML_ENTITY_REF_NODE) ||
20972 (child->type == XML_CDATA_SECTION_NODE))) {
20973 /*
20974 * 2.3 If the {content type} is element-only, then the
20975 * element information item has no character information
20976 * item [children] other than those whose [character
20977 * code] is defined as a white space in [XML 1.0 (Second
20978 * Edition)].
20979 */
William M. Brack2f2a6632004-08-20 23:09:47 +000020980 xmlSchemaVComplexTypeErr(ctxt,
20981 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020982 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000020983 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000020984 "because the content type is element-only");
20985 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000020986 break;
20987 }
20988 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020989 }
20990 /*
20991 * Content model check finalization.
20992 */
20993 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000020994 if (ret == 0) {
20995 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020996 &values[0], &terminal);
Daniel Veillard0e460da2005-03-30 22:47:10 +000020997 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020998 * If a next value still exists, It does not have to
Daniel Veillard0e460da2005-03-30 22:47:10 +000020999 * mean that there's an element missing, since it
21000 * might be an optional element. So double check it.
21001 */
21002 ret = xmlRegExecPushString(ctxt->regexp,
21003 NULL, NULL);
21004 if (ret <= 0) {
21005 ret = 1;
21006 xmlSchemaVComplexTypeElemErr(ctxt,
21007 XML_SCHEMAV_ELEMENT_CONTENT,
21008 elem, type, "Missing child element(s)",
21009 nbval, nbneg, values);
21010 } else
21011 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021012#ifdef DEBUG_AUTOMATA
Daniel Veillard0e460da2005-03-30 22:47:10 +000021013 xmlGenericError(xmlGenericErrorContext,
21014 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021015#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021016#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021017 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021018 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021019 "Element %s content check succeeded\n",
21020 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021021#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021022 }
21023 xmlRegFreeExecCtxt(ctxt->regexp);
21024 ctxt->regexp = oldregexp;
21025 }
21026 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000021027 break;
21028 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021029 case XML_SCHEMA_CONTENT_BASIC:
21030 /*
21031 * If the simple content was already validated
21032 * (e.g. a default value), the content need not
21033 * to be validated again.
21034 */
21035 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000021036 xmlChar *value = NULL;
21037 /*
21038 * We hit a complexType with a simpleContent resolving
21039 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000021040 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000021041 /*
21042 * 2.2 If the {content type} is a simple type definition,
21043 * then the element information item has no element
21044 * information item [children], and the ·normalized value·
21045 * of the element information item is ·valid· with respect
21046 * to that simple type definition as defined by String
21047 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021048 */
21049 /*
21050 * STREAM: Children are processed.
21051 */
21052 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000021053 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021054 /*
21055 * TODO: Could the entity stuff produce elements
21056 * as well?
21057 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000021058 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000021059 xmlSchemaVComplexTypeErr(ctxt,
21060 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021061 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000021062 "Element content is not allowed, because "
21063 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000021064 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
21065 break;
21066 }
21067 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021068 }
21069 ctxt->node = elem;
21070 ctxt->cur = elem->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021071 if (ret != 0) {
21072 FREE_AND_NULL(value)
21073 break;
21074 }
21075 /*
21076 * Validate the character content against a simple type.
21077 */
21078 if (elem->children == NULL)
21079 value = NULL;
21080 else
21081 value = xmlNodeGetContent(elem);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021082 /*
21083 * NOTE: This call won't check the correct types of the
21084 * content nodes, since this should be done here.
21085 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000021086 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
21087 type->contentTypeDef, value, 1, 1, 1, 0);
21088 if (ret > 0) {
21089 /*
21090 * NOTE: Although an error will be reported by
21091 * xmlSchemaValidateSimpleTypeValue, the spec wants
21092 * a specific complex type error to be reported
21093 * additionally.
21094 */
21095 xmlSchemaVComplexTypeErr(ctxt,
21096 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
21097 elem, type,
21098 "The character content is not valid");
21099 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
21100 } else if (ret < 0) {
21101 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
21102 "Internal error: xmlSchemaValidateComplexType, "
21103 "Element '%s': Error while validating character "
21104 "content against complex type '%s'.\n",
21105 elem->name, type->name);
21106 if (value != NULL)
21107 xmlFree(value);
21108 ctxt->type = oldtype;
21109 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021110 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000021111 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000021112 xmlFree(value);
21113
Daniel Veillard01fa6152004-06-29 17:04:39 +000021114 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021115 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021116 default:
21117 TODO xmlGenericError(xmlGenericErrorContext,
21118 "unimplemented content type %d\n",
21119 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000021120 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021121 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021122 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000021123}
21124
21125/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021126 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000021127 * @ctxt: a schema validation context
21128 * @elem: an element
21129 * @type: the list of type declarations
21130 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021131 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000021132 *
21133 * Returns 0 if the element is schemas valid, a positive error code
21134 * number otherwise and -1 in case of internal or API error.
21135 */
21136static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021137xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021138 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021139 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021140 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021141{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021142 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000021143
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021144
21145 if ((ctxt == NULL) || (type == NULL)) {
21146 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
21147 "Internal error: xmlSchemaValidateElementByType, "
21148 "bad arguments", NULL);
21149 return (-1);
21150 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021151 /*
21152 * This one is called by "xmlSchemaValidateElementByDeclaration".
21153 * It will forward to the proper validation
21154 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021155 */
21156 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021157 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021158 XML_SCHEMAV_CVC_TYPE_1,
21159 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021160 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021161 return (XML_SCHEMAV_CVC_TYPE_1);
21162 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021163
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021164 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021165 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021166 XML_SCHEMAV_CVC_TYPE_2,
21167 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000021168 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021169 return (XML_SCHEMAV_CVC_TYPE_2);
21170 }
21171
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021172 switch (type->type) {
21173 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021174 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
21175 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021176 break;
21177 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021178 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021179 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021180 break;
21181 case XML_SCHEMA_TYPE_BASIC:
21182 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
21183 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
21184 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021185 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021186 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021187 break;
21188 default:
21189 ret = -1;
21190 break;
21191 }
21192 if (ret == -1)
21193 return (-1);
21194 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021195 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000021196}
21197
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021198static int
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021199xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021200 xmlSchemaTypePtr type,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021201 const xmlChar *value,
21202 xmlSchemaValPtr *val)
21203{
21204 xmlSchemaTypePtr prim;
21205
21206 if (val == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021207 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021208 XML_SCHEMAV_INTERNAL,
21209 "Internal error: xmlSchemaPostCreateVal, "
21210 "bad arguments", NULL, NULL);
21211 return (-1);
21212 }
21213 /*
21214 * Only string or anySimpleType values are expected to be post-created.
21215 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021216 prim = xmlSchemaGetPrimitiveType(type);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021217 if ((prim->builtInType == XML_SCHEMAS_STRING) ||
21218 (prim->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21219 {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021220 if (value == NULL)
21221 /* TODO: Can this happen at all? */
21222 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
21223 xmlStrdup(BAD_CAST ""));
21224 else
21225 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING, value);
21226 if ((*val) == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021227 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021228 XML_SCHEMAV_INTERNAL,
21229 "Internal error: xmlSchemaPostCreateVal, "
21230 "failed to create the value", NULL, NULL);
21231 return (-1);
21232 }
21233 return (0);
21234 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021235 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021236 XML_SCHEMAV_INTERNAL,
21237 "Internal error: xmlSchemaPostCreateVal, "
21238 "the given type is not supported", NULL, NULL);
21239 return (-1);
21240}
21241
21242static int
21243xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021244 xmlSchemaAttrStatePtr state)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021245{
21246 xmlChar *value;
21247 const xmlChar *defValue;
21248 xmlSchemaValPtr defVal;
21249 int fixed;
21250 int ret;
21251
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021252 if (vctxt->attrInfo->typeDef == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021253 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
21254 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
21255 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021256 vctxt->node = vctxt->attrInfo->node;
21257 vctxt->cur = vctxt->node->children;
21258 /* STREAM */
21259 value = xmlNodeListGetString(vctxt->node->doc, vctxt->cur, 1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021260
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021261 /*
21262 * NOTE: This call also checks the content nodes for correct type.
21263 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021264 ret = xmlSchemaValidateSimpleTypeValue(vctxt, vctxt->attrInfo->typeDef,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021265 value, 1, 1, 1, 1);
21266
21267 /*
21268 * Handle 'fixed' attributes.
21269 */
21270 if (ret > 0) {
21271 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21272 /*
21273 * NOTE: Fixed value constraints will be not
21274 * applied if the value was invalid, because:
21275 * 1. The validation process does not return a precomputed
21276 * value.
21277 * 2. An invalid value implies a violation of a fixed
21278 * value constraint.
21279 */
21280 } else if (ret == 0) {
21281 state->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021282 if (xmlSchemaGetEffectiveValueConstraint(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021283 (xmlSchemaAttributePtr) vctxt->attrInfo->decl,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021284 &fixed, &defValue, &defVal) && (fixed == 1)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000021285
21286 int ws = xmlSchemaGetWhiteSpaceFacetValue(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021287 vctxt->nodeInfo->typeDef);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021288 /*
21289 * cvc-au : Attribute Locally Valid (Use)
21290 * For an attribute information item to be·valid·
21291 * with respect to an attribute use its ·normalized
21292 * value· must match the canonical lexical representation
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021293 * of the attribute use's {value constraint} value, if it
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021294 * is present and fixed.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021295 *
21296 * TODO: Use somehow the *normalized* value and the *canonical*
21297 * fixed value. This here compares the canonical values of both.
21298 * The normalized value of, for example, a float type can differ
21299 * from its canonical representation. This all means that a fixed
21300 * value can only be OK, if it's present in the canonical form in
21301 * the instance.
21302 * NOTE: Since the value for string and anySimpleType is not always
21303 * precomputed during validation, we need to do it now.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021304 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021305 if (vctxt->value == NULL) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000021306 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021307 * Post-create the value.
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000021308 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021309 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
21310 value, &(vctxt->value)) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021311 ret = -1;
21312 goto exit;
21313 }
21314 value = NULL;
21315 }
21316 if (defVal == NULL) {
21317 xmlChar *str;
21318
21319 /*
21320 * Post-create the default/fixed value.
21321 */
21322 if (defValue == NULL)
21323 str = xmlStrdup(BAD_CAST "");
21324 else
21325 str = xmlStrdup(defValue);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021326 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
21327 str, &defVal) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021328 ret = -1;
21329 FREE_AND_NULL(str)
21330 goto exit;
21331 }
21332 ((xmlSchemaAttributePtr) vctxt->attrInfo->decl)->defVal = defVal;
21333 }
21334 if (xmlSchemaCompareValuesWhtsp(vctxt->value,
21335 (xmlSchemaWhitespaceValueType) ws,
21336 defVal,
21337 (xmlSchemaWhitespaceValueType) ws) != 0)
21338 {
21339 state->state = XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021340 }
21341 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021342 }
21343exit:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021344 if (value != NULL) {
21345 xmlFree(value);
21346 }
21347 return (ret);
21348}
21349
Daniel Veillard4255d502002-04-16 15:50:10 +000021350/**
21351 * xmlSchemaValidateAttributes:
21352 * @ctxt: a schema validation context
21353 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000021354 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000021355 *
21356 * Validate the attributes of an element.
21357 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000021358 * 1. Existent, invalid attributes are reported in the form
21359 * "prefix:localName".
21360 * Reason: readability - it is easier to find the actual XML
21361 * representation of the attributes QName.
21362 * 2. Missing attributes are reported in the form
21363 * {"URI", "localName"}.
21364 * This is necessary, since the the prefix need not to be declared
21365 * at all, and thus is not computable.
21366 *
Daniel Veillard4255d502002-04-16 15:50:10 +000021367 * Returns 0 if the element is schemas valid, a positive error code
21368 * number otherwise and -1 in case of internal or API error.
21369 */
21370static int
Daniel Veillard3646d642004-06-02 19:19:14 +000021371xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021372{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021373 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000021374 int ret;
21375 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021376 const xmlChar *defValue;
21377 xmlSchemaValPtr defVal;
21378 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021379 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000021380 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000021381 int found;
William M. Brack803812b2004-06-03 02:11:24 +000021382 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021383 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021384 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000021385#ifdef DEBUG_ATTR_VALIDATION
21386 int redundant = 0;
21387#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000021388
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021389
Daniel Veillardc0826a72004-08-10 14:17:33 +000021390 /*
21391 * Allow all attributes if the type is anyType.
21392 */
21393 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
21394 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021395
21396 oldnode = ctxt->node;
21397 if (type != NULL)
21398 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000021399 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000021400 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000021401 attrDecl = attrUse->attr;
21402#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021403 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000021404 printf("attr use - use: %d\n", attrDecl->occurs);
21405#endif
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021406 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
Daniel Veillard3646d642004-06-02 19:19:14 +000021407
21408 if (curState->decl == attrUse->attr) {
21409#ifdef DEBUG_ATTR_VALIDATION
21410 redundant = 1;
21411#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021412 }
Daniel Veillard3646d642004-06-02 19:19:14 +000021413 attr = curState->attr;
21414#ifdef DEBUG_ATTR_VALIDATION
21415 printf("attr - name: %s\n", attr->name);
21416 if (attr->ns != NULL)
21417 printf("attr - ns: %s\n", attr->ns->href);
21418 else
21419 printf("attr - ns: none\n");
21420#endif
21421 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021422 if (attr == NULL)
21423 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000021424 if (attrDecl->ref != NULL) {
21425 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021426 continue;
21427 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000021428 if ((attrDecl->refNs == NULL) ||
21429 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021430 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000021431 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021432 continue;
21433 }
21434 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000021435 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021436 continue;
21437 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000021438 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021439 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000021440 if (attr->ns == NULL) {
21441 /*
William M. Bracke7091952004-05-11 15:09:58 +000021442 * accept an unqualified attribute only if the target
21443 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000021444 */
Daniel Veillard3646d642004-06-02 19:19:14 +000021445 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000021446 /*
21447 * This check was removed, since the target namespace
21448 * was evaluated during parsing and already took
21449 * "attributeFormDefault" into account.
21450 */
21451 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000021452 continue;
21453 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000021454 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000021455 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000021456 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000021457 attr->ns->href))
21458 continue;
21459 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021460 }
Daniel Veillard3646d642004-06-02 19:19:14 +000021461#ifdef DEBUG_ATTR_VALIDATION
21462 printf("found\n");
21463#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021464 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000021465 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021466 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
21467 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021468 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021469 */
Daniel Veillard3646d642004-06-02 19:19:14 +000021470 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021471 if (!found) {
21472 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21473 xmlSchemaAttrStatePtr tmp;
21474
Daniel Veillard3646d642004-06-02 19:19:14 +000021475#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021476 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000021477#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021478 /*
21479 * Add a new dummy attribute state.
21480 */
21481 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
21482 if (tmp == NULL) {
21483 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
21484 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021485 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021486 }
21487 tmp->attr = NULL;
21488 tmp->state = XML_SCHEMAS_ATTR_MISSING;
21489 tmp->decl = attrDecl;
21490 tmp->next = NULL;
21491
21492 if (reqAttrStates == NULL) {
21493 reqAttrStates = tmp;
21494 reqAttrStatesTop = tmp;
21495 } else {
21496 reqAttrStatesTop->next = tmp;
21497 reqAttrStatesTop = tmp;
21498 }
21499 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21500 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
21501 &fixed, &defValue, &defVal))) {
21502 xmlSchemaAttrStatePtr tmp;
21503 /*
21504 * Handle non existent default/fixed attributes.
21505 */
21506 tmp = (xmlSchemaAttrStatePtr)
21507 xmlMalloc(sizeof(xmlSchemaAttrState));
21508 if (tmp == NULL) {
21509 xmlSchemaVErrMemory(ctxt,
21510 "registering schema specified attributes", NULL);
21511 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021512 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021513 }
21514 tmp->attr = NULL;
21515 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
21516 tmp->decl = attrDecl;
21517 tmp->value = defValue;
21518 tmp->next = NULL;
Kasimier T. Buchcika62f75f2005-03-21 22:01:47 +000021519 if (defAttrStatesTop == NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021520 defAttrStates = tmp;
Kasimier T. Buchcika62f75f2005-03-21 22:01:47 +000021521 else
21522 defAttrStatesTop->next = tmp;
21523 defAttrStatesTop = tmp;
21524 }
Daniel Veillard3646d642004-06-02 19:19:14 +000021525 }
21526 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000021527 }
Daniel Veillard3646d642004-06-02 19:19:14 +000021528 /*
21529 * Add required attributes to the attribute states of the context.
21530 */
21531 if (reqAttrStates != NULL) {
21532 if (ctxt->attr == NULL) {
21533 ctxt->attr = reqAttrStates;
21534 } else {
21535 ctxt->attrTop->next = reqAttrStates;
21536 }
21537 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000021538 }
Daniel Veillard3646d642004-06-02 19:19:14 +000021539 /*
21540 * Process wildcards.
21541 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021542
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021543 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000021544#ifdef DEBUG_ATTR_VALIDATION
21545 xmlSchemaWildcardNsPtr ns;
21546 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000021547 if (type->attributeWildcard->processContents ==
21548 XML_SCHEMAS_ANY_LAX)
21549 printf("processContents: lax\n");
21550 else if (type->attributeWildcard->processContents ==
21551 XML_SCHEMAS_ANY_STRICT)
21552 printf("processContents: strict\n");
21553 else
21554 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000021555 if (type->attributeWildcard->any)
21556 printf("type: any\n");
21557 else if (type->attributeWildcard->negNsSet != NULL) {
21558 printf("type: negated\n");
21559 if (type->attributeWildcard->negNsSet->value == NULL)
21560 printf("ns: (absent)\n");
21561 else
21562 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
21563 } else if (type->attributeWildcard->nsSet != NULL) {
21564 printf("type: set\n");
21565 ns = type->attributeWildcard->nsSet;
21566 while (ns != NULL) {
21567 if (ns->value == NULL)
21568 printf("ns: (absent)\n");
21569 else
21570 printf("ns: %s\n", ns->value);
21571 ns = ns->next;
21572 }
21573 } else
21574 printf("empty\n");
21575
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000021576
21577#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000021578 curState = ctxt->attr;
21579 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000021580 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
21581 if (curState->attr->ns != NULL)
21582 nsURI = curState->attr->ns->href;
21583 else
21584 nsURI = NULL;
21585 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
21586 nsURI)) {
21587 /*
21588 * Handle processContents.
21589 */
21590 if ((type->attributeWildcard->processContents ==
21591 XML_SCHEMAS_ANY_LAX) ||
21592 (type->attributeWildcard->processContents ==
21593 XML_SCHEMAS_ANY_STRICT)) {
21594
21595 attr = curState->attr;
21596 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021597 attr->name, nsURI);
21598 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000021599 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000021600 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021601 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
21602 /* TODO
21603 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
21604 */
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000021605 } else if (type->attributeWildcard->processContents ==
21606 XML_SCHEMAS_ANY_LAX) {
21607 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021608 } else
21609 curState->state = XML_SCHEMAS_ATTR_WILD_NO_DECL;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000021610 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000021611 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021612 }
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000021613 }
Daniel Veillard3646d642004-06-02 19:19:14 +000021614 curState = curState->next;
21615 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021616 }
21617
Daniel Veillardc0826a72004-08-10 14:17:33 +000021618 if (ctxt->attr != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021619 int valueNeeded;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021620
21621 /*
21622 * Validate the value of the attribute.
21623 */
21624 if (ctxt->value != NULL) {
21625 xmlSchemaFreeValue(ctxt->value);
21626 ctxt->value = NULL;
21627 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000021628 curState = ctxt->attr;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021629 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021630 valueNeeded = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021631 switch (curState->state) {
21632 case XML_SCHEMAS_ATTR_VALIDATE_VALUE:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021633
21634 /*
21635 * Create an attribute info if needed.
21636 */
21637 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021638 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
21639 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021640 if (ctxt->attrInfo == NULL) {
21641 xmlSchemaVErrMemory(ctxt,
21642 "allocating an attribute info", NULL);
21643 goto fatal_exit;
21644 }
21645 }
21646 /*
21647 * Init the attribute info.
21648 */
21649 ctxt->attrInfo->flags = 0;
21650 ctxt->attrInfo->node = (xmlNodePtr) curState->attr;
21651 ctxt->attrInfo->decl = (xmlSchemaTypePtr) curState->decl;
21652 ctxt->attrInfo->value = NULL;
21653 if (curState->decl != NULL)
21654 ctxt->attrInfo->typeDef = curState->decl->subtypes;
21655 else
21656 ctxt->attrInfo->typeDef = NULL;
21657 if (curState->attr->ns != NULL)
21658 ctxt->attrInfo->namespaceName =
21659 curState->attr->ns->href;
21660 else
21661 ctxt->attrInfo->namespaceName = NULL;
21662 ctxt->attrInfo->localName = curState->attr->name;
21663
21664 ctxt->nodeInfo = ctxt->attrInfo;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021665 /*
21666 * Evaluate IDCs.
21667 */
21668 if (ctxt->xpathStates != NULL) {
21669 ret = xmlSchemaXPathEvaluate(ctxt,
21670 XML_ATTRIBUTE_NODE);
21671 if (ret == -1)
21672 goto fatal_exit;
21673 }
21674
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021675 ret = xmlSchemaCheckAttrLocallyValid(ctxt, curState);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021676 if (ret == -1)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021677 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021678 if ((ret != 0) && (ctxt->value != NULL)) {
21679 xmlSchemaFreeValue(ctxt->value);
21680 ctxt->value = NULL;
21681 }
21682 /* No break on purpose. */
21683 case XML_SCHEMAS_ATTR_CHECKED:
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021684 if (ctxt->xpathStates != NULL) {
21685 /*
21686 * Evaluate IDCs.
21687 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021688 if (ctxt->value != NULL) {
21689 ctxt->attrInfo->value = ctxt->value;
21690 ctxt->value = NULL;
21691 }
21692 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
21693 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021694 }
21695 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021696 default:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021697 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021698 }
21699 curState = curState->next;
21700 }
21701
21702 /*
21703 * Report missing and illegal attributes.
21704 */
21705 curState = ctxt->attr;
21706 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000021707 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
21708 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021709 if (curState->decl != NULL) {
21710 if (curState->decl->ref != NULL)
21711 attrDecl = curState->decl->refDecl;
21712 else
21713 attrDecl = curState->decl;
21714 } else
21715 attrDecl = NULL;
21716 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
21717 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
21718 } else if (curState->state ==
21719 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
21720 xmlSchemaVCustomErr(ctxt,
21721 XML_SCHEMAV_CVC_ATTRIBUTE_2,
21722 (xmlNodePtr) attr,
21723 (xmlSchemaTypePtr) attrDecl,
21724 "The type definition is absent",
21725 NULL);
21726 } else if (curState->state ==
21727 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
21728 xmlSchemaVCustomErr(ctxt,
21729 XML_SCHEMAV_CVC_AU,
21730 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
21731 "The value does not match the fixed value "
21732 "constraint", NULL);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000021733 } else if (curState->state == XML_SCHEMAS_ATTR_WILD_NO_DECL) {
21734 xmlSchemaVWildcardErr(ctxt,
21735 XML_SCHEMAV_CVC_WILDCARD,
21736 (xmlNodePtr) attr,
21737 type->attributeWildcard,
21738 "No global attribute declaration found, but "
21739 "stipulated by the strict processContents of "
21740 "the wildcard");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021741 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021742 /* TODO: "prohibited" won't ever be touched here!.
21743 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
21744 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021745 /*
21746 * TODO: One might report different error messages
21747 * for the following errors.
21748 */
21749 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000021750 xmlSchemaVIllegalAttrErr(ctxt,
21751 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
21752 } else {
21753 xmlSchemaVIllegalAttrErr(ctxt,
21754 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
21755 }
21756 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000021757 }
21758 curState = curState->next;
21759 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021760 }
21761
21762 /*
21763 * Add missing default/fixed attributes.
21764 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000021765 if (defAttrStates != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021766 curState = defAttrStates;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000021767
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021768 while (curState != NULL) {
21769 attrDecl = curState->decl;
21770 if (attrDecl->ref != NULL)
21771 attrDecl = attrDecl->refDecl;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000021772 /*
21773 * Evaluate IDCs on default attributes.
21774 */
21775 if (ctxt->xpathStates != NULL) {
21776 /*
21777 * Create an attribute info if needed.
21778 */
21779 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021780 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
21781 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000021782 if (ctxt->attrInfo == NULL) {
21783 xmlSchemaVErrMemory(ctxt,
21784 "allocating an attribute info", NULL);
21785 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021786 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021787 ctxt->attrInfo->value = NULL;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000021788 }
21789 /*
21790 * Init the attribute info.
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000021791 * TODO: Hmm, maby a bit oversized this all.
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000021792 */
21793 ctxt->attrInfo->flags = 0;
21794 ctxt->attrInfo->decl = (xmlSchemaTypePtr) attrDecl;
21795 ctxt->attrInfo->node = NULL;
21796 ctxt->attrInfo->typeDef = attrDecl->subtypes;
21797 ctxt->attrInfo->namespaceName = attrDecl->targetNamespace;
21798 ctxt->attrInfo->localName = attrDecl->name;
21799
21800 ctxt->nodeInfo = ctxt->attrInfo;
21801
21802 ret = xmlSchemaXPathEvaluate(ctxt,
21803 XML_ATTRIBUTE_NODE);
21804 if (ret == -1)
21805 goto fatal_exit;
21806 if (ctxt->attrInfo->value != NULL) {
21807 xmlSchemaFreeValue(ctxt->attrInfo->value);
21808 ctxt->attrInfo->value = NULL;
21809 }
21810 if (ret > 0) {
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000021811 /*
21812 * IDCs will consume the precomputed default value,
21813 * so we need to clone it somehow.
21814 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021815 /*
21816 * string or anySimpleType does not create a precomputed value
21817 * by default, so it will be created here on demand.
21818 * TODO: default/fixed attributes are a bit unoptimized:
21819 * the string value will be hold by ->defValue and inside
21820 * the precomputed value.
21821 */
21822 if (attrDecl->defVal == NULL) {
21823 xmlChar *str = xmlStrdup(attrDecl->defValue);
21824
21825 if (xmlSchemaPostCreateVal(ctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000021826 ctxt->attrInfo->typeDef,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000021827 str,
21828 &(attrDecl->defVal)) == -1) {
21829 FREE_AND_NULL(str)
21830 goto fatal_exit;
21831 }
21832 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000021833 ctxt->attrInfo->value = xmlSchemaCopyValue(attrDecl->defVal);
21834 /* TODO: error on NULL return. */
21835 }
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000021836
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000021837 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
21838 goto fatal_exit;
21839 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000021840
21841 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
21842 /*
21843 * PSVI: Add a new attribute node to the current element.
21844 */
21845 if (attrDecl->targetNamespace == NULL) {
21846 xmlNewProp(elem, attrDecl->name, curState->value);
21847 } else {
21848 xmlNsPtr ns;
21849
21850 ns = xmlSearchNsByHref(elem->doc, elem,
21851 attrDecl->targetNamespace);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021852 if (ns == NULL) {
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000021853 xmlChar prefix[12];
21854 int counter = 1;
21855
21856 attr = curState->attr;
21857 /*
21858 * Create a namespace declaration on the validation
21859 * root node if no namespace declaration is in scope.
21860 */
21861 snprintf((char *) prefix, sizeof(prefix), "p");
21862 /*
21863 * This is somehow not performant, since the ancestor
21864 * axis beyond @elem will be searched as well.
21865 */
21866 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
21867 while (ns != NULL) {
21868 if (counter > 1000) {
21869 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
21870 XML_SCHEMAV_INTERNAL,
21871 "Internal error: xmlSchemaValidateAttributes, "
21872 "could not compute a ns prefix for "
21873 "default/fixed attribute '%s'.\n",
21874 attrDecl->name, NULL);
21875
21876 break;
21877 }
21878 snprintf((char *) prefix,
21879 sizeof(prefix), "p%d", counter++);
21880 ns = xmlSearchNs(elem->doc, elem,
21881 BAD_CAST prefix);
21882 }
21883 if (ns == NULL) {
21884 ns = xmlNewNs(ctxt->validationRoot,
21885 attrDecl->targetNamespace, BAD_CAST prefix);
21886 xmlNewNsProp(elem, ns, attrDecl->name,
21887 curState->value);
21888 }
21889 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021890 xmlNewNsProp(elem, ns, attrDecl->name,
21891 curState->value);
21892 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021893 }
21894 }
21895 curState = curState->next;
21896 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000021897 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021898 ret = ctxt->err;
21899 goto exit;
21900
21901fatal_exit:
21902 ret = -1;
21903
21904exit:
21905
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021906 if (defAttrStates != NULL)
21907 xmlSchemaFreeAttributeStates(defAttrStates);
21908
Daniel Veillard3646d642004-06-02 19:19:14 +000021909#ifdef DEBUG_ATTR_VALIDATION
21910 if (redundant)
21911 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021912 "xmlSchemaValidateAttributes: redundant call by "
21913 "type: %s\n", type->name);
Daniel Veillard3646d642004-06-02 19:19:14 +000021914#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021915 ctxt->nodeInfo = ctxt->elemInfos[ctxt->depth];
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021916 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000021917 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000021918}
21919
21920/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000021921 * xmlSchemaStartValidation:
Daniel Veillard4255d502002-04-16 15:50:10 +000021922 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000021923 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000021924 * The starting point of the validation, called by
21925 * xmlSchemaValidateDocument and xmlSchemaValidateOneElement.
Daniel Veillard4255d502002-04-16 15:50:10 +000021926 *
21927 * Returns 0 if the element is schemas valid, a positive error code
21928 * number otherwise and -1 in case of internal or API error.
21929 */
21930static int
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000021931xmlSchemaStartValidation(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021932{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021933 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021934 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000021935
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000021936 ctxt->err = 0;
21937 ctxt->nberrors = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021938 if (ctxt->schema == NULL) {
21939 /*
21940 * No schema was specified at time of creation of the validation
21941 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
21942 * of the instance to build a schema.
21943 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021944 if (ctxt->pctxt == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000021945 if (xmlSchemaCreatePCtxtOnVCtxt(ctxt) == -1)
21946 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021947 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
21948 if (ctxt->schema == NULL)
21949 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021950 ctxt->xsiAssemble = 1;
21951 } else
21952 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021953 /*
21954 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000021955 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021956 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021957 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
21958 if (ret == -1) {
21959 xmlSchemaVCustomErr(ctxt,
21960 XML_SCHEMAV_INTERNAL,
21961 ctxt->node, NULL,
21962 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021963 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021964 }
21965 /*
21966 * NOTE: We won't react on schema parser errors here.
21967 * TODO: But a warning would be nice.
21968 */
21969 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021970 if (ret != -1) {
21971 if (ctxt->node->ns != NULL)
21972 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
21973 ctxt->node->ns->href);
21974 else
21975 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
21976
21977 if (elemDecl == NULL) {
21978 xmlSchemaVCustomErr(ctxt,
21979 XML_SCHEMAV_CVC_ELT_1,
21980 ctxt->node, NULL,
21981 "No matching global declaration available", NULL);
21982 ret = XML_SCHEMAV_CVC_ELT_1;
21983 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000021984 /*
21985 * Augment the IDC definitions.
21986 */
21987 if (ctxt->schema->idcDef != NULL) {
21988 xmlHashScan(ctxt->schema->idcDef,
21989 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
21990 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021991 ctxt->depth = -1;
21992 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021993 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000021994 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021995 if (ret < 0) {
21996 xmlSchemaVCustomErr(ctxt,
21997 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
21998 "Internal error: xmlSchemaValidateElement, "
21999 "calling validation by declaration", NULL);
22000 }
22001 }
22002 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022003
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022004 if (ctxt->xsiAssemble) {
22005 if (ctxt->schema != NULL) {
22006 xmlSchemaFree(ctxt->schema);
22007 ctxt->schema = NULL;
22008 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022009 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022010 xmlSchemaClearValidCtxt(ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022011 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000022012}
22013
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022014
Daniel Veillard4255d502002-04-16 15:50:10 +000022015/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022016 * xmlSchemaValidateOneElement:
22017 * @ctxt: a schema validation context
22018 * @elem: an element node
22019 *
22020 * Validate a branch of a tree, starting with the given @elem.
22021 *
22022 * Returns 0 if the element and its subtree is valid, a positive error
22023 * code number otherwise and -1 in case of an internal or API error.
22024 */
22025int
22026xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
22027{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022028 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022029 return (-1);
22030
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022031 if (ctxt->schema == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022032 xmlSchemaVErr(ctxt, NULL,
22033 XML_SCHEMAV_INTERNAL,
22034 "API error: xmlSchemaValidateOneElement, "
22035 "no schema specified.\n", NULL, NULL);
22036 return (-1);
22037 }
22038
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022039 ctxt->doc = elem->doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022040 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022041 ctxt->validationRoot = elem;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022042 return (xmlSchemaStartValidation(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000022043}
22044
22045/************************************************************************
22046 * *
22047 * SAX Validation code *
22048 * *
22049 ************************************************************************/
22050
22051/************************************************************************
22052 * *
22053 * Validation interfaces *
22054 * *
22055 ************************************************************************/
22056
22057/**
22058 * xmlSchemaNewValidCtxt:
22059 * @schema: a precompiled XML Schemas
22060 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022061 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000022062 *
22063 * Returns the validation context or NULL in case of error
22064 */
22065xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022066xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
22067{
Daniel Veillard4255d502002-04-16 15:50:10 +000022068 xmlSchemaValidCtxtPtr ret;
22069
22070 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
22071 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022072 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000022073 return (NULL);
22074 }
22075 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000022076 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000022077 return (ret);
22078}
22079
22080/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022081 * xmlSchemaClearValidCtxt:
22082 * @ctxt: the schema validation context
22083 *
22084 * Free the resources associated to the schema validation context;
22085 * leaves some fields alive intended for reuse of the context.
22086 */
22087static void
22088xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
22089{
22090 if (vctxt == NULL)
22091 return;
22092
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022093 vctxt->flags = 0;
22094
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022095 vctxt->validationRoot = NULL;
22096 if (vctxt->attr != NULL) {
22097 xmlSchemaFreeAttributeStates(vctxt->attr);
22098 vctxt->attr = NULL;
22099 }
22100 if (vctxt->value != NULL) {
22101 xmlSchemaFreeValue(vctxt->value);
22102 vctxt->value = NULL;
22103 }
22104 /*
22105 * Augmented IDC information.
22106 */
22107 if (vctxt->aidcs != NULL) {
22108 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
22109 do {
22110 next = cur->next;
22111 xmlFree(cur);
22112 cur = next;
22113 } while (cur != NULL);
22114 vctxt->aidcs = NULL;
22115 }
22116 if (vctxt->idcNodes != NULL) {
22117 int i;
22118 xmlSchemaPSVIIDCNodePtr item;
22119
22120 for (i = 0; i < vctxt->nbIdcNodes; i++) {
22121 item = vctxt->idcNodes[i];
22122 xmlFree(item->keys);
22123 xmlFree(item);
22124 }
22125 xmlFree(vctxt->idcNodes);
22126 vctxt->idcNodes = NULL;
22127 }
22128 /*
22129 * Note that we won't delete the XPath state pool here.
22130 */
22131 if (vctxt->xpathStates != NULL) {
22132 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
22133 vctxt->xpathStates = NULL;
22134 }
22135 if (vctxt->attrInfo != NULL) {
22136 if (vctxt->attrInfo->value != NULL) {
22137 xmlSchemaFreeValue(vctxt->attrInfo->value);
22138 }
22139 memset(vctxt->attrInfo, 0, sizeof(xmlSchemaNodeInfo));
22140 }
22141 if (vctxt->elemInfos != NULL) {
22142 int i;
22143 xmlSchemaNodeInfoPtr info;
22144
22145 for (i = 0; i < vctxt->sizeElemInfos; i++) {
22146 info = vctxt->elemInfos[i];
22147 if (info == NULL)
22148 break;
22149 if (info->value != NULL) {
22150 xmlSchemaFreeValue(info->value);
22151 info->value = NULL;
22152 }
22153 if (info->idcMatchers != NULL) {
22154 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
22155 info->idcMatchers = NULL;
22156 }
22157 if (info->idcTable != NULL) {
22158 xmlSchemaIDCFreeIDCTable(info->idcTable);
22159 info->idcTable = NULL;
22160 }
22161 }
22162 }
22163}
22164
22165/**
Daniel Veillard4255d502002-04-16 15:50:10 +000022166 * xmlSchemaFreeValidCtxt:
22167 * @ctxt: the schema validation context
22168 *
22169 * Free the resources associated to the schema validation context
22170 */
22171void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022172xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
22173{
Daniel Veillard4255d502002-04-16 15:50:10 +000022174 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022175 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000022176 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000022177 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000022178 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022179 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022180 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022181 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022182 if (ctxt->idcNodes != NULL) {
22183 int i;
22184 xmlSchemaPSVIIDCNodePtr item;
22185
22186 for (i = 0; i < ctxt->nbIdcNodes; i++) {
22187 item = ctxt->idcNodes[i];
22188 xmlFree(item->keys);
22189 xmlFree(item);
22190 }
22191 xmlFree(ctxt->idcNodes);
22192 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022193 if (ctxt->idcKeys != NULL) {
22194 int i;
22195 for (i = 0; i < ctxt->nbIdcKeys; i++)
22196 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
22197 xmlFree(ctxt->idcKeys);
22198 }
22199
22200 if (ctxt->xpathStates != NULL)
22201 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
22202 if (ctxt->xpathStatePool != NULL)
22203 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
22204
22205 /*
22206 * Augmented IDC information.
22207 */
22208 if (ctxt->aidcs != NULL) {
22209 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
22210 do {
22211 next = cur->next;
22212 xmlFree(cur);
22213 cur = next;
22214 } while (cur != NULL);
22215 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022216 if (ctxt->attrInfo != NULL) {
22217 if (ctxt->attrInfo->value != NULL)
22218 xmlSchemaFreeValue(ctxt->attrInfo->value);
22219 xmlFree(ctxt->attrInfo);
22220 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022221 if (ctxt->elemInfos != NULL) {
22222 int i;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022223 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000022224
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022225 for (i = 0; i < ctxt->sizeElemInfos; i++) {
22226 info = ctxt->elemInfos[i];
22227 if (info == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022228 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022229 if (info->value != NULL)
22230 xmlSchemaFreeValue(info->value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022231 if (info->idcMatchers != NULL)
22232 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022233 if (info->idcTable != NULL)
22234 xmlSchemaIDCFreeIDCTable(info->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022235 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022236 * TODO: Don't know if those will have to be freed if in streaming
22237 * mode.
22238 *
22239 * xmlFree(info->localName);
22240 * if (info->namespaceName != NULL)
22241 * xmlFree(info->namespaceName);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022242 */
22243 xmlFree(info);
22244 }
22245 xmlFree(ctxt->elemInfos);
22246 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022247 xmlFree(ctxt);
22248}
22249
22250/**
22251 * xmlSchemaSetValidErrors:
22252 * @ctxt: a schema validation context
22253 * @err: the error function
22254 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000022255 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000022256 *
William M. Brack2f2a6632004-08-20 23:09:47 +000022257 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000022258 */
22259void
22260xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022261 xmlSchemaValidityErrorFunc err,
22262 xmlSchemaValidityWarningFunc warn, void *ctx)
22263{
Daniel Veillard4255d502002-04-16 15:50:10 +000022264 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022265 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000022266 ctxt->error = err;
22267 ctxt->warning = warn;
22268 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022269 if (ctxt->pctxt != NULL)
22270 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000022271}
22272
22273/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000022274 * xmlSchemaGetValidErrors:
22275 * @ctxt: a XML-Schema validation context
22276 * @err: the error function result
22277 * @warn: the warning function result
22278 * @ctx: the functions context result
22279 *
22280 * Get the error and warning callback informations
22281 *
22282 * Returns -1 in case of error and 0 otherwise
22283 */
22284int
22285xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
22286 xmlSchemaValidityErrorFunc * err,
22287 xmlSchemaValidityWarningFunc * warn, void **ctx)
22288{
22289 if (ctxt == NULL)
22290 return (-1);
22291 if (err != NULL)
22292 *err = ctxt->error;
22293 if (warn != NULL)
22294 *warn = ctxt->warning;
22295 if (ctx != NULL)
22296 *ctx = ctxt->userData;
22297 return (0);
22298}
22299
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022300
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022301/**
Daniel Veillard6927b102004-10-27 17:29:04 +000022302 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022303 * @ctxt: a schema validation context
22304 * @options: a combination of xmlSchemaValidOption
22305 *
22306 * Sets the options to be used during the validation.
22307 *
22308 * Returns 0 in case of success, -1 in case of an
22309 * API error.
22310 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022311int
22312xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
22313 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022314
22315{
22316 int i;
22317
22318 if (ctxt == NULL)
22319 return (-1);
22320 /*
22321 * WARNING: Change the start value if adding to the
22322 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022323 * TODO: Is there an other, more easy to maintain,
22324 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022325 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022326 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022327 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022328 xmlSchemaVErr(ctxt, NULL,
22329 XML_SCHEMAV_INTERNAL,
22330 "Internal error: xmlSchemaSetValidOptions, "
22331 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022332 return (-1);
22333 }
22334 }
22335 ctxt->options = options;
22336 return (0);
22337}
22338
22339/**
Daniel Veillard6927b102004-10-27 17:29:04 +000022340 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022341 * @ctxt: a schema validation context
22342 *
William M. Brack21e4ef22005-01-02 09:53:13 +000022343 * Get the validation context options.
22344 *
22345 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022346 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022347int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022348xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
22349
22350{
22351 if (ctxt == NULL)
22352 return (-1);
22353 else
22354 return (ctxt->options);
22355}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022356
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022357
Daniel Veillard259f0df2004-08-18 09:13:18 +000022358/**
Daniel Veillard4255d502002-04-16 15:50:10 +000022359 * xmlSchemaValidateDoc:
22360 * @ctxt: a schema validation context
22361 * @doc: a parsed document tree
22362 *
22363 * Validate a document tree in memory.
22364 *
22365 * Returns 0 if the document is schemas valid, a positive error code
22366 * number otherwise and -1 in case of internal or API error.
22367 */
22368int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022369xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
22370{
Daniel Veillard4255d502002-04-16 15:50:10 +000022371 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022372 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022373
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022374 ctxt->doc = doc;
22375 ctxt->node = xmlDocGetRootElement(doc);
22376 if (ctxt->node == NULL) {
22377 xmlSchemaVCustomErr(ctxt,
22378 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
22379 (xmlNodePtr) doc, NULL,
22380 "The document has no document element", NULL);
22381 return (ctxt->err);
22382 }
22383 ctxt->validationRoot = ctxt->node;
22384 xmlSchemaStartValidation(ctxt);
22385
22386 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000022387}
22388
22389/**
22390 * xmlSchemaValidateStream:
22391 * @ctxt: a schema validation context
22392 * @input: the input to use for reading the data
22393 * @enc: an optional encoding information
22394 * @sax: a SAX handler for the resulting events
22395 * @user_data: the context to provide to the SAX handler.
22396 *
22397 * Validate a document tree in memory.
22398 *
22399 * Returns 0 if the document is schemas valid, a positive error code
22400 * number otherwise and -1 in case of internal or API error.
22401 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022402int
Daniel Veillard4255d502002-04-16 15:50:10 +000022403xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022404 xmlParserInputBufferPtr input, xmlCharEncoding enc,
22405 xmlSAXHandlerPtr sax, void *user_data)
22406{
Daniel Veillard4255d502002-04-16 15:50:10 +000022407 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022408 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022409 ctxt->input = input;
22410 ctxt->enc = enc;
22411 ctxt->sax = sax;
22412 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000022413 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022414}
22415
Daniel Veillard5d4644e2005-04-01 13:11:58 +000022416#define bottom_xmlschemas
22417#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000022418#endif /* LIBXML_SCHEMAS_ENABLED */