blob: 4852b6c9710a5a4f606c1833e53ade6081bf6854 [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.
Daniel Veillardb0f397e2003-12-23 23:30:53 +000018 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019#define IN_LIBXML
20#include "libxml.h"
21
22#ifdef LIBXML_SCHEMAS_ENABLED
23
24#include <string.h>
25#include <libxml/xmlmemory.h>
26#include <libxml/parser.h>
27#include <libxml/parserInternals.h>
28#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000029#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000030
31#include <libxml/xmlschemas.h>
32#include <libxml/schemasInternals.h>
33#include <libxml/xmlschemastypes.h>
34#include <libxml/xmlautomata.h>
35#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000036#include <libxml/dict.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000037#ifdef LIBXML_PATTERN_ENABLED
38#include <libxml/pattern.h>
39#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000040
Daniel Veillarda84c0b32003-06-02 16:58:46 +000041/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000042
Daniel Veillard82bbbd42003-05-11 20:16:09 +000043/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000044
Daniel Veillard82bbbd42003-05-11 20:16:09 +000045/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000046
Daniel Veillard118aed72002-09-24 14:13:13 +000047/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000048
Daniel Veillard4255d502002-04-16 15:50:10 +000049/* #define DEBUG_AUTOMATA 1 */
50
Daniel Veillard3646d642004-06-02 19:19:14 +000051/* #define DEBUG_ATTR_VALIDATION 1 */
52
Daniel Veillardc0826a72004-08-10 14:17:33 +000053/* #define DEBUG_UNION_VALIDATION 1 */
54
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000055#define ELEM_INFO_ENABLED 1
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000056
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000057/* #define IDC_ENABLED 1 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000058
59/* #define IDC_VALUE_SUPPORT 1 */
60
61/* #define IDC_XPATH_SUPPORT 1 */
62
63/* #define DEBUG_IDC 1 */
64
Daniel Veillardc0826a72004-08-10 14:17:33 +000065
Daniel Veillard4255d502002-04-16 15:50:10 +000066#define UNBOUNDED (1 << 30)
67#define TODO \
68 xmlGenericError(xmlGenericErrorContext, \
69 "Unimplemented block at %s:%d\n", \
70 __FILE__, __LINE__);
71
William M. Brack2f2a6632004-08-20 23:09:47 +000072#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000073
Daniel Veillard4255d502002-04-16 15:50:10 +000074/*
75 * The XML Schemas namespaces
76 */
77static const xmlChar *xmlSchemaNs = (const xmlChar *)
78 "http://www.w3.org/2001/XMLSchema";
79
80static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
81 "http://www.w3.org/2001/XMLSchema-instance";
82
Daniel Veillardc0826a72004-08-10 14:17:33 +000083static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
84 "Element decl.";
85static const xmlChar *xmlSchemaElemDesElemRef = (const xmlChar *)
86 "Element ref.";
87static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
88 "Attribute decl.";
89static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
90 "Attribute ref.";
91static const xmlChar *xmlSchemaElemDesST = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000092 "simple type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000093static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000094 "complex type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000095
Daniel Veillard4255d502002-04-16 15:50:10 +000096#define IS_SCHEMA(node, type) \
97 ((node != NULL) && (node->ns != NULL) && \
98 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
99 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
100
Daniel Veillardc0826a72004-08-10 14:17:33 +0000101#define FREE_AND_NULL(str) \
102 if (str != NULL) { \
103 xmlFree(str); \
104 str = NULL; \
105 }
106
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000107#define IS_ANYTYPE(item) \
108 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
109 (item->builtInType == XML_SCHEMAS_ANYTYPE))
110
111#define IS_COMPLEX_TYPE(item) \
112 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
113 (item->builtInType == XML_SCHEMAS_ANYTYPE))
114
115#define IS_SIMPLE_TYPE(item) \
116 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
117 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
118 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
119
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +0000120/*
Daniel Veillardc0826a72004-08-10 14:17:33 +0000121#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
122#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
123#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +0000124*/
Daniel Veillardc0826a72004-08-10 14:17:33 +0000125
Daniel Veillard4255d502002-04-16 15:50:10 +0000126#define XML_SCHEMAS_PARSE_ERROR 1
127
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000128#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
129
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000130
131/*
132* XML_SCHEMA_VAL_XSI_ASSEMBLE_TNS_COMPOSE
133* allow to assemble schemata with
134* the same target namespace from
135* different sources; otherwise, the first
136* encountered schema with a specific target
137* namespace will be used only *
138
139*
140* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
141* locate schemata to be imported
142* using the namespace name; otherwise
143* the location URI will be used */
144
145/*
146* xmlSchemaParserOption:
147*
148* This is the set of XML Schema parser options.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000149*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000150typedef enum {
151 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000152 * locate schemata to be imported
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000153 * using the namespace name; otherwise
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000154 * the location URI will be used *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000155} xmlSchemaParserOption;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000156*/
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000157
158/*
159XMLPUBFUN int XMLCALL
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000160 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
161 int options);
162XMLPUBFUN int XMLCALL
163 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt);
164
165*/
166
167typedef struct _xmlSchemaAssemble xmlSchemaAssemble;
168typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
169struct _xmlSchemaAssemble {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000170 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000171 int nbItems; /* used for dynamic addition of schemata */
172 int sizeItems; /* used for dynamic addition of schemata */
173};
174
Daniel Veillard4255d502002-04-16 15:50:10 +0000175struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000176 void *userData; /* user specific data block */
177 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
178 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000179 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000180 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000181 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000182
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000183 xmlSchemaPtr topschema; /* The main schema */
184 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
185
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000186 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000187 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000188 int counter;
189
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000190 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000191 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000192 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000193
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000194 const char *buffer;
195 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000196
Daniel Veillard4255d502002-04-16 15:50:10 +0000197 /*
198 * Used to build complex element content models
199 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000200 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000201 xmlAutomataStatePtr start;
202 xmlAutomataStatePtr end;
203 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000204
205 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000206 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000207 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
208 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000209 xmlSchemaAssemblePtr assemble;
210 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000211 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard4255d502002-04-16 15:50:10 +0000212};
213
214
215#define XML_SCHEMAS_ATTR_UNKNOWN 1
216#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000217#define XML_SCHEMAS_ATTR_PROHIBITED 3
218#define XML_SCHEMAS_ATTR_MISSING 4
219#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
220#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000221#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
222#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000223#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
224#define XML_SCHEMAS_ATTR_WILD_NO_DECL 10
Daniel Veillard4255d502002-04-16 15:50:10 +0000225
226typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
227typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
228struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000229 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000230 xmlAttrPtr attr;
231 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000232 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000233 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000234};
235
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000236typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
237typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
238struct _xmlSchemaBasicItem {
239 xmlSchemaTypeType type;
240 xmlSchemaAnnotPtr annot;
241};
242
243typedef struct _xmlSchemaItemQNRef xmlSchemaItemQNRef;
244typedef xmlSchemaItemQNRef *xmlSchemaItemQNRefPtr;
245struct _xmlSchemaItemQNRef {
246 xmlSchemaBasicItemPtr item;
247 const xmlChar *name;
248 const xmlChar *targetNamespace;
249};
250
251typedef struct _xmlSchemaIDC xmlSchemaIDC;
252typedef xmlSchemaIDC *xmlSchemaIDCPtr;
253
254/**
255 * xmlSchemaIDCSelect:
256 *
257 * The identity-constraint "field" and "selector" item, holding the
258 * XPath expression.
259 */
260typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
261typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
262struct _xmlSchemaIDCSelect {
263 xmlSchemaIDCSelectPtr next;
264 xmlSchemaIDCPtr idc;
265 int index; /* an index position if significant for IDC key-sequences */
266 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000267 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000268};
269
270/**
271 * xmlSchemaIDC:
272 *
273 * The identity-constraint definition component.
274 */
275
276struct _xmlSchemaIDC {
277 xmlSchemaTypeType type;
278 xmlSchemaAnnotPtr annot;
279 xmlSchemaIDCPtr next;
280 xmlNodePtr node;
281 const xmlChar *name;
282 const xmlChar *targetNamespace;
283 xmlSchemaIDCSelectPtr selector;
284 xmlSchemaIDCSelectPtr fields;
285 int nbFields;
286 xmlSchemaItemQNRefPtr ref;
287};
288
289/**
290 * xmlSchemaIDCAug:
291 *
292 * The augmented IDC information used for validation.
293 */
294typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
295typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
296struct _xmlSchemaIDCAug {
297 xmlSchemaIDCAugPtr next; /* next in a list */
298 xmlSchemaIDCPtr def; /* the IDC definition */
299 int bubbleDepth; /* the lowest level to which IDC
300 tables need to be bubbled upwards */
301};
302
303/**
304 * xmlSchemaPSVIIDCKeySequence:
305 *
306 * The key sequence of a node table item.
307 */
308typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
309typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
310struct _xmlSchemaPSVIIDCKey {
311 xmlSchemaTypePtr type;
312 xmlSchemaValPtr compValue;
313};
314
315/**
316 * xmlSchemaPSVIIDCNode:
317 *
318 * The node table item of a node table.
319 */
320typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
321typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
322struct _xmlSchemaPSVIIDCNode {
323 xmlNodePtr node;
324 xmlSchemaPSVIIDCKeyPtr *keys;
325};
326
327/**
328 * xmlSchemaPSVIIDCBinding:
329 *
330 * The identity-constraint binding item of the [identity-constraint table].
331 */
332typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
333typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
334struct _xmlSchemaPSVIIDCBinding {
335 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
336 xmlSchemaIDCPtr definition; /* the IDC definition */
337 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
338 int nbNodes; /* number of entries in the node table */
339 int sizeNodes; /* size of the node table */
340 int nbDupls; /* number of already identified duplicates in the node
341 table */
342 /* int nbKeys; number of keys in each key-sequence */
343};
344
345#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
346#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
347
348#define XPATH_STATE_OBJ_MATCHES -2
349#define XPATH_STATE_OBJ_BLOCKED -3
350
351typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
352typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
353
354/**
355 * xmlSchemaIDCStateObj:
356 *
357 * The state object used to evaluate XPath expressions.
358 */
359typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
360typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
361struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000362 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000363 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000364 int depth; /* depth of creation */
365 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000366 int nbHistory;
367 int sizeHistory;
368 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
369 matcher */
370 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000371 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000372};
373
374#define IDC_MATCHER 0
375
376/**
377 * xmlSchemaIDCMatcher:
378 *
379 * Used to IDC selectors (and fields) successively.
380 */
381struct _xmlSchemaIDCMatcher {
382 int type;
383 int depth; /* the tree depth at creation time */
384 xmlSchemaIDCMatcherPtr next; /* next in the list */
385 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
386 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
387 elements */
388 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000389 int targetDepth;
390};
391
392/*
393* Element info flags.
394*/
395#define XML_SCHEMA_ELEM_INFO_VALUE_NEEDED 1<<0
396
397/**
398 * xmlSchemaElemInfo:
399 *
400 * Holds information of an element node.
401 */
402typedef struct _xmlSchemaElemInfo xmlSchemaElemInfo;
403typedef xmlSchemaElemInfo *xmlSchemaElemInfoPtr;
404struct _xmlSchemaElemInfo {
405 int depth;
406 int flags; /* combination of element info flags */
407 xmlNodePtr node;
408 const xmlChar *localName;
409 const xmlChar *namespaceName;
410 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +0000411 xmlSchemaTypePtr decl; /* the element/attribute declaration */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000412 xmlSchemaValPtr value; /* the pre-computed value if any */
413 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
414 for the scope element*/
415 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
416 element */
417};
418
Daniel Veillard4255d502002-04-16 15:50:10 +0000419/**
420 * xmlSchemaValidCtxt:
421 *
422 * A Schemas validation context
423 */
424
425struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000426 void *userData; /* user specific data block */
427 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000428 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000429 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000430
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000431 xmlSchemaPtr schema; /* The schema in use */
432 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000433 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000434 xmlCharEncoding enc;
435 xmlSAXHandlerPtr sax;
436 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000437
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000438 xmlDocPtr myDoc;
439 int err;
440 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000441
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000442 xmlNodePtr node;
443 xmlNodePtr cur;
444 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000445
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000446 xmlRegExecCtxtPtr regexp;
447 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000448
Daniel Veillard3646d642004-06-02 19:19:14 +0000449 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000450 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000451 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000452 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000453 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000454 xmlNodePtr validationRoot;
455 xmlSchemaParserCtxtPtr pctxt;
456 int xsiAssemble;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000457#ifdef ELEM_INFO_ENABLED
458 int depth;
459 xmlSchemaElemInfoPtr *elemInfos; /* array of element informations */
460 int sizeElemInfos;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +0000461 xmlSchemaElemInfoPtr nodeInfo; /* the current element information */
462 xmlSchemaElemInfoPtr attrInfo; /* node infor for the current attribute */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000463#endif
464#ifdef IDC_ENABLED
465 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
466
467 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
468 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
469
470 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
471 int nbIdcNodes;
472 int sizeIdcNodes;
473
474 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
475 int nbIdcKeys;
476 int sizeIdcKeys;
477#endif
Daniel Veillard4255d502002-04-16 15:50:10 +0000478};
479
Daniel Veillard1d913862003-11-21 00:28:39 +0000480/*
481 * These are the entries in the schemas importSchemas hash table
482 */
483typedef struct _xmlSchemaImport xmlSchemaImport;
484typedef xmlSchemaImport *xmlSchemaImportPtr;
485struct _xmlSchemaImport {
486 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000487 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000488 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000489 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000490};
Daniel Veillard4255d502002-04-16 15:50:10 +0000491
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000492/*
493 * These are the entries associated to includes in a schemas
494 */
495typedef struct _xmlSchemaInclude xmlSchemaInclude;
496typedef xmlSchemaInclude *xmlSchemaIncludePtr;
497struct _xmlSchemaInclude {
498 xmlSchemaIncludePtr next;
499
500 const xmlChar *schemaLocation;
501 xmlDocPtr doc;
502};
503
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000504typedef struct _xmlSchemaParticle xmlSchemaParticle;
505typedef xmlSchemaParticle *xmlSchemaParticlePtr;
506struct _xmlSchemaParticle {
507 xmlSchemaTypeType type;
508 xmlSchemaParticlePtr next; /* the next particle if in a list */
509 int minOccurs;
510 int maxOccurs;
511 xmlSchemaTypePtr term;
512};
513
514
515typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
516typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
517struct _xmlSchemaModelGroup {
518 xmlSchemaTypeType type;
519 int compositor; /* one of all, choice or sequence */
520 xmlSchemaParticlePtr particles; /* list of particles */
521 xmlSchemaAnnotPtr annot;
522};
523
524typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
525typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
526struct _xmlSchemaModelGroupDef {
527 xmlSchemaTypeType type;
528 const xmlChar *name;
529 const xmlChar *targetNamespace;
530 xmlSchemaModelGroupPtr modelGroup;
531 xmlSchemaAnnotPtr annot;
532};
533
Daniel Veillard4255d502002-04-16 15:50:10 +0000534/************************************************************************
535 * *
536 * Some predeclarations *
537 * *
538 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000539
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000540static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
541 xmlSchemaPtr schema,
542 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000543static void
544xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
545 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
546static const char *
547xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
548static int
549xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000550 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000551 const xmlChar *value,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000552 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000553 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000554 int normalize,
555 int checkNodes);
556static int
557xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
558 xmlSchemaElementPtr elemDecl);
559static int
560xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
561 xmlSchemaTypePtr type);
562static int
563xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000564static int
565xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
566 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000567static void
568xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
569 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
William M. Brack87640d52004-04-17 14:58:15 +0000570
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000571/************************************************************************
572 * *
573 * Datatype error handlers *
574 * *
575 ************************************************************************/
576
577/**
578 * xmlSchemaPErrMemory:
579 * @node: a context node
580 * @extra: extra informations
581 *
582 * Handle an out of memory condition
583 */
584static void
585xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
586 const char *extra, xmlNodePtr node)
587{
588 if (ctxt != NULL)
589 ctxt->nberrors++;
590 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
591 extra);
592}
593
594/**
595 * xmlSchemaPErr:
596 * @ctxt: the parsing context
597 * @node: the context node
598 * @error: the error code
599 * @msg: the error message
600 * @str1: extra data
601 * @str2: extra data
602 *
603 * Handle a parser error
604 */
605static void
606xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
607 const char *msg, const xmlChar * str1, const xmlChar * str2)
608{
609 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000610 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000611 void *data = NULL;
612
613 if (ctxt != NULL) {
614 ctxt->nberrors++;
615 channel = ctxt->error;
616 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000617 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000618 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000619 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000620 error, XML_ERR_ERROR, NULL, 0,
621 (const char *) str1, (const char *) str2, NULL, 0, 0,
622 msg, str1, str2);
623}
624
625/**
626 * xmlSchemaPErr2:
627 * @ctxt: the parsing context
628 * @node: the context node
629 * @node: the current child
630 * @error: the error code
631 * @msg: the error message
632 * @str1: extra data
633 * @str2: extra data
634 *
635 * Handle a parser error
636 */
637static void
638xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
639 xmlNodePtr child, int error,
640 const char *msg, const xmlChar * str1, const xmlChar * str2)
641{
642 if (child != NULL)
643 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
644 else
645 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
646}
647
Daniel Veillard01fa6152004-06-29 17:04:39 +0000648
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000649/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000650 * xmlSchemaPErrExt:
651 * @ctxt: the parsing context
652 * @node: the context node
653 * @error: the error code
654 * @strData1: extra data
655 * @strData2: extra data
656 * @strData3: extra data
657 * @msg: the message
658 * @str1: extra parameter for the message display
659 * @str2: extra parameter for the message display
660 * @str3: extra parameter for the message display
661 * @str4: extra parameter for the message display
662 * @str5: extra parameter for the message display
663 *
664 * Handle a parser error
665 */
666static void
667xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
668 const xmlChar * strData1, const xmlChar * strData2,
669 const xmlChar * strData3, const char *msg, const xmlChar * str1,
670 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
671 const xmlChar * str5)
672{
673
674 xmlGenericErrorFunc channel = NULL;
675 xmlStructuredErrorFunc schannel = NULL;
676 void *data = NULL;
677
678 if (ctxt != NULL) {
679 ctxt->nberrors++;
680 channel = ctxt->error;
681 data = ctxt->userData;
682 schannel = ctxt->serror;
683 }
684 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
685 error, XML_ERR_ERROR, NULL, 0,
686 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000687 (const char *) strData3, 0, 0, msg, str1, str2,
688 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000689}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000690
Daniel Veillard3646d642004-06-02 19:19:14 +0000691
692/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000693 * xmlSchemaVTypeErrMemory:
694 * @node: a context node
695 * @extra: extra informations
696 *
697 * Handle an out of memory condition
698 */
699static void
700xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
701 const char *extra, xmlNodePtr node)
702{
703 if (ctxt != NULL) {
704 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000705 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000706 }
707 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
708 extra);
709}
710
711/**
712 * xmlSchemaVErr3:
713 * @ctxt: the validation context
714 * @node: the context node
715 * @error: the error code
716 * @msg: the error message
717 * @str1: extra data
718 * @str2: extra data
719 * @str3: extra data
720 *
721 * Handle a validation error
722 */
723static void
724xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
725 const char *msg, const xmlChar *str1, const xmlChar *str2,
726 const xmlChar *str3)
727{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000728 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000729 xmlGenericErrorFunc channel = NULL;
730 void *data = NULL;
731
732 if (ctxt != NULL) {
733 ctxt->nberrors++;
734 ctxt->err = error;
735 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000736 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000737 data = ctxt->userData;
738 }
739 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000740 /* Removed, since the old schema error codes have been
741 * substituted for the global error codes.
742 *
743 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
744 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000745 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000746 error, XML_ERR_ERROR, NULL, 0,
747 (const char *) str1, (const char *) str2,
748 (const char *) str3, 0, 0,
749 msg, str1, str2, str3);
750}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000751
752/**
753 * xmlSchemaVErrExt:
754 * @ctxt: the validation context
755 * @node: the context node
756 * @error: the error code
757 * @msg: the message
758 * @str1: extra parameter for the message display
759 * @str2: extra parameter for the message display
760 * @str3: extra parameter for the message display
761 * @str4: extra parameter for the message display
762 * @str5: extra parameter for the message display
763 *
764 * Handle a validation error
765 */
766static void
767xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
768 const char *msg, const xmlChar * str1,
769 const xmlChar * str2, const xmlChar * str3,
770 const xmlChar * str4, const xmlChar * str5)
771{
772 xmlStructuredErrorFunc schannel = NULL;
773 xmlGenericErrorFunc channel = NULL;
774 void *data = NULL;
775
776 if (ctxt != NULL) {
777 ctxt->nberrors++;
778 ctxt->err = error;
779 channel = ctxt->error;
780 schannel = ctxt->serror;
781 data = ctxt->userData;
782 }
783 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000784 /* Removed, since the old schema error codes have been
785 * substituted for the global error codes.
786 *
787 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
788 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000789 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
790 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
791 msg, str1, str2, str3, str4, str5);
792}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000793/**
794 * xmlSchemaVErr:
795 * @ctxt: the validation context
796 * @node: the context node
797 * @error: the error code
798 * @msg: the error message
799 * @str1: extra data
800 * @str2: extra data
801 *
802 * Handle a validation error
803 */
804static void
805xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
806 const char *msg, const xmlChar * str1, const xmlChar * str2)
807{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000808 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000809 xmlGenericErrorFunc channel = NULL;
810 void *data = NULL;
811
812 if (ctxt != NULL) {
813 ctxt->nberrors++;
814 ctxt->err = error;
815 channel = ctxt->error;
816 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000817 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000818 }
819 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000820 /* Removed, since the old schema error codes have been
821 * substituted for the global error codes.
822 *
823 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
824 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000825 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000826 error, XML_ERR_ERROR, NULL, 0,
827 (const char *) str1, (const char *) str2, NULL, 0, 0,
828 msg, str1, str2);
829}
Daniel Veillard4255d502002-04-16 15:50:10 +0000830
Daniel Veillardc0826a72004-08-10 14:17:33 +0000831/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000832 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000833 * @attr: the attribute declaration/use
834 *
835 * Returns the name of the attribute; if the attribute
836 * is a reference, the name of the referenced global type will be returned.
837 */
838static const xmlChar *
839xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
840{
841 if (attr->ref != NULL)
842 return(attr->ref);
843 else
844 return(attr->name);
845}
846
847/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000848 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000849 * @type: the type (element or attribute)
850 *
851 * Returns the target namespace URI of the type; if the type is a reference,
852 * the target namespace of the referenced type will be returned.
853 */
854static const xmlChar *
855xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
856{
857 if (attr->ref != NULL)
858 return (attr->refNs);
859 else
860 return(attr->targetNamespace);
861}
862
863/**
864 * xmlSchemaFormatNsUriLocal:
865 * @buf: the string buffer
866 * @uri: the namespace URI
867 * @local: the local name
868 *
869 * Returns a representation of the given URI used
870 * for error reports.
871 *
872 * Returns an empty string, if @ns is NULL, a formatted
873 * string otherwise.
874 */
875static const xmlChar*
876xmlSchemaFormatNsUriLocal(xmlChar **buf,
877 const xmlChar *uri, const xmlChar *local)
878{
879 if (*buf != NULL)
880 xmlFree(*buf);
881 if (uri == NULL) {
882 *buf = xmlStrdup(BAD_CAST "{'");
883 *buf = xmlStrcat(*buf, local);
884 } else {
885 *buf = xmlStrdup(BAD_CAST "{'");
886 *buf = xmlStrcat(*buf, uri);
887 *buf = xmlStrcat(*buf, BAD_CAST "', '");
888 *buf = xmlStrcat(*buf, local);
889 }
890 *buf = xmlStrcat(*buf, BAD_CAST "'}");
891 return ((const xmlChar *) *buf);
892}
893
894/**
895 * xmlSchemaFormatNsPrefixLocal:
896 * @buf: the string buffer
897 * @ns: the namespace
898 * @local: the local name
899 *
900 * Returns a representation of the given URI used
901 * for error reports.
902 *
903 * Returns an empty string, if @ns is NULL, a formatted
904 * string otherwise.
905 */
906static const xmlChar*
907xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
908 xmlNsPtr ns, const xmlChar *local)
909{
910 if (*buf != NULL) {
911 xmlFree(*buf);
912 *buf = NULL;
913 }
914 if ((ns == NULL) || (ns->prefix == NULL))
915 return(local);
916 else {
917 *buf = xmlStrdup(ns->prefix);
918 *buf = xmlStrcat(*buf, BAD_CAST ":");
919 *buf = xmlStrcat(*buf, local);
920 }
921 return ((const xmlChar *) *buf);
922}
923
924/**
925 * xmlSchemaFormatItemForReport:
926 * @buf: the string buffer
927 * @itemDes: the designation of the item
928 * @itemName: the name of the item
929 * @item: the item as an object
930 * @itemNode: the node of the item
931 * @local: the local name
932 * @parsing: if the function is used during the parse
933 *
934 * Returns a representation of the given item used
935 * for error reports.
936 *
937 * The following order is used to build the resulting
938 * designation if the arguments are not NULL:
939 * 1a. If itemDes not NULL -> itemDes
940 * 1b. If (itemDes not NULL) and (itemName not NULL)
941 * -> itemDes + itemName
942 * 2. If the preceding was NULL and (item not NULL) -> item
943 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
944 *
945 * If the itemNode is an attribute node, the name of the attribute
946 * will be appended to the result.
947 *
948 * Returns the formatted string and sets @buf to the resulting value.
949 */
950static xmlChar*
951xmlSchemaFormatItemForReport(xmlChar **buf,
952 const xmlChar *itemDes,
953 xmlSchemaTypePtr item,
954 xmlNodePtr itemNode,
955 int parsing)
956{
957 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +0000958 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000959
960 if (*buf != NULL) {
961 xmlFree(*buf);
962 *buf = NULL;
963 }
964
William M. Brack2f2a6632004-08-20 23:09:47 +0000965 if (itemDes != NULL) {
966 *buf = xmlStrdup(itemDes);
967 } else if (item != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000968 switch (item->type) {
969 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000970 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
971 *buf = xmlStrdup(BAD_CAST "'anyType'");
972 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
973 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
974 else {
975 /* *buf = xmlStrdup(BAD_CAST "bi "); */
976 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
977 *buf = xmlStrdup(BAD_CAST "'");
978 *buf = xmlStrcat(*buf, item->name);
979 *buf = xmlStrcat(*buf, BAD_CAST "'");
980 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000981 break;
982 case XML_SCHEMA_TYPE_SIMPLE:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000983 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
984 *buf = xmlStrdup(xmlSchemaElemDesST);
985 *buf = xmlStrcat(*buf, BAD_CAST " '");
986 *buf = xmlStrcat(*buf, item->name);
987 *buf = xmlStrcat(*buf, BAD_CAST "'");
988 } else {
989 *buf = xmlStrdup(xmlSchemaElemDesST);
Daniel Veillardc0826a72004-08-10 14:17:33 +0000990 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000991 break;
992 case XML_SCHEMA_TYPE_COMPLEX:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000993 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
994 *buf = xmlStrdup(xmlSchemaElemDesCT);
995 *buf = xmlStrcat(*buf, BAD_CAST " '");
996 *buf = xmlStrcat(*buf, item->name);
997 *buf = xmlStrcat(*buf, BAD_CAST "'");
998 } else {
999 *buf = xmlStrdup(xmlSchemaElemDesCT);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001000 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001001 break;
1002 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1003 xmlSchemaAttributePtr attr;
1004
1005 attr = (xmlSchemaAttributePtr) item;
1006 if ((attr->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
1007 (attr->ref == NULL)) {
1008 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1009 *buf = xmlStrcat(*buf, BAD_CAST " '");
1010 *buf = xmlStrcat(*buf, attr->name);
1011 *buf = xmlStrcat(*buf, BAD_CAST "'");
1012 } else {
1013 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1014 *buf = xmlStrcat(*buf, BAD_CAST " '");
1015 *buf = xmlStrcat(*buf, attr->refPrefix);
1016 *buf = xmlStrcat(*buf, BAD_CAST ":");
1017 *buf = xmlStrcat(*buf, attr->ref);
1018 *buf = xmlStrcat(*buf, BAD_CAST "'");
1019 }
1020 }
1021 break;
1022 case XML_SCHEMA_TYPE_ELEMENT: {
1023 xmlSchemaElementPtr elem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001024
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001025 elem = (xmlSchemaElementPtr) item;
1026 if ((elem->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
1027 (elem->ref == NULL)) {
1028 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1029 *buf = xmlStrcat(*buf, BAD_CAST " '");
1030 *buf = xmlStrcat(*buf, elem->name);
1031 *buf = xmlStrcat(*buf, BAD_CAST "'");
1032 } else {
1033 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
1034 *buf = xmlStrcat(*buf, BAD_CAST " '");
1035 *buf = xmlStrcat(*buf, elem->refPrefix);
1036 *buf = xmlStrcat(*buf, BAD_CAST ":");
1037 *buf = xmlStrcat(*buf, elem->ref);
1038 *buf = xmlStrcat(*buf, BAD_CAST "'");
1039 }
1040 }
1041 break;
1042 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1043 case XML_SCHEMA_TYPE_IDC_KEY:
1044 case XML_SCHEMA_TYPE_IDC_KEYREF:
1045 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1046 *buf = xmlStrdup(BAD_CAST "unique '");
1047 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1048 *buf = xmlStrdup(BAD_CAST "key '");
1049 else
1050 *buf = xmlStrdup(BAD_CAST "keyRef '");
1051 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1052 *buf = xmlStrcat(*buf, BAD_CAST "'");
1053 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001054 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1055 TODO
1056 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001057 default:
William M. Brack2f2a6632004-08-20 23:09:47 +00001058 named = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001059 }
William M. Brack2f2a6632004-08-20 23:09:47 +00001060 } else
1061 named = 0;
1062
1063 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00001064 xmlNodePtr elem;
1065
1066 if (itemNode->type == XML_ATTRIBUTE_NODE)
1067 elem = itemNode->parent;
1068 else
1069 elem = itemNode;
1070 *buf = xmlStrdup(BAD_CAST "Element '");
1071 if (parsing)
1072 *buf = xmlStrcat(*buf, elem->name);
1073 else
1074 *buf = xmlStrcat(*buf,
1075 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
1076 *buf = xmlStrcat(*buf, BAD_CAST "'");
1077 }
1078 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1079 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1080 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
1081 itemNode->ns, itemNode->name));
1082 *buf = xmlStrcat(*buf, BAD_CAST "'");
1083 }
1084 FREE_AND_NULL(str);
1085
1086 return (*buf);
1087}
1088
1089/**
1090 * xmlSchemaPFormatItemDes:
1091 * @buf: the string buffer
1092 * @item: the item as a schema object
1093 * @itemNode: the item as a node
1094 *
1095 * If the pointer to @buf is not NULL and @but holds no value,
1096 * the value is set to a item designation using
1097 * xmlSchemaFormatItemForReport. This one avoids adding
1098 * an attribute designation postfix.
1099 *
1100 * Returns a string of all enumeration elements.
1101 */
1102static void
1103xmlSchemaPRequestItemDes(xmlChar **buf,
1104 xmlSchemaTypePtr item,
1105 xmlNodePtr itemNode)
1106{
1107 if ((buf == 0) || (*buf != NULL))
1108 return;
1109 if (itemNode->type == XML_ATTRIBUTE_NODE)
1110 itemNode = itemNode->parent;
1111 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
1112}
1113
1114/**
1115 * xmlSchemaFormatFacetEnumSet:
1116 * @buf: the string buffer
1117 * @type: the type holding the enumeration facets
1118 *
1119 * Builds a string consisting of all enumeration elements.
1120 *
1121 * Returns a string of all enumeration elements.
1122 */
1123static const xmlChar *
1124xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
1125{
1126 xmlSchemaFacetLinkPtr link;
1127
1128 if (*buf != NULL)
1129 xmlFree(*buf);
1130 *buf = NULL;
1131 for (link = type->facetSet; link != NULL; link = link->next) {
1132 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
1133 if (*buf == NULL) {
1134 *buf = xmlStrdup(BAD_CAST "'");
1135 *buf = xmlStrcat(*buf, link->facet->value);
1136 *buf = xmlStrcat(*buf, BAD_CAST "'");
1137 } else {
1138 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1139 *buf = xmlStrcat(*buf, link->facet->value);
1140 *buf = xmlStrcat(*buf, BAD_CAST "'");
1141 }
1142 }
1143 }
1144 return ((const xmlChar *) *buf);
1145}
1146
1147/**
1148 * xmlSchemaVFacetErr:
1149 * @ctxt: the schema validation context
1150 * @error: the error code
1151 * @node: the node to be validated
1152 * @value: the value of the node
1153 * @type: the type holding the facet
1154 * @facet: the facet
1155 * @message: the error message of NULL
1156 * @str1: extra data
1157 * @str2: extra data
1158 * @str3: extra data
1159 *
1160 * Reports a facet validation error.
1161 * TODO: Should this report the value of an element as well?
1162 */
1163static void
1164xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
1165 xmlParserErrors error,
1166 xmlNodePtr node,
1167 const xmlChar *value,
1168 unsigned long length,
1169 xmlSchemaTypePtr type,
1170 xmlSchemaFacetPtr facet,
1171 const char *message,
1172 const xmlChar *str1,
1173 const xmlChar *str2,
1174 const xmlChar *str3)
1175{
1176 xmlChar *str = NULL, *msg = NULL;
1177 xmlSchemaTypeType facetType;
1178
1179 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1180 msg = xmlStrcat(msg, BAD_CAST " [");
1181 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1182 msg = xmlStrcat(msg, BAD_CAST ", facet '");
1183 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1184 facetType = XML_SCHEMA_FACET_ENUMERATION;
1185 /*
1186 * If enumerations are validated, one must not expect the
1187 * facet to be given.
1188 */
1189 } else
1190 facetType = facet->type;
1191 msg = xmlStrcat(msg, BAD_CAST xmlSchemaFacetTypeToString(facetType));
1192 msg = xmlStrcat(msg, BAD_CAST "']: ");
1193 if (message == NULL) {
1194 /*
1195 * Use a default message.
1196 */
1197 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1198 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1199 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1200
1201 char len[25], actLen[25];
1202
1203 /* FIXME, TODO: What is the max expected string length of the
1204 * this value?
1205 */
1206 if (node->type == XML_ATTRIBUTE_NODE)
1207 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1208 else
1209 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1210
1211 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1212 snprintf(actLen, 24, "%lu", length);
1213
1214 if (facetType == XML_SCHEMA_FACET_LENGTH)
1215 msg = xmlStrcat(msg,
1216 BAD_CAST "this differs from the allowed length of '%s'.\n");
1217 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
1218 msg = xmlStrcat(msg,
1219 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
1220 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
1221 msg = xmlStrcat(msg,
1222 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
1223
1224 if (node->type == XML_ATTRIBUTE_NODE)
1225 xmlSchemaVErrExt(ctxt, node, error,
1226 (const char *) msg,
1227 value, (const xmlChar *) actLen, (const xmlChar *) len,
1228 NULL, NULL);
1229 else
1230 xmlSchemaVErr(ctxt, node, error,
1231 (const char *) msg,
1232 (const xmlChar *) actLen, (const xmlChar *) len);
1233
1234 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
1235 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
1236 "of the set {%s}.\n");
1237 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1238 xmlSchemaFormatFacetEnumSet(&str, type));
1239 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1240 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1241 "by the pattern '%s'.\n");
1242 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1243 facet->value);
1244 } else if (node->type == XML_ATTRIBUTE_NODE) {
1245 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1246 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1247 } else {
1248 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1249 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1250 }
1251 } else {
1252 msg = xmlStrcat(msg, (const xmlChar *) message);
1253 msg = xmlStrcat(msg, BAD_CAST ".\n");
1254 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1255 }
1256 FREE_AND_NULL(str)
1257 xmlFree(msg);
1258}
1259
1260/**
1261 * xmlSchemaVSimpleTypeErr:
1262 * @ctxt: the schema validation context
1263 * @error: the error code
1264 * @type: the type used for validation
1265 * @node: the node containing the validated value
1266 * @value: the validated value
1267 *
1268 * Reports a simple type validation error.
1269 * TODO: Should this report the value of an element as well?
1270 */
1271static void
1272xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1273 xmlParserErrors error,
1274 xmlNodePtr node,
1275 const xmlChar *value,
1276 xmlSchemaTypePtr type)
1277{
1278 xmlChar *str = NULL, *msg = NULL;
1279
1280 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1281 msg = xmlStrcat(msg, BAD_CAST " [");
1282 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1283 if (node->type == XML_ATTRIBUTE_NODE) {
1284 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1285 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1286 } else {
1287 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1288 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1289 }
1290 FREE_AND_NULL(str)
1291 xmlFree(msg);
1292}
1293
1294/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001295 * xmlSchemaVComplexTypeErr:
1296 * @ctxt: the schema validation context
1297 * @error: the error code
1298 * @node: the node containing the validated value
1299 * @type: the complex type used for validation
1300 * @message: the error message
1301 *
1302 * Reports a complex type validation error.
1303 */
1304static void
1305xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1306 xmlParserErrors error,
1307 xmlNodePtr node,
1308 xmlSchemaTypePtr type,
1309 const char *message)
1310{
1311 xmlChar *str = NULL, *msg = NULL;
1312
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001313 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001314 /* Specify the complex type only if it is global. */
1315 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001316 msg = xmlStrcat(msg, BAD_CAST " [");
1317 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1318 msg = xmlStrcat(msg, BAD_CAST "]");
1319 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001320 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1321 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001322 (const xmlChar *) message, NULL);
1323 FREE_AND_NULL(str)
1324 xmlFree(msg);
1325}
1326
1327/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001328 * xmlSchemaVComplexTypeElemErr:
1329 * @ctxt: the schema validation context
1330 * @error: the error code
1331 * @node: the node containing the validated value
1332 * @type: the complex type used for validation
1333 * @message: the error message
1334 *
1335 * Reports a complex type validation error.
1336 */
1337static void
1338xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1339 xmlParserErrors error,
1340 xmlNodePtr node,
1341 xmlSchemaTypePtr type,
1342 const char *message,
1343 int nbval,
1344 int nbneg,
1345 xmlChar **values)
1346{
1347 xmlChar *str = NULL, *msg = NULL;
1348 xmlChar *localName, *nsName;
1349 const xmlChar *cur, *end;
1350 int i;
1351
1352 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1353 /* Specify the complex type only if it is global. */
1354 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1355 msg = xmlStrcat(msg, BAD_CAST " [");
1356 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1357 msg = xmlStrcat(msg, BAD_CAST "]");
1358 FREE_AND_NULL(str)
1359 }
1360 msg = xmlStrcat(msg, BAD_CAST ": ");
1361 msg = xmlStrcat(msg, (const xmlChar *) message);
1362 /*
1363 * Note that is does not make sense to report that we have a
1364 * wildcard here, since the wildcard might be unfolded into
1365 * multiple transitions.
1366 */
1367 if (nbval + nbneg > 0) {
1368 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001369 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001370 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001371 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001372 nsName = NULL;
1373
1374 for (i = 0; i < nbval + nbneg; i++) {
1375 cur = values[i];
1376 /*
1377 * Get the local name.
1378 */
1379 localName = NULL;
1380
1381 end = cur;
1382 if (*end == '*') {
1383 localName = xmlStrdup(BAD_CAST "*");
1384 *end++;
1385 } else {
1386 while ((*end != 0) && (*end != '|'))
1387 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001388 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001389 }
1390 if (*end != 0) {
1391 *end++;
1392 /*
1393 * Skip "*|*" if they come with negated expressions, since
1394 * they represent the same negated wildcard.
1395 */
1396 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1397 /*
1398 * Get the namespace name.
1399 */
1400 cur = end;
1401 if (*end == '*') {
1402 nsName = xmlStrdup(BAD_CAST "{*}");
1403 } else {
1404 while (*end != 0)
1405 end++;
1406
1407 if (i >= nbval)
1408 nsName = xmlStrdup(BAD_CAST "{##other:");
1409 else
1410 nsName = xmlStrdup(BAD_CAST "{");
1411
1412 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1413 nsName = xmlStrcat(nsName, BAD_CAST "}");
1414 }
1415 str = xmlStrcat(str, BAD_CAST nsName);
1416 FREE_AND_NULL(nsName)
1417 } else {
1418 FREE_AND_NULL(localName);
1419 continue;
1420 }
1421 }
1422 str = xmlStrcat(str, BAD_CAST localName);
1423 FREE_AND_NULL(localName);
1424
1425 if (i < nbval + nbneg -1)
1426 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001427 }
1428 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001429 msg = xmlStrcat(msg, BAD_CAST str);
1430 FREE_AND_NULL(str)
1431 }
1432 msg = xmlStrcat(msg, BAD_CAST ".\n");
1433 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1434 xmlFree(msg);
1435}
1436
1437/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001438 * xmlSchemaPMissingAttrErr:
1439 * @ctxt: the schema validation context
1440 * @ownerDes: the designation of the owner
1441 * @ownerName: the name of the owner
1442 * @ownerItem: the owner as a schema object
1443 * @ownerElem: the owner as an element node
1444 * @node: the parent element node of the missing attribute node
1445 * @type: the corresponding type of the attribute node
1446 *
1447 * Reports an illegal attribute.
1448 */
1449static void
1450xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1451 xmlParserErrors error,
1452 xmlChar **ownerDes,
1453 xmlSchemaTypePtr ownerItem,
1454 xmlNodePtr ownerElem,
1455 const char *name,
1456 const char *message)
1457{
1458 xmlChar *des = NULL;
1459
1460 if (ownerDes == NULL)
1461 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1462 else if (*ownerDes == NULL) {
1463 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1464 des = *ownerDes;
1465 } else
1466 des = *ownerDes;
1467 if (message != NULL)
1468 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1469 else
1470 xmlSchemaPErr(ctxt, ownerElem, error,
1471 "%s: The attribute '%s' is required but missing.\n",
1472 BAD_CAST des, BAD_CAST name);
1473 if (ownerDes == NULL)
1474 FREE_AND_NULL(des);
1475}
1476
William M. Brack2f2a6632004-08-20 23:09:47 +00001477/**
1478 * xmlSchemaCompTypeToString:
1479 * @type: the type of the schema item
1480 *
1481 * Returns the component name of a schema item.
1482 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001483static const char *
1484xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1485{
1486 switch (type) {
1487 case XML_SCHEMA_TYPE_SIMPLE:
1488 return("simple type definition");
1489 case XML_SCHEMA_TYPE_COMPLEX:
1490 return("complex type definition");
1491 case XML_SCHEMA_TYPE_ELEMENT:
1492 return("element declaration");
1493 case XML_SCHEMA_TYPE_ATTRIBUTE:
1494 return("attribute declaration");
1495 case XML_SCHEMA_TYPE_GROUP:
1496 return("model group definition");
1497 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1498 return("attribute group definition");
1499 case XML_SCHEMA_TYPE_NOTATION:
1500 return("notation declaration");
1501 default:
1502 return("Not a schema component");
1503 }
1504}
1505/**
1506 * xmlSchemaPResCompAttrErr:
1507 * @ctxt: the schema validation context
1508 * @error: the error code
1509 * @ownerDes: the designation of the owner
1510 * @ownerItem: the owner as a schema object
1511 * @ownerElem: the owner as an element node
1512 * @name: the name of the attribute holding the QName
1513 * @refName: the referenced local name
1514 * @refURI: the referenced namespace URI
1515 * @message: optional message
1516 *
1517 * Used to report QName attribute values that failed to resolve
1518 * to schema components.
1519 */
1520static void
1521xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1522 xmlParserErrors error,
1523 xmlChar **ownerDes,
1524 xmlSchemaTypePtr ownerItem,
1525 xmlNodePtr ownerElem,
1526 const char *name,
1527 const xmlChar *refName,
1528 const xmlChar *refURI,
1529 xmlSchemaTypeType refType,
1530 const char *refTypeStr)
1531{
1532 xmlChar *des = NULL, *strA = NULL;
1533
1534 if (ownerDes == NULL)
1535 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1536 else if (*ownerDes == NULL) {
1537 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1538 des = *ownerDes;
1539 } else
1540 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001541 if (refTypeStr == NULL)
1542 refTypeStr = xmlSchemaCompTypeToString(refType);
1543 xmlSchemaPErrExt(ctxt, ownerElem, error,
1544 NULL, NULL, NULL,
1545 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1546 "%s.\n", BAD_CAST des, BAD_CAST name,
1547 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1548 BAD_CAST refTypeStr, NULL);
1549 if (ownerDes == NULL)
1550 FREE_AND_NULL(des)
1551 FREE_AND_NULL(strA)
1552}
1553
William M. Brack2f2a6632004-08-20 23:09:47 +00001554/**
1555 * xmlSchemaPCustomAttrErr:
1556 * @ctxt: the schema parser context
1557 * @error: the error code
1558 * @ownerDes: the designation of the owner
1559 * @ownerItem: the owner as a schema object
1560 * @attr: the illegal attribute node
1561 *
1562 * Reports an illegal attribute during the parse.
1563 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001564static void
1565xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001566 xmlParserErrors error,
1567 xmlChar **ownerDes,
1568 xmlSchemaTypePtr ownerItem,
1569 xmlAttrPtr attr,
1570 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001571{
1572 xmlChar *des = NULL;
1573
1574 if (ownerDes == NULL)
1575 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1576 else if (*ownerDes == NULL) {
1577 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1578 des = *ownerDes;
1579 } else
1580 des = *ownerDes;
1581 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1582 "%s, attribute '%s': %s.\n",
1583 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1584 if (ownerDes == NULL)
1585 FREE_AND_NULL(des);
1586}
1587
1588/**
1589 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001590 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001591 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001592 * @ownerDes: the designation of the attribute's owner
1593 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001594 * @attr: the illegal attribute node
1595 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001596 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001597 */
1598static void
1599xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1600 xmlParserErrors error,
1601 xmlChar **ownerDes,
1602 xmlSchemaTypePtr ownerItem,
1603 xmlAttrPtr attr)
1604{
1605 xmlChar *des = NULL, *strA = NULL;
1606
1607 if (ownerDes == NULL)
1608 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1609 else if (*ownerDes == NULL) {
1610 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1611 des = *ownerDes;
1612 } else
1613 des = *ownerDes;
1614 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1615 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1616 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1617 if (ownerDes == NULL)
1618 FREE_AND_NULL(des);
1619 FREE_AND_NULL(strA);
1620}
1621
William M. Brack2f2a6632004-08-20 23:09:47 +00001622/**
1623 * xmlSchemaPAquireDes:
1624 * @des: the first designation
1625 * @itemDes: the second designation
1626 * @item: the schema item
1627 * @itemElem: the node of the schema item
1628 *
1629 * Creates a designation for an item.
1630 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001631static void
1632xmlSchemaPAquireDes(xmlChar **des,
1633 xmlChar **itemDes,
1634 xmlSchemaTypePtr item,
1635 xmlNodePtr itemElem)
1636{
1637 if (itemDes == NULL)
1638 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1639 else if (*itemDes == NULL) {
1640 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1641 *des = *itemDes;
1642 } else
1643 *des = *itemDes;
1644}
1645
William M. Brack2f2a6632004-08-20 23:09:47 +00001646/**
1647 * xmlSchemaPCustomErr:
1648 * @ctxt: the schema parser context
1649 * @error: the error code
1650 * @itemDes: the designation of the schema item
1651 * @item: the schema item
1652 * @itemElem: the node of the schema item
1653 * @message: the error message
1654 * @str1: an optional param for the error message
1655 * @str2: an optional param for the error message
1656 * @str3: an optional param for the error message
1657 *
1658 * Reports an error during parsing.
1659 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001660static void
1661xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1662 xmlParserErrors error,
1663 xmlChar **itemDes,
1664 xmlSchemaTypePtr item,
1665 xmlNodePtr itemElem,
1666 const char *message,
1667 const xmlChar *str1,
1668 const xmlChar *str2,
1669 const xmlChar *str3)
1670{
1671 xmlChar *des = NULL, *msg = NULL;
1672
1673 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1674 msg = xmlStrdup(BAD_CAST "%s: ");
1675 msg = xmlStrcat(msg, (const xmlChar *) message);
1676 msg = xmlStrcat(msg, BAD_CAST ".\n");
1677 if ((itemElem == NULL) && (item != NULL))
1678 itemElem = item->node;
1679 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1680 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1681 if (itemDes == NULL)
1682 FREE_AND_NULL(des);
1683 FREE_AND_NULL(msg);
1684}
1685
William M. Brack2f2a6632004-08-20 23:09:47 +00001686/**
1687 * xmlSchemaPCustomErr:
1688 * @ctxt: the schema parser context
1689 * @error: the error code
1690 * @itemDes: the designation of the schema item
1691 * @item: the schema item
1692 * @itemElem: the node of the schema item
1693 * @message: the error message
1694 * @str1: the optional param for the error message
1695 *
1696 * Reports an error during parsing.
1697 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001698static void
1699xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1700 xmlParserErrors error,
1701 xmlChar **itemDes,
1702 xmlSchemaTypePtr item,
1703 xmlNodePtr itemElem,
1704 const char *message,
1705 const xmlChar *str1)
1706{
1707 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1708 str1, NULL, NULL);
1709}
1710
William M. Brack2f2a6632004-08-20 23:09:47 +00001711/**
1712 * xmlSchemaPAttrUseErr:
1713 * @ctxt: the schema parser context
1714 * @error: the error code
1715 * @itemDes: the designation of the schema type
1716 * @item: the schema type
1717 * @itemElem: the node of the schema type
1718 * @attr: the invalid schema attribute
1719 * @message: the error message
1720 * @str1: the optional param for the error message
1721 *
1722 * Reports an attribute use error during parsing.
1723 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001724static void
1725xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1726 xmlParserErrors error,
1727 xmlChar **itemDes,
1728 xmlSchemaTypePtr item,
1729 xmlNodePtr itemElem,
1730 const xmlSchemaAttributePtr attr,
1731 const char *message,
1732 const xmlChar *str1)
1733{
1734 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1735
1736 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1737 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1738 xmlSchemaGetAttrName(attr));
1739 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1740 msg = xmlStrcat(msg, (const xmlChar *) message);
1741 msg = xmlStrcat(msg, BAD_CAST ".\n");
1742 if ((itemElem == NULL) && (item != NULL))
1743 itemElem = item->node;
1744 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1745 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1746 if (itemDes == NULL)
1747 FREE_AND_NULL(des);
1748 FREE_AND_NULL(strA);
1749 xmlFree(msg);
1750}
1751
William M. Brack2f2a6632004-08-20 23:09:47 +00001752/**
1753 * xmlSchemaPIllegalFacetAtomicErr:
1754 * @ctxt: the schema parser context
1755 * @error: the error code
1756 * @itemDes: the designation of the type
1757 * @item: the schema type
1758 * @baseItem: the base type of type
1759 * @facet: the illegal facet
1760 *
1761 * Reports an illegal facet for atomic simple types.
1762 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001763static void
1764xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1765 xmlParserErrors error,
1766 xmlChar **itemDes,
1767 xmlSchemaTypePtr item,
1768 xmlSchemaTypePtr baseItem,
1769 xmlSchemaFacetPtr facet)
1770{
1771 xmlChar *des = NULL, *strT = NULL;
1772
1773 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1774 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1775 "%s: The facet '%s' is not allowed on types derived from the "
1776 "type %s.\n",
1777 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type),
1778 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1779 NULL, NULL);
1780 if (itemDes == NULL)
1781 FREE_AND_NULL(des);
1782 FREE_AND_NULL(strT);
1783}
1784
William M. Brack2f2a6632004-08-20 23:09:47 +00001785/**
1786 * xmlSchemaPIllegalFacetListUnionErr:
1787 * @ctxt: the schema parser context
1788 * @error: the error code
1789 * @itemDes: the designation of the schema item involved
1790 * @item: the schema item involved
1791 * @facet: the illegal facet
1792 *
1793 * Reports an illegal facet for <list> and <union>.
1794 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001795static void
1796xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1797 xmlParserErrors error,
1798 xmlChar **itemDes,
1799 xmlSchemaTypePtr item,
1800 xmlSchemaFacetPtr facet)
1801{
1802 xmlChar *des = NULL, *strT = NULL;
1803
1804 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1805 xmlSchemaPErr(ctxt, item->node, error,
1806 "%s: The facet '%s' is not allowed.\n",
1807 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type));
1808 if (itemDes == NULL)
1809 FREE_AND_NULL(des);
1810 FREE_AND_NULL(strT);
1811}
1812
1813/**
1814 * xmlSchemaPMutualExclAttrErr:
1815 * @ctxt: the schema validation context
1816 * @error: the error code
1817 * @elemDes: the designation of the parent element node
1818 * @attr: the bad attribute node
1819 * @type: the corresponding type of the attribute node
1820 *
1821 * Reports an illegal attribute.
1822 */
1823static void
1824xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1825 xmlParserErrors error,
1826 xmlChar **ownerDes,
1827 xmlSchemaTypePtr ownerItem,
1828 xmlAttrPtr attr,
1829 const char *name1,
1830 const char *name2)
1831{
1832 xmlChar *des = NULL;
1833
1834 if (ownerDes == NULL)
1835 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1836 else if (*ownerDes == NULL) {
1837 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1838 des = *ownerDes;
1839 } else
1840 des = *ownerDes;
1841 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1842 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1843 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1844 if (ownerDes == NULL)
1845 FREE_AND_NULL(des)
1846}
1847
1848/**
1849 * xmlSchemaPSimpleTypeErr:
1850 * @ctxt: the schema validation context
1851 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001852 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001853 * @ownerDes: the designation of the owner
1854 * @ownerItem: the schema object if existent
1855 * @node: the validated node
1856 * @value: the validated value
1857 *
1858 * Reports a simple type validation error.
1859 * TODO: Should this report the value of an element as well?
1860 */
1861static void
1862xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1863 xmlParserErrors error,
1864 xmlChar **ownerDes,
1865 xmlSchemaTypePtr ownerItem,
1866 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001867 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001868 const char *typeDes,
1869 const xmlChar *value,
1870 const char *message,
1871 const xmlChar *str1,
1872 const xmlChar *str2)
1873{
William M. Brack2f2a6632004-08-20 23:09:47 +00001874 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001875
1876 if (ownerDes == NULL)
1877 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1878 else if (*ownerDes == NULL) {
1879 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1880 des = *ownerDes;
1881 } else
1882 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001883 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001884 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001885 if (message == NULL) {
1886 /*
1887 * Use default messages.
1888 */
1889 if (node->type == XML_ATTRIBUTE_NODE) {
1890 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1891 "%s, attribute '%s' [%s]: The value '%s' is not "
1892 "valid.\n",
1893 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1894 node->name), BAD_CAST typeDes, value, NULL);
1895 } else {
1896 xmlSchemaPErr(ctxt, node, error,
1897 "%s [%s]: The character content is not valid.\n",
1898 BAD_CAST des, BAD_CAST typeDes);
1899 }
1900 } else {
1901 xmlChar *msg;
1902
1903 msg = xmlStrdup(BAD_CAST "%s");
1904 if (node->type == XML_ATTRIBUTE_NODE)
1905 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1906 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1907 msg = xmlStrcat(msg, (const xmlChar *) message);
1908 msg = xmlStrcat(msg, BAD_CAST ".\n");
1909 if (node->type == XML_ATTRIBUTE_NODE) {
1910 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1911 (const char *) msg,
1912 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1913 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1914 } else {
1915 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1916 (const char *) msg,
1917 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1918 }
1919 xmlFree(msg);
1920 }
1921 /* Cleanup. */
1922 FREE_AND_NULL(strA)
1923 FREE_AND_NULL(strT)
1924 if (ownerDes == NULL)
1925 FREE_AND_NULL(des)
1926}
1927
William M. Brack2f2a6632004-08-20 23:09:47 +00001928/**
1929 * xmlSchemaPContentErr:
1930 * @ctxt: the schema parser context
1931 * @error: the error code
1932 * @onwerDes: the designation of the holder of the content
1933 * @ownerItem: the owner item of the holder of the content
1934 * @ownerElem: the node of the holder of the content
1935 * @child: the invalid child node
1936 * @message: the optional error message
1937 * @content: the optional string describing the correct content
1938 *
1939 * Reports an error concerning the content of a schema element.
1940 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001941static void
1942xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1943 xmlParserErrors error,
1944 xmlChar **ownerDes,
1945 xmlSchemaTypePtr ownerItem,
1946 xmlNodePtr ownerElem,
1947 xmlNodePtr child,
1948 const char *message,
1949 const char *content)
1950{
1951 xmlChar *des = NULL;
1952
1953 if (ownerDes == NULL)
1954 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1955 else if (*ownerDes == NULL) {
1956 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1957 des = *ownerDes;
1958 } else
1959 des = *ownerDes;
1960 if (message != NULL)
1961 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1962 "%s: %s.\n",
1963 BAD_CAST des, BAD_CAST message);
1964 else {
1965 if (content != NULL) {
1966 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1967 "%s: The content is not valid. Expected is %s.\n",
1968 BAD_CAST des, BAD_CAST content);
1969 } else {
1970 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1971 "%s: The content is not valid.\n",
1972 BAD_CAST des, NULL);
1973 }
1974 }
1975 if (ownerDes == NULL)
1976 FREE_AND_NULL(des)
1977}
1978
1979/**
1980 * xmlSchemaVIllegalAttrErr:
1981 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001982 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00001983 * @attr: the illegal attribute node
1984 *
1985 * Reports an illegal attribute.
1986 */
1987static void
1988xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001989 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00001990 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001991{
1992 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001993
1994 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
1995 error,
1996 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001997 "%s: The attribute '%s' is not allowed.\n",
1998 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
1999 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2000 FREE_AND_NULL(strE)
2001 FREE_AND_NULL(strA)
2002}
2003
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002004
2005static int
2006xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2007{
2008 switch (item->type) {
2009 case XML_SCHEMA_TYPE_COMPLEX:
2010 case XML_SCHEMA_TYPE_SIMPLE:
2011 case XML_SCHEMA_TYPE_GROUP:
2012 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2013 return(1);
2014 break;
2015 case XML_SCHEMA_TYPE_ELEMENT:
2016 if ( ((xmlSchemaElementPtr) item)->flags &
2017 XML_SCHEMAS_ELEM_GLOBAL)
2018 return(1);
2019 break;
2020 case XML_SCHEMA_TYPE_ATTRIBUTE:
2021 if ( ((xmlSchemaAttributePtr) item)->flags &
2022 XML_SCHEMAS_ATTR_GLOBAL)
2023 return(1);
2024 break;
2025 /* Note that attribute groups are always global. */
2026 default:
2027 return(1);
2028 }
2029 return (0);
2030}
2031
William M. Brack2f2a6632004-08-20 23:09:47 +00002032/**
2033 * xmlSchemaVCustomErr:
2034 * @ctxt: the schema validation context
2035 * @error: the error code
2036 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002037 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00002038 * @message: the error message
2039 * @str1: the optional param for the message
2040 *
2041 * Reports a validation error.
2042 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002043static void
2044xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
2045 xmlParserErrors error,
2046 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002047 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002048 const char *message,
2049 const xmlChar *str1)
2050{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002051 xmlChar *msg = NULL, *str = NULL;
2052
2053 if (node == NULL) {
2054 xmlSchemaVErr(ctxt, NULL,
2055 XML_SCHEMAV_INTERNAL,
2056 "Internal error: xmlSchemaVCustomErr, no node "
2057 "given.\n", NULL, NULL);
2058 return;
2059 }
2060 /* TODO: Are the HTML and DOCB doc nodes expected here? */
2061 if (node->type != XML_DOCUMENT_NODE) {
2062 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002063 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002064 msg = xmlStrcat(msg, BAD_CAST " [");
2065 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
2066 msg = xmlStrcat(msg, BAD_CAST "]");
2067 }
2068 msg = xmlStrcat(msg, BAD_CAST ": ");
2069 } else
2070 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002071 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002072 msg = xmlStrcat(msg, BAD_CAST ".\n");
2073 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
2074 FREE_AND_NULL(msg)
2075 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002076}
2077
William M. Brack2f2a6632004-08-20 23:09:47 +00002078/**
2079 * xmlSchemaWildcardPCToString:
2080 * @pc: the type of processContents
2081 *
2082 * Returns a string representation of the type of
2083 * processContents.
2084 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002085static const char *
2086xmlSchemaWildcardPCToString(int pc)
2087{
2088 switch (pc) {
2089 case XML_SCHEMAS_ANY_SKIP:
2090 return ("skip");
2091 case XML_SCHEMAS_ANY_LAX:
2092 return ("lax");
2093 case XML_SCHEMAS_ANY_STRICT:
2094 return ("strict");
2095 default:
2096 return ("invalid process contents");
2097 }
2098}
2099
William M. Brack2f2a6632004-08-20 23:09:47 +00002100/**
2101 * xmlSchemaVWildcardErr:
2102 * @ctxt: the schema validation context
2103 * @error: the error code
2104 * @node: the validated node
2105 * @wild: the wildcard used
2106 * @message: the error message
2107 *
2108 * Reports an validation-by-wildcard error.
2109 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002110static void
2111xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
2112 xmlParserErrors error,
2113 xmlNodePtr node,
2114 xmlSchemaWildcardPtr wild,
2115 const char *message)
2116{
2117 xmlChar *des = NULL, *msg = NULL;
2118
2119 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00002120 msg = xmlStrdup(BAD_CAST "%s [");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002121 msg = xmlStrcat(msg, BAD_CAST xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002122 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002123 msg = xmlStrcat(msg, (const xmlChar *) message);
2124 msg = xmlStrcat(msg, BAD_CAST ".\n");
2125 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
2126 FREE_AND_NULL(des);
2127 FREE_AND_NULL(msg);
2128}
2129
2130/**
2131 * xmlSchemaVMissingAttrErr:
2132 * @ctxt: the schema validation context
2133 * @node: the parent element node of the missing attribute node
2134 * @type: the corresponding type of the attribute node
2135 *
2136 * Reports an illegal attribute.
2137 */
2138static void
2139xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
2140 xmlNodePtr elem,
2141 xmlSchemaAttributePtr type)
2142{
2143 const xmlChar *name, *uri;
2144 xmlChar *strE = NULL, *strA = NULL;
2145
2146 if (type->ref != NULL) {
2147 name = type->ref;
2148 uri = type->refNs;
2149 } else {
2150 name = type->name;
2151 uri = type->targetNamespace;
2152 }
2153 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002154 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
2155 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002156 "%s: The attribute %s is required but missing.\n",
2157 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
2158 xmlSchemaFormatNsUriLocal(&strA, uri, name));
2159 FREE_AND_NULL(strE)
2160 FREE_AND_NULL(strA)
2161}
2162
Daniel Veillard4255d502002-04-16 15:50:10 +00002163/************************************************************************
2164 * *
2165 * Allocation functions *
2166 * *
2167 ************************************************************************/
2168
2169/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002170 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002171 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002172 *
2173 * Allocate a new Schema structure.
2174 *
2175 * Returns the newly allocated structure or NULL in case or error
2176 */
2177static xmlSchemaPtr
2178xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2179{
2180 xmlSchemaPtr ret;
2181
2182 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2183 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002184 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002185 return (NULL);
2186 }
2187 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002188 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002189 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002190
2191 return (ret);
2192}
2193
2194/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002195 * xmlSchemaNewSchema:
2196 * @ctxt: a schema validation context
2197 *
2198 * Allocate a new Schema structure.
2199 *
2200 * Returns the newly allocated structure or NULL in case or error
2201 */
2202static xmlSchemaAssemblePtr
2203xmlSchemaNewAssemble(void)
2204{
2205 xmlSchemaAssemblePtr ret;
2206
2207 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2208 if (ret == NULL) {
2209 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2210 return (NULL);
2211 }
2212 memset(ret, 0, sizeof(xmlSchemaAssemble));
2213 ret->items = NULL;
2214 return (ret);
2215}
2216
2217/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002218 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002219 *
2220 * Allocate a new Facet structure.
2221 *
2222 * Returns the newly allocated structure or NULL in case or error
2223 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002224xmlSchemaFacetPtr
2225xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002226{
2227 xmlSchemaFacetPtr ret;
2228
2229 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2230 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002231 return (NULL);
2232 }
2233 memset(ret, 0, sizeof(xmlSchemaFacet));
2234
2235 return (ret);
2236}
2237
2238/**
2239 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002240 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002241 * @node: a node
2242 *
2243 * Allocate a new annotation structure.
2244 *
2245 * Returns the newly allocated structure or NULL in case or error
2246 */
2247static xmlSchemaAnnotPtr
2248xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2249{
2250 xmlSchemaAnnotPtr ret;
2251
2252 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2253 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002254 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002255 return (NULL);
2256 }
2257 memset(ret, 0, sizeof(xmlSchemaAnnot));
2258 ret->content = node;
2259 return (ret);
2260}
2261
2262/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002263 * xmlSchemaFreeAnnot:
2264 * @annot: a schema type structure
2265 *
2266 * Deallocate a annotation structure
2267 */
2268static void
2269xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2270{
2271 if (annot == NULL)
2272 return;
2273 xmlFree(annot);
2274}
2275
2276/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002277 * xmlSchemaFreeImport:
2278 * @import: a schema import structure
2279 *
2280 * Deallocate an import structure
2281 */
2282static void
2283xmlSchemaFreeImport(xmlSchemaImportPtr import)
2284{
2285 if (import == NULL)
2286 return;
2287
2288 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002289 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002290 xmlFree(import);
2291}
2292
2293/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002294 * xmlSchemaFreeInclude:
2295 * @include: a schema include structure
2296 *
2297 * Deallocate an include structure
2298 */
2299static void
2300xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2301{
2302 if (include == NULL)
2303 return;
2304
2305 xmlFreeDoc(include->doc);
2306 xmlFree(include);
2307}
2308
2309/**
2310 * xmlSchemaFreeIncludeList:
2311 * @includes: a schema include list
2312 *
2313 * Deallocate an include structure
2314 */
2315static void
2316xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2317{
2318 xmlSchemaIncludePtr next;
2319
2320 while (includes != NULL) {
2321 next = includes->next;
2322 xmlSchemaFreeInclude(includes);
2323 includes = next;
2324 }
2325}
2326
2327/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002328 * xmlSchemaFreeNotation:
2329 * @schema: a schema notation structure
2330 *
2331 * Deallocate a Schema Notation structure.
2332 */
2333static void
2334xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2335{
2336 if (nota == NULL)
2337 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002338 xmlFree(nota);
2339}
2340
2341/**
2342 * xmlSchemaFreeAttribute:
2343 * @schema: a schema attribute structure
2344 *
2345 * Deallocate a Schema Attribute structure.
2346 */
2347static void
2348xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2349{
2350 if (attr == NULL)
2351 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002352 if (attr->annot != NULL)
2353 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002354 if (attr->defVal != NULL)
2355 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002356 xmlFree(attr);
2357}
2358
2359/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002360 * xmlSchemaFreeWildcardNsSet:
2361 * set: a schema wildcard namespace
2362 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002363 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002364 */
2365static void
2366xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2367{
2368 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002369
Daniel Veillard3646d642004-06-02 19:19:14 +00002370 while (set != NULL) {
2371 next = set->next;
2372 xmlFree(set);
2373 set = next;
2374 }
2375}
2376
2377/**
2378 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002379 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002380 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002381 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002382 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002383void
Daniel Veillard3646d642004-06-02 19:19:14 +00002384xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2385{
2386 if (wildcard == NULL)
2387 return;
2388 if (wildcard->annot != NULL)
2389 xmlSchemaFreeAnnot(wildcard->annot);
2390 if (wildcard->nsSet != NULL)
2391 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2392 if (wildcard->negNsSet != NULL)
2393 xmlFree(wildcard->negNsSet);
2394 xmlFree(wildcard);
2395}
2396
2397/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002398 * xmlSchemaFreeAttributeGroup:
2399 * @schema: a schema attribute group structure
2400 *
2401 * Deallocate a Schema Attribute Group structure.
2402 */
2403static void
2404xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2405{
2406 if (attr == NULL)
2407 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002408 if (attr->annot != NULL)
2409 xmlSchemaFreeAnnot(attr->annot);
2410 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2411 (attr->attributeWildcard != NULL))
2412 xmlSchemaFreeWildcard(attr->attributeWildcard);
2413
Daniel Veillard4255d502002-04-16 15:50:10 +00002414 xmlFree(attr);
2415}
2416
2417/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002418 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002419 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002420 *
2421 * Deallocate a list of schema attribute uses.
2422 */
2423static void
2424xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2425{
2426 xmlSchemaAttributeLinkPtr next;
2427
2428 while (attrUse != NULL) {
2429 next = attrUse->next;
2430 xmlFree(attrUse);
2431 attrUse = next;
2432 }
2433}
2434
2435/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002436 * xmlSchemaFreeTypeLinkList:
2437 * @alink: a type link
2438 *
2439 * Deallocate a list of types.
2440 */
2441static void
2442xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2443{
2444 xmlSchemaTypeLinkPtr next;
2445
2446 while (link != NULL) {
2447 next = link->next;
2448 xmlFree(link);
2449 link = next;
2450 }
2451}
2452
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002453#ifdef IDC_ENABLED
2454static void
2455xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
2456{
2457 xmlSchemaIDCStateObjPtr next;
2458 while (sto != NULL) {
2459 next = sto->next;
2460 if (sto->history != NULL)
2461 xmlFree(sto->history);
2462 if (sto->xpathCtxt != NULL)
2463 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
2464 xmlFree(sto);
2465 sto = next;
2466 }
2467}
2468
2469/**
2470 * xmlSchemaFreeIDC:
2471 * @idc: a identity-constraint definition
2472 *
2473 * Deallocates an identity-constraint definition.
2474 */
2475static void
2476xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
2477{
2478 xmlSchemaIDCSelectPtr cur, prev;
2479
2480 if (idcDef == NULL)
2481 return;
2482 if (idcDef->annot != NULL)
2483 xmlSchemaFreeAnnot(idcDef->annot);
2484 if (idcDef->ref != NULL)
2485 xmlFree(idcDef->ref);
2486 /* Selector */
2487 if (idcDef->selector != NULL) {
2488 if (idcDef->selector->xpathComp != NULL)
2489 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
2490 xmlFree(idcDef->selector);
2491 }
2492 /* Fields */
2493 if (idcDef->fields != NULL) {
2494 cur = idcDef->fields;
2495 do {
2496 prev = cur;
2497 cur = cur->next;
2498 if (prev->xpathComp != NULL)
2499 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
2500 xmlFree(prev);
2501 } while (cur != NULL);
2502 }
2503 xmlFree(idcDef);
2504}
2505#endif /* IDC_ENABLED */
2506
Daniel Veillard01fa6152004-06-29 17:04:39 +00002507/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002508 * xmlSchemaFreeElement:
2509 * @schema: a schema element structure
2510 *
2511 * Deallocate a Schema Element structure.
2512 */
2513static void
2514xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2515{
2516 if (elem == NULL)
2517 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002518 if (elem->annot != NULL)
2519 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002520 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002521 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002522 if (elem->defVal != NULL)
2523 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002524 xmlFree(elem);
2525}
2526
2527/**
2528 * xmlSchemaFreeFacet:
2529 * @facet: a schema facet structure
2530 *
2531 * Deallocate a Schema Facet structure.
2532 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002533void
Daniel Veillard4255d502002-04-16 15:50:10 +00002534xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2535{
2536 if (facet == NULL)
2537 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002538 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002539 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002540 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002541 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002542 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002543 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002544 xmlFree(facet);
2545}
2546
2547/**
2548 * xmlSchemaFreeType:
2549 * @type: a schema type structure
2550 *
2551 * Deallocate a Schema Type structure.
2552 */
2553void
2554xmlSchemaFreeType(xmlSchemaTypePtr type)
2555{
2556 if (type == NULL)
2557 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002558 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002559 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002560 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002561 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002562
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002563 facet = type->facets;
2564 while (facet != NULL) {
2565 next = facet->next;
2566 xmlSchemaFreeFacet(facet);
2567 facet = next;
2568 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002569 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002570 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2571 if (type->attributeUses != NULL)
2572 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002573 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002574 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002575 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2576 /*
2577 * NOTE: The only case where an attribute wildcard
2578 * is not owned, is if a complex type inherits it
2579 * from a base type.
2580 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002581 xmlSchemaFreeWildcard(type->attributeWildcard);
2582 }
2583 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002584 if (type->memberTypes != NULL)
2585 xmlSchemaFreeTypeLinkList(type->memberTypes);
2586 if (type->facetSet != NULL) {
2587 xmlSchemaFacetLinkPtr next, link;
2588
2589 link = type->facetSet;
2590 do {
2591 next = link->next;
2592 xmlFree(link);
2593 link = next;
2594 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002595 }
2596 if (type->contModel != NULL)
2597 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002598 xmlFree(type);
2599}
2600
2601/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002602 * xmlSchemaFreeTypeList:
2603 * @type: a schema type structure
2604 *
2605 * Deallocate a Schema Type structure.
2606 */
2607static void
2608xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2609{
2610 xmlSchemaTypePtr next;
2611
2612 while (type != NULL) {
2613 next = type->redef;
2614 xmlSchemaFreeType(type);
2615 type = next;
2616 }
2617}
2618
2619/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002620 * xmlSchemaFree:
2621 * @schema: a schema structure
2622 *
2623 * Deallocate a Schema structure.
2624 */
2625void
2626xmlSchemaFree(xmlSchemaPtr schema)
2627{
2628 if (schema == NULL)
2629 return;
2630
Daniel Veillard4255d502002-04-16 15:50:10 +00002631 if (schema->notaDecl != NULL)
2632 xmlHashFree(schema->notaDecl,
2633 (xmlHashDeallocator) xmlSchemaFreeNotation);
2634 if (schema->attrDecl != NULL)
2635 xmlHashFree(schema->attrDecl,
2636 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2637 if (schema->attrgrpDecl != NULL)
2638 xmlHashFree(schema->attrgrpDecl,
2639 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2640 if (schema->elemDecl != NULL)
2641 xmlHashFree(schema->elemDecl,
2642 (xmlHashDeallocator) xmlSchemaFreeElement);
2643 if (schema->typeDecl != NULL)
2644 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002645 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002646 if (schema->groupDecl != NULL)
2647 xmlHashFree(schema->groupDecl,
2648 (xmlHashDeallocator) xmlSchemaFreeType);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002649#ifdef IDC_ENABLED
2650 if (schema->idcDef != NULL)
2651 xmlHashFree(schema->idcDef,
2652 (xmlHashDeallocator) xmlSchemaFreeIDC);
2653#endif
Daniel Veillard1d913862003-11-21 00:28:39 +00002654 if (schema->schemasImports != NULL)
2655 xmlHashFree(schema->schemasImports,
2656 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002657 if (schema->includes != NULL) {
2658 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2659 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002660 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002661 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002662 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002663 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002664 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002665 xmlFree(schema);
2666}
2667
2668/************************************************************************
2669 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002670 * Debug functions *
2671 * *
2672 ************************************************************************/
2673
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002674#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002675
Daniel Veillard4255d502002-04-16 15:50:10 +00002676/**
2677 * xmlSchemaElementDump:
2678 * @elem: an element
2679 * @output: the file output
2680 *
2681 * Dump the element
2682 */
2683static void
2684xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002685 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002686 const xmlChar * namespace ATTRIBUTE_UNUSED,
2687 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002688{
2689 if (elem == NULL)
2690 return;
2691
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002692 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
2693 fprintf(output, "Particle: %s", name);
2694 fprintf(output, ", term element: %s", elem->ref);
2695 if (elem->refNs != NULL)
2696 fprintf(output, " ns %s", elem->refNs);
2697 } else {
2698 fprintf(output, "Element");
2699 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2700 fprintf(output, " (global)");
2701 fprintf(output, ": %s ", elem->name);
2702 if (namespace != NULL)
2703 fprintf(output, "ns %s", namespace);
2704 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002705 fprintf(output, "\n");
2706 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002707 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002708 if (elem->maxOccurs >= UNBOUNDED)
2709 fprintf(output, "max: unbounded\n");
2710 else if (elem->maxOccurs != 1)
2711 fprintf(output, "max: %d\n", elem->maxOccurs);
2712 else
2713 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002714 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002715 /*
2716 * Misc other properties.
2717 */
2718 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
2719 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
2720 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
2721 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
2722 (elem->id != NULL)) {
2723 fprintf(output, " props: ");
2724 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
2725 fprintf(output, "[fixed] ");
2726 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
2727 fprintf(output, "[default] ");
2728 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
2729 fprintf(output, "[abstract] ");
2730 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
2731 fprintf(output, "[nillable] ");
2732 if (elem->id != NULL)
2733 fprintf(output, "[id: '%s'] ", elem->id);
2734 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002735 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002736 /*
2737 * Default/fixed value.
2738 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002739 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002740 fprintf(output, " value: '%s'\n", elem->value);
2741 /*
2742 * Type.
2743 */
2744 if (elem->namedType != NULL) {
2745 fprintf(output, " type: %s ", elem->namedType);
2746 if (elem->namedTypeNs != NULL)
2747 fprintf(output, "ns %s\n", elem->namedTypeNs);
2748 else
2749 fprintf(output, "\n");
2750 }
2751 /*
2752 * Substitution group.
2753 */
2754 if (elem->substGroup != NULL) {
2755 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
2756 if (elem->substGroupNs != NULL)
2757 fprintf(output, "ns %s\n", elem->substGroupNs);
2758 else
2759 fprintf(output, "\n");
2760 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002761}
2762
2763/**
2764 * xmlSchemaAnnotDump:
2765 * @output: the file output
2766 * @annot: a annotation
2767 *
2768 * Dump the annotation
2769 */
2770static void
2771xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2772{
2773 xmlChar *content;
2774
2775 if (annot == NULL)
2776 return;
2777
2778 content = xmlNodeGetContent(annot->content);
2779 if (content != NULL) {
2780 fprintf(output, " Annot: %s\n", content);
2781 xmlFree(content);
2782 } else
2783 fprintf(output, " Annot: empty\n");
2784}
2785
2786/**
2787 * xmlSchemaTypeDump:
2788 * @output: the file output
2789 * @type: a type structure
2790 *
2791 * Dump a SchemaType structure
2792 */
2793static void
2794xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2795{
2796 if (type == NULL) {
2797 fprintf(output, "Type: NULL\n");
2798 return;
2799 }
2800 fprintf(output, "Type: ");
2801 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002802 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002803 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002804 fprintf(output, "no name ");
2805 if (type->targetNamespace != NULL)
2806 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002807 switch (type->type) {
2808 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002809 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002810 break;
2811 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002812 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002813 break;
2814 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002815 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002816 break;
2817 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002818 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002819 break;
2820 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002821 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002822 break;
2823 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002824 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002825 break;
2826 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002827 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002828 break;
2829 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002830 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002831 break;
2832 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002833 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002834 break;
2835 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002836 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00002837 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002838 }
2839 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002840 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002841 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002842 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002843 break;
2844 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002845 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002846 break;
2847 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002848 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002849 break;
2850 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002851 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002852 break;
2853 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002854 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002855 break;
2856 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002857 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002858 break;
2859 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002860 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002861 break;
2862 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002863 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002864 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002865 }
2866 fprintf(output, "\n");
2867 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002868 fprintf(output, " min: %d ", type->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002869 if (type->maxOccurs >= UNBOUNDED)
2870 fprintf(output, "max: unbounded\n");
2871 else if (type->maxOccurs != 1)
2872 fprintf(output, "max: %d\n", type->maxOccurs);
2873 else
2874 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002875 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002876 if (type->base != NULL) {
2877 fprintf(output, " base type: %s", type->base);
2878 if (type->baseNs != NULL)
2879 fprintf(output, " ns %s\n", type->baseNs);
2880 else
2881 fprintf(output, "\n");
2882 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002883 if (type->annot != NULL)
2884 xmlSchemaAnnotDump(output, type->annot);
2885 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002886 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002887
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002888 fprintf(output, " subtypes: ");
2889 while (sub != NULL) {
2890 fprintf(output, "%s ", sub->name);
2891 sub = sub->next;
2892 }
2893 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002894 }
2895
2896}
2897
2898/**
2899 * xmlSchemaDump:
2900 * @output: the file output
2901 * @schema: a schema structure
2902 *
2903 * Dump a Schema structure.
2904 */
2905void
2906xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2907{
Daniel Veillardce682bc2004-11-05 17:22:25 +00002908 if (output == NULL)
2909 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002910 if (schema == NULL) {
2911 fprintf(output, "Schemas: NULL\n");
2912 return;
2913 }
2914 fprintf(output, "Schemas: ");
2915 if (schema->name != NULL)
2916 fprintf(output, "%s, ", schema->name);
2917 else
2918 fprintf(output, "no name, ");
2919 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002920 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002921 else
2922 fprintf(output, "no target namespace");
2923 fprintf(output, "\n");
2924 if (schema->annot != NULL)
2925 xmlSchemaAnnotDump(output, schema->annot);
2926
2927 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2928 output);
2929 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002930 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002931}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002932
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002933#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00002934#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002935/**
2936 * xmlSchemaDebugDumpIDCTable:
2937 * @vctxt: the WXS validation context
2938 *
2939 * Displays the current IDC table for debug purposes.
2940 */
2941static void
2942xmlSchemaDebugDumpIDCTable(FILE * output,
2943 const xmlChar *namespaceName,
2944 const xmlChar *localName,
2945 xmlSchemaPSVIIDCBindingPtr bind)
2946{
2947 xmlChar *str = NULL, *value;
2948 xmlSchemaPSVIIDCNodePtr tab;
2949 xmlSchemaPSVIIDCKeyPtr key;
2950 int i, j, res;
2951
2952 fprintf(output, "IDC: TABLES on %s\n",
2953 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
2954 FREE_AND_NULL(str)
2955
2956 if (bind == NULL)
2957 return;
2958 do {
2959 fprintf(output, "IDC: BINDING %s\n",
2960 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
2961 bind->definition->name));
2962 FREE_AND_NULL(str)
2963 for (i = 0; i < bind->nbNodes; i++) {
2964 tab = bind->nodeTable[i];
2965 fprintf(output, " ( ");
2966 for (j = 0; j < bind->definition->nbFields; j++) {
2967 key = tab->keys[j];
2968 if ((key != NULL) && (key->compValue != NULL)) {
2969#ifdef IDC_VALUE_SUPPORT
2970 res = xmlSchemaGetCanonValue(key->compValue, &value);
2971#else
2972 value = xmlStrdup(BAD_CAST "dummy-value");
2973 res = 0;
2974#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002975 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002976 fprintf(output, "\"%s\" ", value);
2977 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002978 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002979 if (res == 0)
2980 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002981 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002982 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002983 else
2984 fprintf(output, "(key missing), ");
2985 }
2986 fprintf(output, ")\n");
2987 }
2988 bind = bind->next;
2989 } while (bind != NULL);
2990}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00002991#endif /* DEBUG_IDC */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002992#endif /* IDC_ENABLED */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002993#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002994
2995/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002996 * *
2997 * Utilities *
2998 * *
2999 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003000
Daniel Veillardc0826a72004-08-10 14:17:33 +00003001/**
3002 * xmlSchemaGetPropNode:
3003 * @node: the element node
3004 * @name: the name of the attribute
3005 *
3006 * Seeks an attribute with a name of @name in
3007 * no namespace.
3008 *
3009 * Returns the attribute or NULL if not present.
3010 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003011static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003012xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003013{
3014 xmlAttrPtr prop;
3015
Daniel Veillardc0826a72004-08-10 14:17:33 +00003016 if ((node == NULL) || (name == NULL))
3017 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003018 prop = node->properties;
3019 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003020 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3021 return(prop);
3022 prop = prop->next;
3023 }
3024 return (NULL);
3025}
3026
3027/**
3028 * xmlSchemaGetPropNodeNs:
3029 * @node: the element node
3030 * @uri: the uri
3031 * @name: the name of the attribute
3032 *
3033 * Seeks an attribute with a local name of @name and
3034 * a namespace URI of @uri.
3035 *
3036 * Returns the attribute or NULL if not present.
3037 */
3038static xmlAttrPtr
3039xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3040{
3041 xmlAttrPtr prop;
3042
3043 if ((node == NULL) || (name == NULL))
3044 return(NULL);
3045 prop = node->properties;
3046 while (prop != NULL) {
3047 if ((prop->ns != NULL) &&
3048 xmlStrEqual(prop->name, BAD_CAST name) &&
3049 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003050 return(prop);
3051 prop = prop->next;
3052 }
3053 return (NULL);
3054}
3055
3056static const xmlChar *
3057xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3058{
3059 xmlChar *val;
3060 const xmlChar *ret;
3061
3062 val = xmlNodeGetContent(node);
3063 if (val == NULL)
3064 return(NULL);
3065 ret = xmlDictLookup(ctxt->dict, val, -1);
3066 xmlFree(val);
3067 return(ret);
3068}
3069
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003070/**
3071 * xmlSchemaGetProp:
3072 * @ctxt: the parser context
3073 * @node: the node
3074 * @name: the property name
3075 *
3076 * Read a attribute value and internalize the string
3077 *
3078 * Returns the string or NULL if not present.
3079 */
3080static const xmlChar *
3081xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3082 const char *name)
3083{
3084 xmlChar *val;
3085 const xmlChar *ret;
3086
3087 val = xmlGetProp(node, BAD_CAST name);
3088 if (val == NULL)
3089 return(NULL);
3090 ret = xmlDictLookup(ctxt->dict, val, -1);
3091 xmlFree(val);
3092 return(ret);
3093}
3094
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003095/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003096 * *
3097 * Parsing functions *
3098 * *
3099 ************************************************************************/
3100
3101/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003102 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003103 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003104 * @name: the element name
3105 * @ns: the element namespace
3106 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003107 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003108 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003109 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003110 */
3111static xmlSchemaElementPtr
3112xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003113 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003114{
3115 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003116
3117 if ((name == NULL) || (schema == NULL))
3118 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003119
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003120 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003121 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003122 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003123 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003124 } else
3125 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003126 /*
3127 * This one was removed, since top level element declarations have
3128 * the target namespace specified in targetNamespace of the <schema>
3129 * information element, even if elementFormDefault is "unqualified".
3130 */
3131
3132 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003133 if (xmlStrEqual(namespace, schema->targetNamespace))
3134 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3135 else
3136 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003137 if ((ret != NULL) &&
3138 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003139 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003140 }
William M. Bracke7091952004-05-11 15:09:58 +00003141 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003142
William M. Brack2f2a6632004-08-20 23:09:47 +00003143 /*
3144 * Removed since imported components will be hold by the main schema only.
3145 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003146 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003147 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003148 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003149 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003150 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003151 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003152 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3153 return (ret);
3154 } else
3155 ret = NULL;
3156 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003157 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003158#ifdef DEBUG
3159 if (ret == NULL) {
3160 if (namespace == NULL)
3161 fprintf(stderr, "Unable to lookup type %s", name);
3162 else
3163 fprintf(stderr, "Unable to lookup type %s:%s", name,
3164 namespace);
3165 }
3166#endif
3167 return (ret);
3168}
3169
3170/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003171 * xmlSchemaGetType:
3172 * @schema: the schemas context
3173 * @name: the type name
3174 * @ns: the type namespace
3175 *
3176 * Lookup a type in the schemas or the predefined types
3177 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003178 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003179 */
3180static xmlSchemaTypePtr
3181xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003182 const xmlChar * namespace)
3183{
Daniel Veillard4255d502002-04-16 15:50:10 +00003184 xmlSchemaTypePtr ret;
3185
3186 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003187 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003188 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003189 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003190 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003191 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003192 }
3193 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003194 if (ret != NULL)
3195 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003196 /*
3197 * Removed, since the imported components will be grafted on the
3198 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003199 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003200 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003201 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003202 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003203 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003204 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003205 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3206 return (ret);
3207 } else
3208 ret = NULL;
3209 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003210 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003211#ifdef DEBUG
3212 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003213 if (namespace == NULL)
3214 fprintf(stderr, "Unable to lookup type %s", name);
3215 else
3216 fprintf(stderr, "Unable to lookup type %s:%s", name,
3217 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003218 }
3219#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003220 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003221}
3222
Daniel Veillard3646d642004-06-02 19:19:14 +00003223/**
3224 * xmlSchemaGetAttribute:
3225 * @schema: the context of the schema
3226 * @name: the name of the attribute
3227 * @ns: the target namespace of the attribute
3228 *
3229 * Lookup a an attribute in the schema or imported schemas
3230 *
3231 * Returns the attribute declaration or NULL if not found.
3232 */
3233static xmlSchemaAttributePtr
3234xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
3235 const xmlChar * namespace)
3236{
3237 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003238
3239 if ((name == NULL) || (schema == NULL))
3240 return (NULL);
3241
3242
3243 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
3244 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
3245 return (ret);
3246 else
3247 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003248 /*
3249 * Removed, since imported components will be hold by the main schema only.
3250 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003251 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003252 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003253 else
3254 import = xmlHashLookup(schema->schemasImports, namespace);
3255 if (import != NULL) {
3256 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
3257 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
3258 return (ret);
3259 } else
3260 ret = NULL;
3261 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003262 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003263#ifdef DEBUG
3264 if (ret == NULL) {
3265 if (namespace == NULL)
3266 fprintf(stderr, "Unable to lookup attribute %s", name);
3267 else
3268 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
3269 namespace);
3270 }
3271#endif
3272 return (ret);
3273}
3274
3275/**
3276 * xmlSchemaGetAttributeGroup:
3277 * @schema: the context of the schema
3278 * @name: the name of the attribute group
3279 * @ns: the target namespace of the attribute group
3280 *
3281 * Lookup a an attribute group in the schema or imported schemas
3282 *
3283 * Returns the attribute group definition or NULL if not found.
3284 */
3285static xmlSchemaAttributeGroupPtr
3286xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
3287 const xmlChar * namespace)
3288{
3289 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003290
3291 if ((name == NULL) || (schema == NULL))
3292 return (NULL);
3293
3294
3295 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
3296 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3297 return (ret);
3298 else
3299 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003300 /*
3301 * Removed since imported components will be hold by the main schema only.
3302 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003303 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003304 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003305 else
3306 import = xmlHashLookup(schema->schemasImports, namespace);
3307 if (import != NULL) {
3308 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
3309 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3310 return (ret);
3311 else
3312 ret = NULL;
3313 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003314 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003315#ifdef DEBUG
3316 if (ret == NULL) {
3317 if (namespace == NULL)
3318 fprintf(stderr, "Unable to lookup attribute group %s", name);
3319 else
3320 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
3321 namespace);
3322 }
3323#endif
3324 return (ret);
3325}
3326
3327/**
3328 * xmlSchemaGetGroup:
3329 * @schema: the context of the schema
3330 * @name: the name of the group
3331 * @ns: the target namespace of the group
3332 *
3333 * Lookup a group in the schema or imported schemas
3334 *
3335 * Returns the group definition or NULL if not found.
3336 */
3337static xmlSchemaTypePtr
3338xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
3339 const xmlChar * namespace)
3340{
3341 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003342
3343 if ((name == NULL) || (schema == NULL))
3344 return (NULL);
3345
3346
3347 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
3348 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3349 return (ret);
3350 else
3351 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003352 /*
3353 * Removed since imported components will be hold by the main schema only.
3354 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003355 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003356 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003357 else
3358 import = xmlHashLookup(schema->schemasImports, namespace);
3359 if (import != NULL) {
3360 ret = xmlSchemaGetGroup(import->schema, name, namespace);
3361 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3362 return (ret);
3363 else
3364 ret = NULL;
3365 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003366 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003367#ifdef DEBUG
3368 if (ret == NULL) {
3369 if (namespace == NULL)
3370 fprintf(stderr, "Unable to lookup group %s", name);
3371 else
3372 fprintf(stderr, "Unable to lookup group %s:%s", name,
3373 namespace);
3374 }
3375#endif
3376 return (ret);
3377}
3378
Daniel Veillard4255d502002-04-16 15:50:10 +00003379/************************************************************************
3380 * *
3381 * Parsing functions *
3382 * *
3383 ************************************************************************/
3384
3385#define IS_BLANK_NODE(n) \
3386 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
3387
3388/**
3389 * xmlSchemaIsBlank:
3390 * @str: a string
3391 *
3392 * Check if a string is ignorable
3393 *
3394 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
3395 */
3396static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003397xmlSchemaIsBlank(xmlChar * str)
3398{
Daniel Veillard4255d502002-04-16 15:50:10 +00003399 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003400 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003401 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00003402 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003403 return (0);
3404 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003405 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003406 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003407}
3408
3409/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003410 * xmlSchemaAddAssembledItem:
3411 * @ctxt: a schema parser context
3412 * @schema: the schema being built
3413 * @item: the item
3414 *
3415 * Add a item to the schema's list of current items.
3416 * This is used if the schema was already constructed and
3417 * new schemata need to be added to it.
3418 * *WARNING* this interface is highly subject to change.
3419 *
3420 * Returns 0 if suceeds and -1 if an internal error occurs.
3421 */
3422static int
3423xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
3424 xmlSchemaTypePtr item)
3425{
3426 static int growSize = 100;
3427 xmlSchemaAssemblePtr ass;
3428
3429 ass = ctxt->assemble;
3430 if (ass->sizeItems < 0) {
3431 /* If disabled. */
3432 return (0);
3433 }
3434 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003435 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003436 if (ass->items == NULL) {
3437 xmlSchemaPErrMemory(ctxt,
3438 "allocating new item buffer", NULL);
3439 return (-1);
3440 }
3441 ass->sizeItems = growSize;
3442 } else if (ass->sizeItems <= ass->nbItems) {
3443 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003444 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003445 ass->sizeItems * sizeof(xmlSchemaTypePtr));
3446 if (ass->items == NULL) {
3447 xmlSchemaPErrMemory(ctxt,
3448 "growing item buffer", NULL);
3449 ass->sizeItems = 0;
3450 return (-1);
3451 }
3452 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003453 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003454 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
3455 return (0);
3456}
3457
3458/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003459 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003460 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003461 * @schema: the schema being built
3462 * @name: the item name
3463 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003464 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003465 * *WARNING* this interface is highly subject to change
3466 *
3467 * Returns the new struture or NULL in case of error
3468 */
3469static xmlSchemaNotationPtr
3470xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003471 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003472{
3473 xmlSchemaNotationPtr ret = NULL;
3474 int val;
3475
3476 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3477 return (NULL);
3478
3479 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003480 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003481 if (schema->notaDecl == NULL)
3482 return (NULL);
3483
3484 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
3485 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003486 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003487 return (NULL);
3488 }
3489 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003490 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003491 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
3492 ret);
3493 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003494 /*
3495 * TODO: This should never happen, since a unique name will be computed.
3496 * If it fails, then an other internal error must have occured.
3497 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003498 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3499 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003500 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003501 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003502 xmlFree(ret);
3503 return (NULL);
3504 }
3505 return (ret);
3506}
3507
3508
3509/**
3510 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003511 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003512 * @schema: the schema being built
3513 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003514 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003515 *
3516 * Add an XML schema Attrribute declaration
3517 * *WARNING* this interface is highly subject to change
3518 *
3519 * Returns the new struture or NULL in case of error
3520 */
3521static xmlSchemaAttributePtr
3522xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003523 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003524 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003525{
3526 xmlSchemaAttributePtr ret = NULL;
3527 int val;
3528
3529 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3530 return (NULL);
3531
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003532#ifdef DEBUG
3533 fprintf(stderr, "Adding attribute %s\n", name);
3534 if (namespace != NULL)
3535 fprintf(stderr, " target namespace %s\n", namespace);
3536#endif
3537
Daniel Veillard4255d502002-04-16 15:50:10 +00003538 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003539 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003540 if (schema->attrDecl == NULL)
3541 return (NULL);
3542
3543 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3544 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003545 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003546 return (NULL);
3547 }
3548 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003549 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003550 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00003551 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003552 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003553 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003554 if (topLevel) {
3555 xmlSchemaPCustomErr(ctxt,
3556 XML_SCHEMAP_REDEFINED_ATTR,
3557 NULL, NULL, node,
3558 "A global attribute declaration with the name '%s' does "
3559 "already exist", name);
3560 xmlFree(ret);
3561 return (NULL);
3562 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003563 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003564 /*
3565 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
3566 * in the scenario:
3567 * 1. multiple top-level complex types have different target
3568 * namespaces but have the SAME NAME; this can happen if
3569 * schemata are imported
3570 * 2. those complex types contain attributes with an equal name
3571 * 3. those attributes are in no namespace
3572 * We will compute a new context string.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003573 */
3574 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003575 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00003576 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003577
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003578 if (val != 0) {
3579 xmlSchemaPCustomErr(ctxt,
3580 XML_SCHEMAP_INTERNAL,
3581 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003582 "Internal error: xmlSchemaAddAttribute, "
3583 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003584 "could not be added to the hash.", name);
3585 xmlFree(ret);
3586 return (NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003587 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003588 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003589 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003590 if (ctxt->assemble != NULL)
3591 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003592 return (ret);
3593}
3594
3595/**
3596 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003597 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003598 * @schema: the schema being built
3599 * @name: the item name
3600 *
3601 * Add an XML schema Attrribute Group declaration
3602 *
3603 * Returns the new struture or NULL in case of error
3604 */
3605static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003606xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003607 xmlSchemaPtr schema, const xmlChar * name,
3608 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003609{
3610 xmlSchemaAttributeGroupPtr ret = NULL;
3611 int val;
3612
3613 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3614 return (NULL);
3615
3616 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003617 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003618 if (schema->attrgrpDecl == NULL)
3619 return (NULL);
3620
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003621 ret =
3622 (xmlSchemaAttributeGroupPtr)
3623 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003624 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003625 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003626 return (NULL);
3627 }
3628 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003629 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003630 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003631 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003632 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003633 xmlSchemaPCustomErr(ctxt,
3634 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3635 NULL, NULL, node,
3636 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003637 xmlFree(ret);
3638 return (NULL);
3639 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003640 if (ctxt->assemble != NULL)
3641 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003642 return (ret);
3643}
3644
3645/**
3646 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003647 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003648 * @schema: the schema being built
3649 * @name: the type name
3650 * @namespace: the type namespace
3651 *
3652 * Add an XML schema Element declaration
3653 * *WARNING* this interface is highly subject to change
3654 *
3655 * Returns the new struture or NULL in case of error
3656 */
3657static xmlSchemaElementPtr
3658xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003659 const xmlChar * name, const xmlChar * namespace,
3660 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003661{
3662 xmlSchemaElementPtr ret = NULL;
3663 int val;
3664
3665 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3666 return (NULL);
3667
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003668#ifdef DEBUG
3669 fprintf(stderr, "Adding element %s\n", name);
3670 if (namespace != NULL)
3671 fprintf(stderr, " target namespace %s\n", namespace);
3672#endif
3673
Daniel Veillard4255d502002-04-16 15:50:10 +00003674 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003675 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003676 if (schema->elemDecl == NULL)
3677 return (NULL);
3678
3679 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3680 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003681 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003682 return (NULL);
3683 }
3684 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003685 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003686 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003687 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003688 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003689 if (topLevel) {
3690 xmlSchemaPCustomErr(ctxt,
3691 XML_SCHEMAP_REDEFINED_ELEMENT,
3692 NULL, NULL, node,
3693 "A global element declaration with the name '%s' does "
3694 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003695 xmlFree(ret);
3696 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003697 } else {
3698 char buf[30];
3699
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003700 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003701 val = xmlHashAddEntry3(schema->elemDecl, name,
3702 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003703 if (val != 0) {
3704 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003705 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003706 NULL, NULL, node,
3707 "Internal error: xmlSchemaAddElement, "
3708 "a dublicate element declaration with the name '%s' "
3709 "could not be added to the hash.", name);
3710 xmlFree(ret);
3711 return (NULL);
3712 }
3713 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003714
Daniel Veillard4255d502002-04-16 15:50:10 +00003715 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003716 if (ctxt->assemble != NULL)
3717 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003718 return (ret);
3719}
3720
3721/**
3722 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003723 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003724 * @schema: the schema being built
3725 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003726 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003727 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003728 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003729 * *WARNING* this interface is highly subject to change
3730 *
3731 * Returns the new struture or NULL in case of error
3732 */
3733static xmlSchemaTypePtr
3734xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003735 const xmlChar * name, const xmlChar * namespace,
3736 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003737{
3738 xmlSchemaTypePtr ret = NULL;
3739 int val;
3740
3741 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3742 return (NULL);
3743
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003744#ifdef DEBUG
3745 fprintf(stderr, "Adding type %s\n", name);
3746 if (namespace != NULL)
3747 fprintf(stderr, " target namespace %s\n", namespace);
3748#endif
3749
Daniel Veillard4255d502002-04-16 15:50:10 +00003750 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003751 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003752 if (schema->typeDecl == NULL)
3753 return (NULL);
3754
3755 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3756 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003757 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003758 return (NULL);
3759 }
3760 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003761 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003762 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003763 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003764 if (val != 0) {
3765 if (ctxt->includes == 0) {
3766 xmlSchemaPCustomErr(ctxt,
3767 XML_SCHEMAP_REDEFINED_TYPE,
3768 NULL, NULL, node,
3769 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003770 xmlFree(ret);
3771 return (NULL);
3772 } else {
3773 xmlSchemaTypePtr prev;
3774
3775 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3776 if (prev == NULL) {
3777 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003778 XML_ERR_INTERNAL_ERROR,
3779 "Internal error: xmlSchemaAddType, on type "
3780 "'%s'.\n",
3781 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003782 xmlFree(ret);
3783 return (NULL);
3784 }
3785 ret->redef = prev->redef;
3786 prev->redef = ret;
3787 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003788 }
3789 ret->minOccurs = 1;
3790 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003791 ret->attributeUses = NULL;
3792 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003793 if (ctxt->assemble != NULL)
3794 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003795 return (ret);
3796}
3797
3798/**
3799 * xmlSchemaAddGroup:
3800 * @ctxt: a schema validation context
3801 * @schema: the schema being built
3802 * @name: the group name
3803 *
3804 * Add an XML schema Group definition
3805 *
3806 * Returns the new struture or NULL in case of error
3807 */
3808static xmlSchemaTypePtr
3809xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003810 const xmlChar *name, const xmlChar *namespaceName,
3811 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003812{
3813 xmlSchemaTypePtr ret = NULL;
3814 int val;
3815
3816 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3817 return (NULL);
3818
3819 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003820 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003821 if (schema->groupDecl == NULL)
3822 return (NULL);
3823
3824 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3825 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003826 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003827 return (NULL);
3828 }
3829 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003830 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003831 val =
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003832 xmlHashAddEntry2(schema->groupDecl, name, namespaceName,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003833 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003834 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003835 xmlSchemaPCustomErr(ctxt,
3836 XML_SCHEMAP_REDEFINED_GROUP,
3837 NULL, NULL, node,
3838 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003839 xmlFree(ret);
3840 return (NULL);
3841 }
3842 ret->minOccurs = 1;
3843 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003844 if (ctxt->assemble != NULL)
3845 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003846 return (ret);
3847}
3848
Daniel Veillard3646d642004-06-02 19:19:14 +00003849/**
3850 * xmlSchemaNewWildcardNs:
3851 * @ctxt: a schema validation context
3852 *
3853 * Creates a new wildcard namespace constraint.
3854 *
3855 * Returns the new struture or NULL in case of error
3856 */
3857static xmlSchemaWildcardNsPtr
3858xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3859{
3860 xmlSchemaWildcardNsPtr ret;
3861
3862 ret = (xmlSchemaWildcardNsPtr)
3863 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3864 if (ret == NULL) {
3865 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3866 return (NULL);
3867 }
3868 ret->value = NULL;
3869 ret->next = NULL;
3870 return (ret);
3871}
3872
3873/**
3874 * xmlSchemaAddWildcard:
3875 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003876 * Adds a wildcard. It corresponds to a
3877 * xsd:anyAttribute and is used as storage for namespace
3878 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003879 *
3880 * Returns the new struture or NULL in case of error
3881 */
3882static xmlSchemaWildcardPtr
3883xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3884{
3885 xmlSchemaWildcardPtr ret = NULL;
3886
3887 if (ctxt == NULL)
3888 return (NULL);
3889
3890 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3891 if (ret == NULL) {
3892 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3893 return (NULL);
3894 }
3895 memset(ret, 0, sizeof(xmlSchemaWildcard));
3896 ret->minOccurs = 1;
3897 ret->maxOccurs = 1;
3898
3899 return (ret);
3900}
3901
Daniel Veillard4255d502002-04-16 15:50:10 +00003902/************************************************************************
3903 * *
3904 * Utilities for parsing *
3905 * *
3906 ************************************************************************/
3907
3908/**
3909 * xmlGetQNameProp:
3910 * @ctxt: a schema validation context
3911 * @node: a subtree containing XML Schema informations
3912 * @name: the attribute name
3913 * @namespace: the result namespace if any
3914 *
3915 * Extract a QName Attribute value
3916 *
3917 * Returns the NCName or NULL if not found, and also update @namespace
3918 * with the namespace URI
3919 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003920static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003921xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003922 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003923{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003924 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003925 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003926 const xmlChar *ret, *prefix;
3927 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003928 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003929
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003930 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003931 attr = xmlSchemaGetPropNode(node, name);
3932 if (attr == NULL)
3933 return (NULL);
3934 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003935
Daniel Veillard4255d502002-04-16 15:50:10 +00003936 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003937 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003938
Daniel Veillardba0153a2004-04-01 10:42:31 +00003939 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003940 ns = xmlSearchNs(node->doc, node, 0);
3941 if (ns) {
3942 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3943 return (val);
3944 }
3945 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003946 ret = xmlSplitQName3(val, &len);
3947 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003948 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003949 }
3950 ret = xmlDictLookup(ctxt->dict, ret, -1);
3951 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003952
3953 ns = xmlSearchNs(node->doc, node, prefix);
3954 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003955 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3956 NULL, NULL, (xmlNodePtr) attr,
3957 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003958 "The QName value '%s' has no corresponding namespace "
3959 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003960 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003961 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003962 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003963 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003964}
3965
3966/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003967 * xmlSchemaPValAttrNodeQNameValue:
3968 * @ctxt: a schema parser context
3969 * @schema: the schema context
3970 * @ownerDes: the designation of the parent element
3971 * @ownerItem: the parent as a schema object
3972 * @value: the QName value
3973 * @local: the resulting local part if found, the attribute value otherwise
3974 * @uri: the resulting namespace URI if found
3975 *
3976 * Extracts the local name and the URI of a QName value and validates it.
3977 * This one is intended to be used on attribute values that
3978 * should resolve to schema components.
3979 *
3980 * Returns 0, in case the QName is valid, a positive error code
3981 * if not valid and -1 if an internal error occurs.
3982 */
3983static int
3984xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3985 xmlSchemaPtr schema,
3986 xmlChar **ownerDes,
3987 xmlSchemaTypePtr ownerItem,
3988 xmlAttrPtr attr,
3989 const xmlChar *value,
3990 const xmlChar **uri,
3991 const xmlChar **prefix,
3992 const xmlChar **local)
3993{
3994 const xmlChar *pref;
3995 xmlNsPtr ns;
3996 int len, ret;
3997
3998 *uri = NULL;
3999 *local = NULL;
4000 if (prefix != 0)
4001 *prefix = NULL;
4002 ret = xmlValidateQName(value, 1);
4003 if (ret > 0) {
4004 xmlSchemaPSimpleTypeErr(ctxt,
4005 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4006 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004007 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4008 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004009 NULL, NULL, NULL);
4010 *local = value;
4011 return (ctxt->err);
4012 } else if (ret < 0)
4013 return (-1);
4014
4015 if (!strchr((char *) value, ':')) {
4016 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4017 if (ns)
4018 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4019 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4020 /*
4021 * This one takes care of included schemas with no
4022 * target namespace.
4023 */
4024 *uri = schema->targetNamespace;
4025 }
4026 *local = value;
4027 return (0);
4028 }
4029 /*
4030 * At this point xmlSplitQName3 has to return a local name.
4031 */
4032 *local = xmlSplitQName3(value, &len);
4033 *local = xmlDictLookup(ctxt->dict, *local, -1);
4034 pref = xmlDictLookup(ctxt->dict, value, len);
4035 if (prefix != 0)
4036 *prefix = pref;
4037 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4038 if (ns == NULL) {
4039 xmlSchemaPSimpleTypeErr(ctxt,
4040 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4041 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004042 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
4043 "The QName value '%s' has no corresponding namespace "
4044 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004045 return (ctxt->err);
4046 } else {
4047 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4048 }
4049 return (0);
4050}
4051
4052/**
4053 * xmlSchemaPValAttrNodeQName:
4054 * @ctxt: a schema parser context
4055 * @schema: the schema context
4056 * @ownerDes: the designation of the owner element
4057 * @ownerItem: the owner as a schema object
4058 * @attr: the attribute node
4059 * @local: the resulting local part if found, the attribute value otherwise
4060 * @uri: the resulting namespace URI if found
4061 *
4062 * Extracts and validates the QName of an attribute value.
4063 * This one is intended to be used on attribute values that
4064 * should resolve to schema components.
4065 *
4066 * Returns 0, in case the QName is valid, a positive error code
4067 * if not valid and -1 if an internal error occurs.
4068 */
4069static int
4070xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
4071 xmlSchemaPtr schema,
4072 xmlChar **ownerDes,
4073 xmlSchemaTypePtr ownerItem,
4074 xmlAttrPtr attr,
4075 const xmlChar **uri,
4076 const xmlChar **prefix,
4077 const xmlChar **local)
4078{
4079 const xmlChar *value;
4080
4081 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4082 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
4083 ownerDes, ownerItem, attr, value, uri, prefix, local));
4084}
4085
4086/**
4087 * xmlSchemaPValAttrQName:
4088 * @ctxt: a schema parser context
4089 * @schema: the schema context
4090 * @ownerDes: the designation of the parent element
4091 * @ownerItem: the owner as a schema object
4092 * @ownerElem: the parent node of the attribute
4093 * @name: the name of the attribute
4094 * @local: the resulting local part if found, the attribute value otherwise
4095 * @uri: the resulting namespace URI if found
4096 *
4097 * Extracts and validates the QName of an attribute value.
4098 *
4099 * Returns 0, in case the QName is valid, a positive error code
4100 * if not valid and -1 if an internal error occurs.
4101 */
4102static int
4103xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
4104 xmlSchemaPtr schema,
4105 xmlChar **ownerDes,
4106 xmlSchemaTypePtr ownerItem,
4107 xmlNodePtr ownerElem,
4108 const char *name,
4109 const xmlChar **uri,
4110 const xmlChar **prefix,
4111 const xmlChar **local)
4112{
4113 xmlAttrPtr attr;
4114
4115 attr = xmlSchemaGetPropNode(ownerElem, name);
4116 if (attr == NULL) {
4117 *local = NULL;
4118 *uri = NULL;
4119 return (0);
4120 }
4121 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
4122 ownerDes, ownerItem, attr, uri, prefix, local));
4123}
4124
4125/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004126 * xmlGetMaxOccurs:
4127 * @ctxt: a schema validation context
4128 * @node: a subtree containing XML Schema informations
4129 *
4130 * Get the maxOccurs property
4131 *
4132 * Returns the default if not found, or the value
4133 */
4134static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004135xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4136 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004137{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004138 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004139 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004140 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004141
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004142 attr = xmlSchemaGetPropNode(node, "maxOccurs");
4143 if (attr == NULL)
4144 return (def);
4145 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004146
4147 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004148 if (max != UNBOUNDED) {
4149 xmlSchemaPSimpleTypeErr(ctxt,
4150 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4151 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4152 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4153 val, NULL, NULL, NULL);
4154 return (def);
4155 } else
4156 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00004157 }
4158
4159 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004160 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004161 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004162 if (*cur == 0) {
4163 xmlSchemaPSimpleTypeErr(ctxt,
4164 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4165 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4166 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4167 val, NULL, NULL, NULL);
4168 return (def);
4169 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004170 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004171 ret = ret * 10 + (*cur - '0');
4172 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004173 }
William M. Brack76e95df2003-10-18 16:20:14 +00004174 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004175 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004176 /*
4177 * TODO: Restrict the maximal value to Integer.
4178 */
4179 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4180 xmlSchemaPSimpleTypeErr(ctxt,
4181 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4182 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4183 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4184 val, NULL, NULL, NULL);
4185 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004186 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004187 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004188}
4189
4190/**
4191 * xmlGetMinOccurs:
4192 * @ctxt: a schema validation context
4193 * @node: a subtree containing XML Schema informations
4194 *
4195 * Get the minOccurs property
4196 *
4197 * Returns the default if not found, or the value
4198 */
4199static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004200xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4201 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004202{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004203 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004204 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004205 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004206
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004207 attr = xmlSchemaGetPropNode(node, "minOccurs");
4208 if (attr == NULL)
4209 return (def);
4210 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004211 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004212 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004213 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004214 if (*cur == 0) {
4215 xmlSchemaPSimpleTypeErr(ctxt,
4216 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4217 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4218 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4219 val, NULL, NULL, NULL);
4220 return (def);
4221 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004222 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004223 ret = ret * 10 + (*cur - '0');
4224 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004225 }
William M. Brack76e95df2003-10-18 16:20:14 +00004226 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004227 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004228 /*
4229 * TODO: Restrict the maximal value to Integer.
4230 */
4231 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4232 xmlSchemaPSimpleTypeErr(ctxt,
4233 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4234 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4235 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4236 val, NULL, NULL, NULL);
4237 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004238 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004239 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004240}
4241
4242/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004243 * xmlSchemaPGetBoolNodeValue:
4244 * @ctxt: a schema validation context
4245 * @ownerDes: owner designation
4246 * @ownerItem: the owner as a schema item
4247 * @node: the node holding the value
4248 *
4249 * Converts a boolean string value into 1 or 0.
4250 *
4251 * Returns 0 or 1.
4252 */
4253static int
4254xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
4255 xmlChar **ownerDes,
4256 xmlSchemaTypePtr ownerItem,
4257 xmlNodePtr node)
4258{
4259 xmlChar *value = NULL;
4260 int res = 0;
4261
4262 value = xmlNodeGetContent(node);
4263 /*
4264 * 3.2.2.1 Lexical representation
4265 * An instance of a datatype that is defined as ·boolean·
4266 * can have the following legal literals {true, false, 1, 0}.
4267 */
4268 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
4269 res = 1;
4270 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
4271 res = 0;
4272 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
4273 res = 1;
4274 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
4275 res = 0;
4276 else {
4277 xmlSchemaPSimpleTypeErr(ctxt,
4278 XML_SCHEMAP_INVALID_BOOLEAN,
4279 ownerDes, ownerItem, node,
4280 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4281 "(1 | 0 | true | false)", BAD_CAST value,
4282 NULL, NULL, NULL);
4283 }
4284 if (value != NULL)
4285 xmlFree(value);
4286 return (res);
4287}
4288
4289/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004290 * xmlGetBooleanProp:
4291 * @ctxt: a schema validation context
4292 * @node: a subtree containing XML Schema informations
4293 * @name: the attribute name
4294 * @def: the default value
4295 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004296 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00004297 *
4298 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004299 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00004300 */
4301static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004302xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
4303 xmlChar **ownerDes,
4304 xmlSchemaTypePtr ownerItem,
4305 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004306 const char *name, int def)
4307{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004308 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004309
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004310 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004311 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004312 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004313 /*
4314 * 3.2.2.1 Lexical representation
4315 * An instance of a datatype that is defined as ·boolean·
4316 * can have the following legal literals {true, false, 1, 0}.
4317 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004318 if (xmlStrEqual(val, BAD_CAST "true"))
4319 def = 1;
4320 else if (xmlStrEqual(val, BAD_CAST "false"))
4321 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004322 else if (xmlStrEqual(val, BAD_CAST "1"))
4323 def = 1;
4324 else if (xmlStrEqual(val, BAD_CAST "0"))
4325 def = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004326 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004327 xmlSchemaPSimpleTypeErr(ctxt,
4328 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004329 ownerDes, ownerItem,
4330 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
William M. Brack2f2a6632004-08-20 23:09:47 +00004331 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4332 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004333 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004334 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004335}
4336
4337/************************************************************************
4338 * *
4339 * Shema extraction from an Infoset *
4340 * *
4341 ************************************************************************/
4342static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
4343 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004344 xmlNodePtr node,
4345 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004346static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
4347 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004348 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004349 xmlNodePtr node,
4350 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004351static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
4352 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004353 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004354 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004355static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
4356 xmlSchemaPtr schema,
4357 xmlNodePtr node);
4358static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
4359 xmlSchemaPtr schema,
4360 xmlNodePtr node);
4361static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
4362 ctxt,
4363 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004364 xmlNodePtr node,
4365 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004366static xmlSchemaAttributeGroupPtr
4367xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004368 xmlSchemaPtr schema, xmlNodePtr node,
4369 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004370static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
4371 xmlSchemaPtr schema,
4372 xmlNodePtr node);
4373static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
4374 xmlSchemaPtr schema,
4375 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00004376static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004377xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4378 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004379
4380/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004381 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004382 *
4383 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00004384 * @ownerDes: the designation of the parent element
4385 * @ownerItem: the schema object owner if existent
4386 * @attr: the schema attribute node being validated
4387 * @value: the value
4388 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00004389 *
4390 * Validates a value against the given built-in type.
4391 * This one is intended to be used internally for validation
4392 * of schema attribute values during parsing of the schema.
4393 *
4394 * Returns 0 if the value is valid, a positive error code
4395 * number otherwise and -1 in case of an internal or API error.
4396 */
4397static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004398xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
4399 xmlChar **ownerDes,
4400 xmlSchemaTypePtr ownerItem,
4401 xmlAttrPtr attr,
4402 const xmlChar *value,
4403 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004404{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004405
Daniel Veillardc0826a72004-08-10 14:17:33 +00004406 int ret = 0;
4407
4408 /*
4409 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
4410 * one is really meant to be used internally, so better not.
4411 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004412 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004413 return (-1);
4414 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4415 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004416 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004417 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004418 "type '%s' is not a built-in type.\n",
4419 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004420 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004421 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004422 switch (type->builtInType) {
4423 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004424 case XML_SCHEMAS_QNAME:
4425 case XML_SCHEMAS_ANYURI:
4426 case XML_SCHEMAS_TOKEN:
4427 case XML_SCHEMAS_LANGUAGE:
4428 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
4429 break;
4430
4431 /*
4432 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004433 ret = xmlValidateNCName(value, 1);
4434 break;
4435 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00004436 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004437 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004438 "Internal error: xmlSchemaPvalueAttrNode, use "
4439 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
4440 "for extracting QName valueues instead.\n",
4441 NULL, NULL);
4442 return (-1);
4443 case XML_SCHEMAS_ANYURI:
4444 if (value != NULL) {
4445 xmlURIPtr uri = xmlParseURI((const char *) value);
4446 if (uri == NULL)
4447 ret = 1;
4448 else
4449 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004450 }
4451 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004452 case XML_SCHEMAS_TOKEN: {
4453 const xmlChar *cur = value;
4454
4455 if (IS_BLANK_CH(*cur)) {
4456 ret = 1;
4457 } else while (*cur != 0) {
4458 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
4459 ret = 1;
4460 break;
4461 } else if (*cur == ' ') {
4462 cur++;
4463 if ((*cur == 0) || (*cur == ' ')) {
4464 ret = 1;
4465 break;
4466 }
4467 } else {
4468 cur++;
4469 }
4470 }
4471 }
4472 break;
4473 case XML_SCHEMAS_LANGUAGE:
4474 if (xmlCheckLanguageID(value) != 1)
4475 ret = 1;
4476 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004477 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004478 default: {
4479 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004480 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004481 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004482 "valueidation using the type '%s' is not implemented "
4483 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00004484 type->name, NULL);
4485 return (-1);
4486 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004487 }
4488 /*
4489 * TODO: Should we use the S4S error codes instead?
4490 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004491 if (ret < 0) {
4492 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
4493 XML_SCHEMAP_INTERNAL,
4494 "Internal error: xmlSchemaPValAttrNodeValue, "
4495 "failed to validate a schema attribute value.\n",
4496 NULL, NULL);
4497 return (-1);
4498 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004499 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
4500 xmlSchemaPSimpleTypeErr(ctxt,
4501 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
4502 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004503 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004504 NULL, NULL, NULL);
4505 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
4506 } else {
4507 xmlSchemaPSimpleTypeErr(ctxt,
4508 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
4509 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004510 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004511 NULL, NULL, NULL);
4512 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
4513 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004514 }
4515 return (ret);
4516}
4517
4518/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004519 * xmlSchemaPValAttrNode:
4520 *
4521 * @ctxt: a schema parser context
4522 * @ownerDes: the designation of the parent element
4523 * @ownerItem: the schema object owner if existent
4524 * @attr: the schema attribute node being validated
4525 * @type: the built-in type to be validated against
4526 * @value: the resulting value if any
4527 *
4528 * Extracts and validates a value against the given built-in type.
4529 * This one is intended to be used internally for validation
4530 * of schema attribute values during parsing of the schema.
4531 *
4532 * Returns 0 if the value is valid, a positive error code
4533 * number otherwise and -1 in case of an internal or API error.
4534 */
4535static int
4536xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4537 xmlChar **ownerDes,
4538 xmlSchemaTypePtr ownerItem,
4539 xmlAttrPtr attr,
4540 xmlSchemaTypePtr type,
4541 const xmlChar **value)
4542{
4543 const xmlChar *val;
4544
4545 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4546 return (-1);
4547
4548 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4549 if (value != NULL)
4550 *value = val;
4551
4552 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4553 val, type));
4554}
4555
4556/**
4557 * xmlSchemaPValAttr:
4558 *
4559 * @ctxt: a schema parser context
4560 * @node: the element node of the attribute
4561 * @ownerDes: the designation of the parent element
4562 * @ownerItem: the schema object owner if existent
4563 * @ownerElem: the owner element node
4564 * @name: the name of the schema attribute node
4565 * @type: the built-in type to be validated against
4566 * @value: the resulting value if any
4567 *
4568 * Extracts and validates a value against the given built-in type.
4569 * This one is intended to be used internally for validation
4570 * of schema attribute values during parsing of the schema.
4571 *
4572 * Returns 0 if the value is valid, a positive error code
4573 * number otherwise and -1 in case of an internal or API error.
4574 */
4575static int
4576xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4577 xmlChar **ownerDes,
4578 xmlSchemaTypePtr ownerItem,
4579 xmlNodePtr ownerElem,
4580 const char *name,
4581 xmlSchemaTypePtr type,
4582 const xmlChar **value)
4583{
4584 xmlAttrPtr attr;
4585
4586 if ((ctxt == NULL) || (type == NULL)) {
4587 if (value != NULL)
4588 *value = NULL;
4589 return (-1);
4590 }
4591 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4592 if (value != NULL)
4593 *value = NULL;
4594 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004595 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004596 "Internal error: xmlSchemaPValAttr, the given "
4597 "type '%s' is not a built-in type.\n",
4598 type->name, NULL);
4599 return (-1);
4600 }
4601 attr = xmlSchemaGetPropNode(ownerElem, name);
4602 if (attr == NULL) {
4603 if (value != NULL)
4604 *value = NULL;
4605 return (0);
4606 }
4607 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4608 type, value));
4609}
4610/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004611 * xmlSchemaParseAttrDecls:
4612 * @ctxt: a schema validation context
4613 * @schema: the schema being built
4614 * @node: a subtree containing XML Schema informations
4615 * @type: the hosting type
4616 *
4617 * parse a XML schema attrDecls declaration corresponding to
4618 * <!ENTITY % attrDecls
4619 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4620 */
4621static xmlNodePtr
4622xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4623 xmlNodePtr child, xmlSchemaTypePtr type)
4624{
4625 xmlSchemaAttributePtr lastattr, attr;
4626
4627 lastattr = NULL;
4628 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004629 (IS_SCHEMA(child, "attributeGroup"))) {
4630 attr = NULL;
4631 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004632 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004633 } else if (IS_SCHEMA(child, "attributeGroup")) {
4634 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004635 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004636 }
4637 if (attr != NULL) {
4638 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004639 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4640 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4641 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004642 type->attributes = attr;
4643 lastattr = attr;
4644 } else {
4645 lastattr->next = attr;
4646 lastattr = attr;
4647 }
4648 }
4649 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004650 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004651 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004652}
4653
4654/**
4655 * xmlSchemaParseAnnotation:
4656 * @ctxt: a schema validation context
4657 * @schema: the schema being built
4658 * @node: a subtree containing XML Schema informations
4659 *
4660 * parse a XML schema Attrribute declaration
4661 * *WARNING* this interface is highly subject to change
4662 *
William M. Bracke7091952004-05-11 15:09:58 +00004663 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004664 * 1 in case of success.
4665 */
4666static xmlSchemaAnnotPtr
4667xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4668 xmlNodePtr node)
4669{
4670 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004671 xmlNodePtr child = NULL;
4672 xmlAttrPtr attr;
4673 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004674
Daniel Veillardc0826a72004-08-10 14:17:33 +00004675 /*
4676 * INFO: S4S completed.
4677 */
4678 /*
4679 * id = ID
4680 * {any attributes with non-schema namespace . . .}>
4681 * Content: (appinfo | documentation)*
4682 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004683 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4684 return (NULL);
4685 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004686 attr = node->properties;
4687 while (attr != NULL) {
4688 if (((attr->ns == NULL) &&
4689 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4690 ((attr->ns != NULL) &&
4691 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4692
4693 xmlSchemaPIllegalAttrErr(ctxt,
4694 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4695 NULL, NULL, attr);
4696 }
4697 attr = attr->next;
4698 }
4699 /* TODO: Check id. */
4700
4701 /*
4702 * And now for the children...
4703 */
4704 child = node->children;
4705 while (child != NULL) {
4706 if (IS_SCHEMA(child, "appinfo")) {
4707 /* TODO: make available the content of "appinfo". */
4708 /*
4709 * source = anyURI
4710 * {any attributes with non-schema namespace . . .}>
4711 * Content: ({any})*
4712 */
4713 attr = child->properties;
4714 while (attr != NULL) {
4715 if (((attr->ns == NULL) &&
4716 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4717 ((attr->ns != NULL) &&
4718 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004719
Daniel Veillardc0826a72004-08-10 14:17:33 +00004720 xmlSchemaPIllegalAttrErr(ctxt,
4721 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4722 NULL, NULL, attr);
4723 }
4724 attr = attr->next;
4725 }
4726 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4727 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4728 child = child->next;
4729 } else if (IS_SCHEMA(child, "documentation")) {
4730 /* TODO: make available the content of "documentation". */
4731 /*
4732 * source = anyURI
4733 * {any attributes with non-schema namespace . . .}>
4734 * Content: ({any})*
4735 */
4736 attr = child->properties;
4737 while (attr != NULL) {
4738 if (attr->ns == NULL) {
4739 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4740 xmlSchemaPIllegalAttrErr(ctxt,
4741 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4742 NULL, NULL, attr);
4743 }
4744 } else {
4745 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4746 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4747 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4748
4749 xmlSchemaPIllegalAttrErr(ctxt,
4750 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4751 NULL, NULL, attr);
4752 }
4753 }
4754 attr = attr->next;
4755 }
4756 /*
4757 * Attribute "xml:lang".
4758 */
4759 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4760 if (attr != NULL)
4761 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4762 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4763 child = child->next;
4764 } else {
4765 if (!barked)
4766 xmlSchemaPContentErr(ctxt,
4767 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4768 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4769 barked = 1;
4770 child = child->next;
4771 }
4772 }
4773
Daniel Veillard4255d502002-04-16 15:50:10 +00004774 return (ret);
4775}
4776
4777/**
4778 * xmlSchemaParseFacet:
4779 * @ctxt: a schema validation context
4780 * @schema: the schema being built
4781 * @node: a subtree containing XML Schema informations
4782 *
4783 * parse a XML schema Facet declaration
4784 * *WARNING* this interface is highly subject to change
4785 *
4786 * Returns the new type structure or NULL in case of error
4787 */
4788static xmlSchemaFacetPtr
4789xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004790 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004791{
4792 xmlSchemaFacetPtr facet;
4793 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004794 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004795
4796 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4797 return (NULL);
4798
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004799 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004800 if (facet == NULL) {
4801 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4802 return (NULL);
4803 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004804 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004805 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004806 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004807 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4808 "Facet %s has no value\n", node->name, NULL);
4809 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004810 return (NULL);
4811 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004812 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004813 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004814 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004815 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004816 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004817 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004818 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004819 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004820 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004821 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004822 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004823 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004824 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004825 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004826 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004827 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004828 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004829 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004830 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004831 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004832 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004833 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4834 } else if (IS_SCHEMA(node, "minLength")) {
4835 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4836 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004837 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4838 "Unknown facet type %s\n", node->name, NULL);
4839 xmlSchemaFreeFacet(facet);
4840 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004841 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004842 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004843 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004844 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4845 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4846 const xmlChar *fixed;
4847
4848 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4849 if (fixed != NULL) {
4850 if (xmlStrEqual(fixed, BAD_CAST "true"))
4851 facet->fixed = 1;
4852 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004853 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004854 child = node->children;
4855
4856 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004857 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4858 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004859 }
4860 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004861 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4862 "Facet %s has unexpected child content\n",
4863 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004864 }
4865 return (facet);
4866}
4867
4868/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004869 * xmlSchemaParseWildcardNs:
4870 * @ctxt: a schema parser context
4871 * @wildc: the wildcard, already created
4872 * @node: a subtree containing XML Schema informations
4873 *
4874 * Parses the attribute "processContents" and "namespace"
4875 * of a xsd:anyAttribute and xsd:any.
4876 * *WARNING* this interface is highly subject to change
4877 *
4878 * Returns 0 if everything goes fine, a positive error code
4879 * if something is not valid and -1 if an internal error occurs.
4880 */
4881static int
4882xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4883 xmlSchemaPtr schema,
4884 xmlSchemaWildcardPtr wildc,
4885 xmlNodePtr node)
4886{
4887 const xmlChar *pc, *ns, *dictnsItem;
4888 int ret = 0;
4889 xmlChar *nsItem;
4890 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4891 xmlAttrPtr attr;
4892
4893 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4894 if ((pc == NULL)
4895 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4896 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4897 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4898 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4899 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4900 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4901 } else {
4902 xmlSchemaPSimpleTypeErr(ctxt,
4903 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4904 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004905 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004906 NULL, NULL, NULL);
4907 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4908 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4909 }
4910 /*
4911 * Build the namespace constraints.
4912 */
4913 attr = xmlSchemaGetPropNode(node, "namespace");
4914 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4915 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4916 wildc->any = 1;
4917 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4918 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4919 if (wildc->negNsSet == NULL) {
4920 return (-1);
4921 }
4922 wildc->negNsSet->value = schema->targetNamespace;
4923 } else {
4924 const xmlChar *end, *cur;
4925
4926 cur = ns;
4927 do {
4928 while (IS_BLANK_CH(*cur))
4929 cur++;
4930 end = cur;
4931 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4932 end++;
4933 if (end == cur)
4934 break;
4935 nsItem = xmlStrndup(cur, end - cur);
4936 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4937 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4938 xmlSchemaPSimpleTypeErr(ctxt,
4939 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4940 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004941 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004942 "((##any | ##other) | List of (anyURI | "
4943 "(##targetNamespace | ##local)))",
4944 nsItem, NULL, NULL, NULL);
4945 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4946 } else {
4947 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4948 dictnsItem = schema->targetNamespace;
4949 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4950 dictnsItem = NULL;
4951 } else {
4952 /*
4953 * Validate the item (anyURI).
4954 */
4955 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4956 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4957 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4958 }
4959 /*
4960 * Avoid dublicate namespaces.
4961 */
4962 tmp = wildc->nsSet;
4963 while (tmp != NULL) {
4964 if (dictnsItem == tmp->value)
4965 break;
4966 tmp = tmp->next;
4967 }
4968 if (tmp == NULL) {
4969 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4970 if (tmp == NULL) {
4971 xmlFree(nsItem);
4972 return (-1);
4973 }
4974 tmp->value = dictnsItem;
4975 tmp->next = NULL;
4976 if (wildc->nsSet == NULL)
4977 wildc->nsSet = tmp;
4978 else
4979 lastNs->next = tmp;
4980 lastNs = tmp;
4981 }
4982
4983 }
4984 xmlFree(nsItem);
4985 cur = end;
4986 } while (*cur != 0);
4987 }
4988 return (ret);
4989}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004990
4991static int
4992xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4993 xmlSchemaTypePtr item,
4994 xmlNodePtr node,
4995 int minOccurs,
4996 int maxOccurs) {
4997
4998 if (maxOccurs != UNBOUNDED) {
4999 /*
5000 * TODO: Maby we should better not create the particle,
5001 * if min/max is invalid, since it could confuse the build of the
5002 * content model.
5003 */
5004 /*
5005 * 3.9.6 Schema Component Constraint: Particle Correct
5006 *
5007 */
5008 if (maxOccurs < 1) {
5009 /*
5010 * 2.2 {max occurs} must be greater than or equal to 1.
5011 */
5012 xmlSchemaPCustomAttrErr(ctxt,
5013 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
5014 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
5015 "The value must be greater than or equal to 1");
5016 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
5017 } else if (minOccurs > maxOccurs) {
5018 /*
5019 * 2.1 {min occurs} must not be greater than {max occurs}.
5020 */
5021 xmlSchemaPCustomAttrErr(ctxt,
5022 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
5023 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
5024 "The value must not be greater than the value of 'maxOccurs'");
5025 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
5026 }
5027 }
5028 return (0);
5029}
5030
Daniel Veillardc0826a72004-08-10 14:17:33 +00005031/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005032 * xmlSchemaParseAny:
5033 * @ctxt: a schema validation context
5034 * @schema: the schema being built
5035 * @node: a subtree containing XML Schema informations
5036 *
5037 * parse a XML schema Any declaration
5038 * *WARNING* this interface is highly subject to change
5039 *
5040 * Returns the new type structure or NULL in case of error
5041 */
5042static xmlSchemaTypePtr
5043xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5044 xmlNodePtr node)
5045{
5046 xmlSchemaTypePtr type;
5047 xmlNodePtr child = NULL;
5048 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005049 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005050 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005051
5052 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5053 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005054 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
5055 "(nonNegativeInteger | unbounded)");
5056 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
5057 "nonNegativeInteger");
5058 if ((minOccurs == 0) && (maxOccurs == 0))
5059 return (NULL);
5060
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005061 snprintf((char *) name, 30, "#any%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005062 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005063 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005064 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005065 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005066 type->type = XML_SCHEMA_TYPE_ANY;
5067
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005068 /*
5069 * TODO: Use a particle component here.
5070 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005071 wildc = xmlSchemaAddWildcard(ctxt);
5072 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005073 * Check min/max sanity.
5074 */
5075 type->maxOccurs = maxOccurs;
5076 type->minOccurs = minOccurs;
5077 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
5078 node, type->minOccurs, type->maxOccurs);
5079 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005080 * This is not nice, since it is won't be used as a attribute wildcard,
5081 * but better than adding a field to the structure.
5082 */
5083 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005084 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005085 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005086 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005087 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5088 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005089 }
5090 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005091 xmlSchemaPErr2(ctxt, node, child,
5092 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
5093 "Sequence %s has unexpected content\n", type->name,
5094 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005095 }
5096
5097 return (type);
5098}
5099
5100/**
5101 * xmlSchemaParseNotation:
5102 * @ctxt: a schema validation context
5103 * @schema: the schema being built
5104 * @node: a subtree containing XML Schema informations
5105 *
5106 * parse a XML schema Notation declaration
5107 *
5108 * Returns the new structure or NULL in case of error
5109 */
5110static xmlSchemaNotationPtr
5111xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005112 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005113{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005114 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005115 xmlSchemaNotationPtr ret;
5116 xmlNodePtr child = NULL;
5117
5118 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5119 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005120 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005121 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005122 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
5123 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005124 return (NULL);
5125 }
5126 ret = xmlSchemaAddNotation(ctxt, schema, name);
5127 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005128 return (NULL);
5129 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005130 ret->targetNamespace = schema->targetNamespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00005131 child = node->children;
5132 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005133 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5134 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005135 }
5136 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005137 xmlSchemaPErr2(ctxt, node, child,
5138 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
5139 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005140 }
5141
5142 return (ret);
5143}
5144
5145/**
5146 * xmlSchemaParseAnyAttribute:
5147 * @ctxt: a schema validation context
5148 * @schema: the schema being built
5149 * @node: a subtree containing XML Schema informations
5150 *
5151 * parse a XML schema AnyAttrribute declaration
5152 * *WARNING* this interface is highly subject to change
5153 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005154 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00005155 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005156static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005157xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5158 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005159{
Daniel Veillard3646d642004-06-02 19:19:14 +00005160 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005161 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005162 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005163
5164 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5165 return (NULL);
5166
Daniel Veillard3646d642004-06-02 19:19:14 +00005167 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005168 if (ret == NULL) {
5169 return (NULL);
5170 }
William M. Bracke7091952004-05-11 15:09:58 +00005171 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005172 /*
5173 * Check for illegal attributes.
5174 */
5175 attr = node->properties;
5176 while (attr != NULL) {
5177 if (attr->ns == NULL) {
5178 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5179 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
5180 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
5181 xmlSchemaPIllegalAttrErr(ctxt,
5182 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5183 NULL, NULL, attr);
5184 }
5185 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5186 xmlSchemaPIllegalAttrErr(ctxt,
5187 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5188 NULL, NULL, attr);
5189 }
5190 attr = attr->next;
5191 }
5192 /* ret->id = xmlSchemaGetProp(ctxt, node, "id"); */
5193 /*
5194 * Parse the namespace list.
5195 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005196 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
5197 xmlSchemaFreeWildcard(ret);
5198 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005199 }
5200 /*
5201 * And now for the children...
5202 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005203 child = node->children;
5204 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005205 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5206 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005207 }
5208 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005209 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005210 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5211 NULL, NULL, node, child,
5212 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005213 }
5214
5215 return (ret);
5216}
5217
5218
5219/**
5220 * xmlSchemaParseAttribute:
5221 * @ctxt: a schema validation context
5222 * @schema: the schema being built
5223 * @node: a subtree containing XML Schema informations
5224 *
5225 * parse a XML schema Attrribute declaration
5226 * *WARNING* this interface is highly subject to change
5227 *
William M. Bracke7091952004-05-11 15:09:58 +00005228 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005229 */
5230static xmlSchemaAttributePtr
5231xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005232 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005233{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005234 const xmlChar *name, *attrValue;
5235 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00005236 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005237 xmlNodePtr child = NULL;
5238 xmlAttrPtr attr, nameAttr;
5239 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005240
5241 /*
5242 * Note that the w3c spec assumes the schema to be validated with schema
5243 * for schemas beforehand.
5244 *
5245 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00005246 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005247
5248 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5249 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005250 attr = xmlSchemaGetPropNode(node, "ref");
5251 nameAttr = xmlSchemaGetPropNode(node, "name");
5252
5253 if ((attr == NULL) && (nameAttr == NULL)) {
5254 /*
5255 * 3.2.3 : 3.1
5256 * One of ref or name must be present, but not both
5257 */
5258 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5259 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
5260 "One of the attributes 'ref' or 'name' must be present");
5261 return (NULL);
5262 }
5263 if ((topLevel) || (attr == NULL)) {
5264 if (nameAttr == NULL) {
5265 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
5266 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5267 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005268 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005269 }
5270 } else
5271 isRef = 1;
5272
5273 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005274 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005275 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
5276
5277 /*
5278 * Parse as attribute reference.
5279 */
5280 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
5281 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
5282 &refPrefix, &ref) != 0) {
5283 return (NULL);
5284 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005285 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005286 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005287 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005288 if (ret == NULL) {
5289 if (repName != NULL)
5290 xmlFree(repName);
5291 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005292 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005293 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5294 ret->node = node;
5295 ret->refNs = refNs;
5296 ret->refPrefix = refPrefix;
5297 ret->ref = ref;
5298 /*
5299 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
5300 */
5301 if (nameAttr != NULL)
5302 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5303 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5304 "ref", "name");
5305 /*
5306 * Check for illegal attributes.
5307 */
5308 attr = node->properties;
5309 while (attr != NULL) {
5310 if (attr->ns == NULL) {
5311 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
5312 xmlStrEqual(attr->name, BAD_CAST "form")) {
5313 /*
5314 * 3.2.3 : 3.2
5315 * If ref is present, then all of <simpleType>,
5316 * form and type must be absent.
5317 */
5318 xmlSchemaPIllegalAttrErr(ctxt,
5319 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
5320 (xmlSchemaTypePtr) ret, attr);
5321 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
5322 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
5323 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5324 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5325 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5326 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
5327 xmlSchemaPIllegalAttrErr(ctxt,
5328 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5329 &repName, (xmlSchemaTypePtr) ret, attr);
5330 }
5331 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5332 xmlSchemaPIllegalAttrErr(ctxt,
5333 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5334 &repName, (xmlSchemaTypePtr) ret, attr);
5335 }
5336 attr = attr->next;
5337 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005338 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005339 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005340
5341 /*
5342 * Parse as attribute declaration.
5343 */
5344 if (xmlSchemaPValAttrNode(ctxt,
5345 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
5346 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5347 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005348 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005349 /*
5350 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
5351 */
5352 /*
5353 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
5354 */
5355 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
5356 xmlSchemaPSimpleTypeErr(ctxt,
5357 XML_SCHEMAP_NO_XMLNS,
5358 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005359 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005360 "The value must not match 'xmlns'",
5361 NULL, NULL);
5362 if (repName != NULL)
5363 xmlFree(repName);
5364 return (NULL);
5365 }
5366 /*
5367 * Evaluate the target namespace
5368 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005369 if (topLevel) {
5370 ns = schema->targetNamespace;
5371 } else {
5372 attr = xmlSchemaGetPropNode(node, "form");
5373 if (attr != NULL) {
5374 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5375 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
5376 ns = schema->targetNamespace;
5377 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5378 xmlSchemaPSimpleTypeErr(ctxt,
5379 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5380 &repName, NULL, (xmlNodePtr) attr,
5381 NULL, "(qualified | unqualified)",
5382 attrValue, NULL, NULL, NULL);
5383 }
5384 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
5385 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005386 }
5387 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005388 if (ret == NULL) {
5389 if (repName != NULL)
5390 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00005391 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005392 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005393 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005394 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005395 if (topLevel)
5396 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
5397 /*
5398 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
5399 */
5400 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
5401 xmlSchemaPCustomErr(ctxt,
5402 XML_SCHEMAP_NO_XSI,
5403 &repName, (xmlSchemaTypePtr) ret, node,
5404 "The target namespace must not match '%s'",
5405 xmlSchemaInstanceNs);
5406 }
5407 /*
5408 * Check for illegal attributes.
5409 */
5410 attr = node->properties;
5411 while (attr != NULL) {
5412 if (attr->ns == NULL) {
5413 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5414 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5415 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5416 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5417 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
5418 if ((topLevel) ||
5419 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
5420 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
5421 xmlSchemaPIllegalAttrErr(ctxt,
5422 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5423 &repName, (xmlSchemaTypePtr) ret, attr);
5424 }
5425 }
5426 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5427 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5428 &repName, (xmlSchemaTypePtr) ret, attr);
5429 }
5430 attr = attr->next;
5431 }
5432 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
5433 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00005434 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005435 /* TODO: Check ID. */
5436 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00005437 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005438 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00005439 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005440 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
5441 if (ret->defValue != NULL)
5442 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
5443 /*
5444 * Attribute "default".
5445 */
5446 attr = xmlSchemaGetPropNode(node, "default");
5447 if (attr != NULL) {
5448 /*
5449 * 3.2.3 : 1
5450 * default and fixed must not both be present.
5451 */
5452 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
5453 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
5454 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
5455 } else
5456 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5457 }
5458 if (topLevel == 0) {
5459 /*
5460 * Attribute "use".
5461 */
5462 attr = xmlSchemaGetPropNode(node, "use");
5463 if (attr != NULL) {
5464 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5465 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
5466 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5467 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
5468 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
5469 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
5470 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
5471 else
5472 xmlSchemaPSimpleTypeErr(ctxt,
5473 XML_SCHEMAP_INVALID_ATTR_USE,
5474 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005475 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005476 attrValue, NULL, NULL, NULL);
5477 } else
5478 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5479 /*
5480 * 3.2.3 : 2
5481 * If default and use are both present, use must have
5482 * the actual value optional.
5483 */
5484 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
5485 (ret->defValue != NULL) &&
5486 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
5487 xmlSchemaPSimpleTypeErr(ctxt,
5488 XML_SCHEMAP_SRC_ATTRIBUTE_2,
5489 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005490 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005491 "The value must be 'optional' if the attribute "
5492 "'default' is present as well", NULL, NULL);
5493 }
5494 }
5495 /*
5496 * And now for the children...
5497 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005498 child = node->children;
5499 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005500 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5501 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005502 }
5503 if (isRef) {
5504 if (child != NULL) {
5505 if (IS_SCHEMA(child, "simpleType"))
5506 /*
5507 * 3.2.3 : 3.2
5508 * If ref is present, then all of <simpleType>,
5509 * form and type must be absent.
5510 */
5511 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
5512 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5513 "(annotation?)");
5514 else
5515 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5516 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5517 "(annotation?)");
5518 }
5519 } else {
5520 if (IS_SCHEMA(child, "simpleType")) {
5521 if (ret->typeName != NULL) {
5522 /*
5523 * 3.2.3 : 4
5524 * type and <simpleType> must not both be present.
5525 */
5526 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
5527 &repName, (xmlSchemaTypePtr) ret, node, child,
5528 "The attribute 'type' and the <simpleType> child "
5529 "are mutually exclusive", NULL);
5530 } else
5531 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5532 child = child->next;
5533 }
5534 if (child != NULL)
5535 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5536 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5537 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005538 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005539 /*
5540 * Cleanup.
5541 */
5542 if (repName != NULL)
5543 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005544 return (ret);
5545}
5546
5547/**
5548 * xmlSchemaParseAttributeGroup:
5549 * @ctxt: a schema validation context
5550 * @schema: the schema being built
5551 * @node: a subtree containing XML Schema informations
5552 *
5553 * parse a XML schema Attribute Group declaration
5554 * *WARNING* this interface is highly subject to change
5555 *
5556 * Returns the attribute group or NULL in case of error.
5557 */
5558static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005559xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005560 xmlSchemaPtr schema, xmlNodePtr node,
5561 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005562{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005563 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005564 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005565 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005566 const xmlChar *oldcontainer;
5567 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005568
5569 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5570 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005571
5572 nameAttr = xmlSchemaGetPropNode(node, "name");
5573 attr = xmlSchemaGetPropNode(node, "ref");
5574 if ((topLevel) || (attr == NULL)) {
5575 /*
5576 * Parse as an attribute group definition.
5577 * Note that those are allowed at top level only.
5578 */
5579 if (nameAttr == NULL) {
5580 xmlSchemaPMissingAttrErr(ctxt,
5581 XML_SCHEMAP_S4S_ATTR_MISSING,
5582 NULL, NULL, node, "name", NULL);
5583 return (NULL);
5584 }
5585 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5586 /*
5587 * The name is crucial, exit if invalid.
5588 */
5589 if (xmlSchemaPValAttrNode(ctxt,
5590 NULL, NULL, nameAttr,
5591 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5592 return (NULL);
5593 }
5594 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5595 if (ret == NULL)
5596 return (NULL);
5597 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5598 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5599 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005600 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005601 } else {
5602 char buf[50];
5603 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5604
5605 /*
5606 * Parse as an attribute group definition reference.
5607 */
5608 if (attr == NULL) {
5609 xmlSchemaPMissingAttrErr(ctxt,
5610 XML_SCHEMAP_S4S_ATTR_MISSING,
5611 NULL, NULL, node, "ref", NULL);
5612 }
5613 xmlSchemaPValAttrNodeQName(ctxt, schema,
5614 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5615
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005616 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005617 name = (const xmlChar *) buf;
5618 if (name == NULL) {
5619 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5620 "attribute group definition reference", node);
5621 return (NULL);
5622 }
5623 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5624 if (ret == NULL)
5625 return (NULL);
5626 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5627 ret->ref = ref;
5628 ret->refNs = refNs;
5629 /* TODO: Is @refPrefix currently used? */
5630 ret->refPrefix = refPrefix;
5631 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005632 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005633 /*
5634 * Check for illegal attributes.
5635 */
5636 attr = node->properties;
5637 while (attr != NULL) {
5638 if (attr->ns == NULL) {
5639 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5640 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5641 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5642 {
5643 xmlSchemaPIllegalAttrErr(ctxt,
5644 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5645 NULL, NULL, attr);
5646 }
5647 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5648 xmlSchemaPIllegalAttrErr(ctxt,
5649 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5650 NULL, NULL, attr);
5651 }
5652 attr = attr->next;
5653 }
5654 /* TODO: Validate "id" ? */
5655 /*
5656 * And now for the children...
5657 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005658 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005659 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005660 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005661 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005662 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5663 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005664 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005665 if (topLevel) {
5666 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5667 if (IS_SCHEMA(child, "anyAttribute")) {
5668 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5669 child = child->next;
5670 }
5671 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005672 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005673 xmlSchemaPContentErr(ctxt,
5674 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5675 NULL, NULL, node, child, NULL,
5676 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005677 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005678 ctxt->container = oldcontainer;
5679 return (ret);
5680}
5681
5682/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005683 * xmlSchemaPValAttrFormDefault:
5684 * @value: the value
5685 * @flags: the flags to be modified
5686 * @flagQualified: the specific flag for "qualified"
5687 *
5688 * Returns 0 if the value is valid, 1 otherwise.
5689 */
5690static int
5691xmlSchemaPValAttrFormDefault(const xmlChar *value,
5692 int *flags,
5693 int flagQualified)
5694{
5695 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5696 if ((*flags & flagQualified) == 0)
5697 *flags |= flagQualified;
5698 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5699 return (1);
5700
5701 return (0);
5702}
5703
5704/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005705 * xmlSchemaPValAttrBlockFinal:
5706 * @value: the value
5707 * @flags: the flags to be modified
5708 * @flagAll: the specific flag for "#all"
5709 * @flagExtension: the specific flag for "extension"
5710 * @flagRestriction: the specific flag for "restriction"
5711 * @flagSubstitution: the specific flag for "substitution"
5712 * @flagList: the specific flag for "list"
5713 * @flagUnion: the specific flag for "union"
5714 *
5715 * Validates the value of the attribute "final" and "block". The value
5716 * is converted into the specified flag values and returned in @flags.
5717 *
5718 * Returns 0 if the value is valid, 1 otherwise.
5719 */
5720
5721static int
5722xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5723 int *flags,
5724 int flagAll,
5725 int flagExtension,
5726 int flagRestriction,
5727 int flagSubstitution,
5728 int flagList,
5729 int flagUnion)
5730{
5731 int ret = 0;
5732
5733 /*
5734 * TODO: This does not check for dublicate entries.
5735 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005736 if (value == NULL)
5737 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005738 if (xmlStrEqual(value, BAD_CAST "#all")) {
5739 if (flagAll != -1)
5740 *flags |= flagAll;
5741 else {
5742 if (flagExtension != -1)
5743 *flags |= flagExtension;
5744 if (flagRestriction != -1)
5745 *flags |= flagRestriction;
5746 if (flagSubstitution != -1)
5747 *flags |= flagSubstitution;
5748 if (flagList != -1)
5749 *flags |= flagList;
5750 if (flagUnion != -1)
5751 *flags |= flagUnion;
5752 }
5753 } else {
5754 const xmlChar *end, *cur = value;
5755 xmlChar *item;
5756
5757 do {
5758 while (IS_BLANK_CH(*cur))
5759 cur++;
5760 end = cur;
5761 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5762 end++;
5763 if (end == cur)
5764 break;
5765 item = xmlStrndup(cur, end - cur);
5766 if (xmlStrEqual(item, BAD_CAST "extension")) {
5767 if (flagExtension != -1) {
5768 if ((*flags & flagExtension) == 0)
5769 *flags |= flagExtension;
5770 } else
5771 ret = 1;
5772 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5773 if (flagRestriction != -1) {
5774 if ((*flags & flagRestriction) == 0)
5775 *flags |= flagRestriction;
5776 } else
5777 ret = 1;
5778 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5779 if (flagSubstitution != -1) {
5780 if ((*flags & flagSubstitution) == 0)
5781 *flags |= flagSubstitution;
5782 } else
5783 ret = 1;
5784 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5785 if (flagList != -1) {
5786 if ((*flags & flagList) == 0)
5787 *flags |= flagList;
5788 } else
5789 ret = 1;
5790 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5791 if (flagUnion != -1) {
5792 if ((*flags & flagUnion) == 0)
5793 *flags |= flagUnion;
5794 } else
5795 ret = 1;
5796 } else
5797 ret = 1;
5798 if (item != NULL)
5799 xmlFree(item);
5800 cur = end;
5801 } while ((ret == 0) && (*cur != 0));
5802 }
5803
5804 return (ret);
5805}
5806
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005807#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005808static int
5809xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005810 xmlSchemaIDCPtr idc,
5811 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005812 xmlAttrPtr attr,
5813 int isField)
5814{
5815 xmlNodePtr node;
5816
5817 /*
5818 * c-selector-xpath:
5819 * Schema Component Constraint: Selector Value OK
5820 *
5821 * TODO: 1 The {selector} must be a valid XPath expression, as defined
5822 * in [XPath].
5823 */
5824 if (selector == NULL) {
5825 xmlSchemaPErr(ctxt, idc->node,
5826 XML_SCHEMAP_INTERNAL,
5827 "Internal error: xmlSchemaCheckCSelectorXPath, "
5828 "the selector is not specified.\n", NULL, NULL);
5829 return (-1);
5830 }
5831 if (attr == NULL)
5832 node = idc->node;
5833 else
5834 node = (xmlNodePtr) attr;
5835 if (selector->xpath == NULL) {
5836 xmlSchemaPCustomErr(ctxt,
5837 /* TODO: Adjust error code. */
5838 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5839 NULL, NULL, node,
5840 "The XPath expression of the selector is not valid", NULL);
5841 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
5842 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00005843 const xmlChar **nsArray = NULL;
5844 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005845 /*
5846 * Compile the XPath expression.
5847 */
5848 /*
5849 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00005850 * TODO: Call xmlPatterncompile with different options for selector/
5851 * field.
5852 */
5853 nsList = xmlGetNsList(attr->doc, attr->parent);
5854 /*
5855 * Build an array of prefixes and namespaces.
5856 */
5857 if (nsList != NULL) {
5858 int i, count = 0;
5859 xmlNsPtr ns;
5860
5861 for (i = 0; nsList[i] != NULL; i++)
5862 count++;
5863
5864 nsArray = (const xmlChar **) xmlMalloc(
5865 (count * 2 + 1) * sizeof(const xmlChar *));
5866 if (nsArray == NULL) {
5867 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
5868 NULL);
5869 return (-1);
5870 }
5871 for (i = 0; i < count; i++) {
5872 ns = nsList[i];
5873 nsArray[2 * i] = nsList[i]->href;
5874 nsArray[2 * i + 1] = nsList[i]->prefix;
5875 }
5876 nsArray[count * 2] = NULL;
5877 xmlFree(nsList);
5878 }
5879 if (isField)
5880 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
5881 NULL, 0, nsArray);
5882 else
5883 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
5884 NULL, 0, nsArray);
5885 if (nsArray != NULL)
5886 xmlFree((xmlChar **) nsArray);
5887
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005888#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00005889 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005890 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005891 /* TODO: Adjust error code? */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005892 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5893 NULL, NULL, node,
5894 "The XPath expression '%s' could not be "
5895 "compiled", selector->xpath);
5896 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
5897 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00005898#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005899 }
5900 return (0);
5901}
5902
5903/**
5904 * xmlSchemaAssignAnnotation:
5905 * @item: the schema component
5906 * @annot: the annotation
5907 *
5908 * Adds the annotation to the given schema component.
5909 *
5910 * Returns the given annotaion.
5911 */
5912static xmlSchemaAnnotPtr
5913xmlSchemaAssignAnnotation(xmlSchemaBasicItemPtr item,
5914 xmlSchemaAnnotPtr annot)
5915{
5916 xmlSchemaAnnotPtr cur = item->annot;
5917
5918 if (item->annot == NULL) {
5919 item->annot = annot;
5920 return (annot);
5921 }
5922 cur = item->annot;
5923 if (cur->next != NULL) {
5924 cur = cur->next;
5925 }
5926 cur->next = annot;
5927 return (annot);
5928}
5929
5930/**
5931 * xmlSchemaParseIDCSelectorAndField:
5932 * @ctxt: a schema validation context
5933 * @schema: the schema being built
5934 * @node: a subtree containing XML Schema informations
5935 *
5936 * Parses a XML Schema identity-contraint definition's
5937 * <selector> and <field> elements.
5938 *
5939 * Returns the parsed identity-constraint definition.
5940 */
5941static xmlSchemaIDCSelectPtr
5942xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
5943 xmlSchemaPtr schema,
5944 xmlSchemaIDCPtr idc,
5945 xmlNodePtr node,
5946 int isField)
5947{
5948 xmlSchemaIDCSelectPtr item;
5949 xmlNodePtr child = NULL;
5950 xmlAttrPtr attr;
5951
5952 /*
5953 * Check for illegal attributes.
5954 */
5955 attr = node->properties;
5956 while (attr != NULL) {
5957 if (attr->ns == NULL) {
5958 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5959 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
5960 xmlSchemaPIllegalAttrErr(ctxt,
5961 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5962 NULL, NULL, attr);
5963 }
5964 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5965 xmlSchemaPIllegalAttrErr(ctxt,
5966 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5967 NULL, NULL, attr);
5968 }
5969 attr = attr->next;
5970 }
5971 /*
5972 * Create the item.
5973 */
5974 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
5975 if (item == NULL) {
5976 xmlSchemaPErrMemory(ctxt,
5977 "allocating a 'selector' of an identity-constraint definition",
5978 NULL);
5979 return (NULL);
5980 }
5981 memset(item, 0, sizeof(xmlSchemaIDCSelect));
5982 /*
5983 * Attribute "xpath" (mandatory).
5984 */
5985 attr = xmlSchemaGetPropNode(node, "xpath");
5986 if (attr == NULL) {
5987 xmlSchemaPMissingAttrErr(ctxt,
5988 XML_SCHEMAP_S4S_ATTR_MISSING,
5989 NULL, NULL, node,
5990 "name", NULL);
5991 } else {
5992 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5993 /*
5994 * URGENT TODO: "field"s have an other syntax than "selector"s.
5995 */
5996
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00005997 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
5998 isField) == -1) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005999 xmlSchemaPErr(ctxt,
6000 (xmlNodePtr) attr,
6001 XML_SCHEMAP_INTERNAL,
6002 "Internal error: xmlSchemaParseIDCSelectorAndField, "
6003 "validating the XPath expression of a IDC selector.\n",
6004 NULL, NULL);
6005 }
6006
6007 }
6008 /*
6009 * And now for the children...
6010 */
6011 child = node->children;
6012 if (IS_SCHEMA(child, "annotation")) {
6013 /*
6014 * Add the annotation to the parent IDC.
6015 */
6016 xmlSchemaAssignAnnotation((xmlSchemaBasicItemPtr) idc,
6017 xmlSchemaParseAnnotation(ctxt, schema, child));
6018 child = child->next;
6019 }
6020 if (child != NULL) {
6021 xmlSchemaPContentErr(ctxt,
6022 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6023 NULL, NULL, node, child,
6024 NULL, "(annotation?)");
6025 }
6026
6027 return (item);
6028}
6029
6030/**
6031 * xmlSchemaParseIDC:
6032 * @ctxt: a schema validation context
6033 * @schema: the schema being built
6034 * @node: a subtree containing XML Schema informations
6035 *
6036 * Parses a XML Schema identity-contraint definition.
6037 *
6038 * Returns the parsed identity-constraint definition.
6039 */
6040static xmlSchemaIDCPtr
6041xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
6042 xmlSchemaPtr schema,
6043 xmlNodePtr node,
6044 xmlSchemaTypeType idcCategory,
6045 const xmlChar *targetNamespace)
6046{
6047 xmlSchemaIDCPtr item = NULL;
6048 xmlNodePtr child = NULL;
6049 xmlAttrPtr attr;
6050 const xmlChar *name = NULL;
6051 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
6052 int resAdd;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006053
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006054 /*
6055 * Check for illegal attributes.
6056 */
6057 attr = node->properties;
6058 while (attr != NULL) {
6059 if (attr->ns == NULL) {
6060 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6061 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6062 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
6063 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
6064 xmlSchemaPIllegalAttrErr(ctxt,
6065 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6066 NULL, NULL, attr);
6067 }
6068 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6069 xmlSchemaPIllegalAttrErr(ctxt,
6070 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6071 NULL, NULL, attr);
6072 }
6073 attr = attr->next;
6074 }
6075 /*
6076 * Attribute "name" (mandatory).
6077 */
6078 attr = xmlSchemaGetPropNode(node, "name");
6079 if (attr == NULL) {
6080 xmlSchemaPMissingAttrErr(ctxt,
6081 XML_SCHEMAP_S4S_ATTR_MISSING,
6082 NULL, NULL, node,
6083 "name", NULL);
6084 return (NULL);
6085 } else if (xmlSchemaPValAttrNode(ctxt,
6086 NULL, NULL, attr,
6087 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6088 return (NULL);
6089 }
6090 /*
6091 * Create the component.
6092 */
6093 if (schema->idcDef == NULL)
6094 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
6095 if (schema->idcDef == NULL)
6096 return (NULL);
6097
6098 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
6099 if (item == NULL) {
6100 xmlSchemaPErrMemory(ctxt,
6101 "allocating an identity-constraint definition", NULL);
6102 return (NULL);
6103 }
6104 /*
6105 * Add the IDC to the list of IDCs on the schema component.
6106 */
6107 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
6108 if (resAdd != 0) {
6109 xmlSchemaPCustomErrExt(ctxt,
6110 XML_SCHEMAP_REDEFINED_TYPE,
6111 NULL, NULL, node,
6112 "An identity-constraint definition with the name '%s' "
6113 "and targetNamespace '%s' does already exist",
6114 name, targetNamespace, NULL);
6115 xmlFree(item);
6116 return (NULL);
6117 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006118 memset(item, 0, sizeof(xmlSchemaIDC));
6119 item->name = name;
6120 item->type = idcCategory;
6121 item->node = node;
6122 /*
6123 * The target namespace of the parent element declaration.
6124 */
6125 item->targetNamespace = targetNamespace;
6126 /* TODO: Handle attribute "id". */
6127 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
6128 /*
6129 * Attribute "refer" (mandatory).
6130 */
6131 attr = xmlSchemaGetPropNode(node, "refer");
6132 if (attr == NULL) {
6133 xmlSchemaPMissingAttrErr(ctxt,
6134 XML_SCHEMAP_S4S_ATTR_MISSING,
6135 NULL, NULL, node,
6136 "refer", NULL);
6137 } else {
6138 /*
6139 * Create a reference item.
6140 */
6141 item->ref = (xmlSchemaItemQNRefPtr) xmlMalloc(
6142 sizeof(xmlSchemaItemQNRef));
6143 if (item->ref == NULL) {
6144 xmlSchemaPErrMemory(ctxt,
6145 "allocating a QName reference item", NULL);
6146 return (NULL);
6147 }
6148 memset(item->ref, 0, sizeof(xmlSchemaItemQNRef));
6149 xmlSchemaPValAttrNodeQName(ctxt, schema,
6150 NULL, NULL, attr,
6151 &(item->ref->targetNamespace), 0,
6152 &(item->ref->name));
6153 }
6154 }
6155 /*
6156 * And now for the children...
6157 */
6158 child = node->children;
6159 if (IS_SCHEMA(child, "annotation")) {
6160 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6161 child = child->next;
6162 }
6163 /*
6164 * Child element <selector>.
6165 */
6166 if (IS_SCHEMA(child, "selector")) {
6167 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6168 item, child, 0);
6169 child = child->next;
6170 /*
6171 * Child elements <field>.
6172 */
6173 if (IS_SCHEMA(child, "field")) {
6174 do {
6175 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6176 item, child, 1);
6177 if (field != NULL) {
6178 field->index = item->nbFields;
6179 item->nbFields++;
6180 if (lastField != NULL)
6181 lastField->next = field;
6182 else
6183 item->fields = field;
6184 lastField = field;
6185 }
6186 child = child->next;
6187 } while (IS_SCHEMA(child, "field"));
6188 } else {
6189 xmlSchemaPContentErr(ctxt,
6190 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6191 NULL, NULL, node, child,
6192 NULL, "(annotation?, (selector, field+))");
6193 }
6194 }
6195 if (child != NULL) {
6196 xmlSchemaPContentErr(ctxt,
6197 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6198 NULL, NULL, node, child,
6199 NULL, "(annotation?, (selector, field+))");
6200 }
6201
6202 return (item);
6203}
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006204#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006205
Daniel Veillardc0826a72004-08-10 14:17:33 +00006206/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006207 * xmlSchemaParseElement:
6208 * @ctxt: a schema validation context
6209 * @schema: the schema being built
6210 * @node: a subtree containing XML Schema informations
6211 *
6212 * parse a XML schema Element declaration
6213 * *WARNING* this interface is highly subject to change
6214 *
William M. Bracke7091952004-05-11 15:09:58 +00006215 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006216 */
6217static xmlSchemaElementPtr
6218xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006219 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006220{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006221 const xmlChar *name = NULL;
6222 const xmlChar *attrValue;
6223 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006224 xmlSchemaElementPtr ret;
6225 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006226 const xmlChar *oldcontainer;
6227 xmlAttrPtr attr, nameAttr;
6228 int minOccurs, maxOccurs;
6229 int isRef = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006230#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006231 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006232#endif
William M. Bracke7091952004-05-11 15:09:58 +00006233
6234 /* 3.3.3 Constraints on XML Representations of Element Declarations */
6235 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006236
Daniel Veillard4255d502002-04-16 15:50:10 +00006237 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6238 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006239
Daniel Veillardc0826a72004-08-10 14:17:33 +00006240 oldcontainer = ctxt->container;
6241
6242 nameAttr = xmlSchemaGetPropNode(node, "name");
6243 attr = xmlSchemaGetPropNode(node, "ref");
6244 if ((topLevel) || (attr == NULL)) {
6245 if (nameAttr == NULL) {
6246 xmlSchemaPMissingAttrErr(ctxt,
6247 XML_SCHEMAP_S4S_ATTR_MISSING,
6248 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
6249 "name", NULL);
6250 return (NULL);
6251 }
6252 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
6253 } else {
6254 isRef = 1;
6255
6256 }
6257 /*
6258 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
6259 * to no component at all
6260 * TODO: It might be better to validate the element, even if it won't be
6261 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006262 */
6263 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6264 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006265 if ((minOccurs == 0) && (maxOccurs == 0))
6266 return (NULL);
6267 /*
6268 * If we get a "ref" attribute on a local <element> we will assume it's
6269 * a reference - even if there's a "name" attribute; this seems to be more
6270 * robust.
6271 */
6272 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006273 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006274 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6275
6276 /*
6277 * Parse as a particle.
6278 */
6279 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006280 (xmlChar **) &xmlSchemaElemDesElemRef,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006281 NULL, attr, &refNs, &refPrefix, &ref);
6282
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006283 snprintf(buf, 49, "#eRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006284 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006285 if (ret == NULL) {
6286 if (repName != NULL)
6287 xmlFree(repName);
6288 return (NULL);
6289 }
6290 ret->type = XML_SCHEMA_TYPE_ELEMENT;
6291 ret->node = node;
6292 ret->ref = ref;
6293 ret->refNs = refNs;
6294 ret->refPrefix = refPrefix;
6295 ret->flags |= XML_SCHEMAS_ELEM_REF;
6296 /*
6297 * Check for illegal attributes.
6298 */
6299 /*
6300 * 3.3.3 : 2.1
6301 * One of ref or name must be present, but not both
6302 */
6303 if (nameAttr != NULL) {
6304 xmlSchemaPMutualExclAttrErr(ctxt,
6305 XML_SCHEMAP_SRC_ELEMENT_2_1,
6306 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6307 "ref", "name");
6308 }
6309 /* 3.3.3 : 2.2 */
6310 attr = node->properties;
6311 while (attr != NULL) {
6312 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006313 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
6314 xmlStrEqual(attr->name, BAD_CAST "name") ||
6315 xmlStrEqual(attr->name, BAD_CAST "id") ||
6316 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
6317 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
6318 {
6319 attr = attr->next;
6320 continue;
6321 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006322 xmlSchemaPCustomAttrErr(ctxt,
6323 XML_SCHEMAP_SRC_ELEMENT_2_2,
6324 &repName, (xmlSchemaTypePtr) ret, attr,
6325 "Only the attributes 'minOccurs', 'maxOccurs' and "
6326 "'id' are allowed in addition to 'ref'");
6327 break;
6328 }
6329 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6330 xmlSchemaPIllegalAttrErr(ctxt,
6331 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6332 &repName, (xmlSchemaTypePtr) ret, attr);
6333 }
6334 attr = attr->next;
6335 }
6336 } else {
6337 const xmlChar *ns = NULL, *fixed;
6338
6339 /*
6340 * Parse as an element declaration.
6341 */
6342 if (xmlSchemaPValAttrNode(ctxt,
6343 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
6344 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
6345 return (NULL);
6346 /*
6347 * Evaluate the target namespace.
6348 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006349 if (topLevel) {
6350 ns = schema->targetNamespace;
6351 } else {
6352 attr = xmlSchemaGetPropNode(node, "form");
6353 if (attr != NULL) {
6354 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6355 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00006356 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006357 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6358 xmlSchemaPSimpleTypeErr(ctxt,
6359 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6360 &repName, NULL, (xmlNodePtr) attr,
6361 NULL, "(qualified | unqualified)",
6362 attrValue, NULL, NULL, NULL);
6363 }
6364 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6365 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00006366 }
6367 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006368 if (ret == NULL) {
6369 if (repName != NULL)
6370 xmlFree(repName);
6371 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006372 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006373 ret->type = XML_SCHEMA_TYPE_ELEMENT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006374 ret->node = node;
6375 ret->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006376 /*
6377 * Check for illegal attributes.
6378 */
William M. Bracke7091952004-05-11 15:09:58 +00006379 attr = node->properties;
6380 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006381 if (attr->ns == NULL) {
6382 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6383 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6384 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6385 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6386 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6387 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006388 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
6389 {
6390 if (topLevel == 0) {
6391 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006392 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006393 (!xmlStrEqual(attr->name, BAD_CAST "form")))
6394 {
6395 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
6396 /*
6397 * 3.3.6 : 3 If there is a non-·absent· {substitution
6398 * group affiliation}, then {scope} must be global.
6399 * TODO: This one is redundant, since the S4S does
6400 * prohibit this attribute on local declarations already;
6401 * so why an explicit error code? Weird spec.
6402 * TODO: Move this to the proper constraint layer.
6403 * TODO: Or better wait for spec 1.1 to come.
6404 */
6405 xmlSchemaPIllegalAttrErr(ctxt,
6406 XML_SCHEMAP_E_PROPS_CORRECT_3,
6407 &repName, (xmlSchemaTypePtr) ret, attr);
6408 } else {
6409 xmlSchemaPIllegalAttrErr(ctxt,
6410 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6411 &repName, (xmlSchemaTypePtr) ret, attr);
6412 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006413 }
6414 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
6415 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
6416 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
6417
6418 xmlSchemaPIllegalAttrErr(ctxt,
6419 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6420 &repName, (xmlSchemaTypePtr) ret, attr);
6421 }
6422 }
6423 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6424
6425 xmlSchemaPIllegalAttrErr(ctxt,
6426 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6427 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00006428 }
6429 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006430 }
William M. Bracke7091952004-05-11 15:09:58 +00006431 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006432 * Extract/validate attributes.
6433 */
6434 if (topLevel) {
6435 /*
6436 * Process top attributes of global element declarations here.
6437 */
6438 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
6439 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
6440 xmlSchemaPValAttrQName(ctxt, schema, &repName,
6441 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
6442 &(ret->substGroupNs), NULL, &(ret->substGroup));
6443 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6444 node, "abstract", 0))
6445 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
6446 /*
6447 * Attribute "final".
6448 */
6449 attr = xmlSchemaGetPropNode(node, "final");
6450 if (attr == NULL) {
6451 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
6452 } else {
6453 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6454 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6455 -1,
6456 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
6457 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
6458 xmlSchemaPSimpleTypeErr(ctxt,
6459 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6460 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006461 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006462 attrValue, NULL, NULL, NULL);
6463 }
6464 }
6465 }
6466 /*
6467 * Attribute "block".
6468 */
6469 attr = xmlSchemaGetPropNode(node, "block");
6470 if (attr == NULL) {
6471 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
6472 } else {
6473 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6474 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6475 -1,
6476 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
6477 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
6478 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
6479 xmlSchemaPSimpleTypeErr(ctxt,
6480 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6481 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006482 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00006483 "restriction | substitution))", attrValue,
6484 NULL, NULL, NULL);
6485 }
6486 }
6487 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6488 node, "nillable", 0))
6489 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006490
Daniel Veillardc0826a72004-08-10 14:17:33 +00006491 xmlSchemaPValAttrQName(ctxt, schema,
6492 &repName, (xmlSchemaTypePtr) ret, node,
6493 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00006494
Daniel Veillardc0826a72004-08-10 14:17:33 +00006495 ret->value = xmlSchemaGetProp(ctxt, node, "default");
6496 attr = xmlSchemaGetPropNode(node, "fixed");
6497 if (attr != NULL) {
6498 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6499 if (ret->value != NULL) {
6500 /*
6501 * 3.3.3 : 1
6502 * default and fixed must not both be present.
6503 */
6504 xmlSchemaPMutualExclAttrErr(ctxt,
6505 XML_SCHEMAP_SRC_ELEMENT_1,
6506 &repName, (xmlSchemaTypePtr) ret, attr,
6507 "default", "fixed");
6508 } else {
6509 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
6510 ret->value = fixed;
6511 }
6512 }
6513 }
6514 /*
6515 * Extract/validate common attributes.
6516 */
6517 /* TODO: Check ID: */
6518 ret->id = xmlSchemaGetProp(ctxt, node, "id");
6519 ret->minOccurs = minOccurs;
6520 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006521 if (topLevel != 1)
6522 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
6523 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006524 /*
6525 * And now for the children...
6526 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006527 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006528 child = node->children;
6529 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006530 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6531 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006532 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006533 if (isRef) {
6534 if (child != NULL) {
6535 xmlSchemaPContentErr(ctxt,
6536 XML_SCHEMAP_SRC_ELEMENT_2_2,
6537 &repName, (xmlSchemaTypePtr) ret, node, child,
6538 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00006539 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006540 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006541 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006542 /*
6543 * 3.3.3 : 3
6544 * "type" and either <simpleType> or <complexType> are mutually
6545 * exclusive
6546 */
William M. Bracke7091952004-05-11 15:09:58 +00006547 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006548 xmlSchemaPContentErr(ctxt,
6549 XML_SCHEMAP_SRC_ELEMENT_3,
6550 &repName, (xmlSchemaTypePtr) ret, node, child,
6551 "The attribute 'type' and the <complexType> child are "
6552 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006553 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006554 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006555 child = child->next;
6556 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006557 /*
6558 * 3.3.3 : 3
6559 * "type" and either <simpleType> or <complexType> are
6560 * mutually exclusive
6561 */
William M. Bracke7091952004-05-11 15:09:58 +00006562 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006563 xmlSchemaPContentErr(ctxt,
6564 XML_SCHEMAP_SRC_ELEMENT_3,
6565 &repName, (xmlSchemaTypePtr) ret, node, child,
6566 "The attribute 'type' and the <simpleType> child are "
6567 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006568 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006569 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006570 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006571 }
William M. Bracke7091952004-05-11 15:09:58 +00006572 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006573 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006574#ifdef IDC_ENABLED
6575 if (IS_SCHEMA(child, "unique")) {
6576 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6577 XML_SCHEMA_TYPE_IDC_UNIQUE, ret->targetNamespace);
6578 } else if (IS_SCHEMA(child, "key")) {
6579 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6580 XML_SCHEMA_TYPE_IDC_KEY, ret->targetNamespace);
6581 } else if (IS_SCHEMA(child, "keyref")) {
6582 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6583 XML_SCHEMA_TYPE_IDC_KEYREF, ret->targetNamespace);
6584 }
6585 if (lastIDC != NULL)
6586 lastIDC->next = curIDC;
6587 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006588 ret->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006589 lastIDC = curIDC;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006590#else
6591 TODO
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006592#endif
6593 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00006594 }
6595 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006596 xmlSchemaPContentErr(ctxt,
6597 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6598 &repName, (xmlSchemaTypePtr) ret, node, child,
6599 NULL, "(annotation?, ((simpleType | complexType)?, "
6600 "(unique | key | keyref)*))");
6601 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006602
Daniel Veillardc0826a72004-08-10 14:17:33 +00006603 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006604 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006605 /*
6606 * Cleanup.
6607 */
6608 if (repName != NULL)
6609 xmlFree(repName);
6610 /*
6611 * NOTE: Element Declaration Representation OK 4. will be checked at a
6612 * different layer.
6613 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006614 return (ret);
6615}
6616
6617/**
6618 * xmlSchemaParseUnion:
6619 * @ctxt: a schema validation context
6620 * @schema: the schema being built
6621 * @node: a subtree containing XML Schema informations
6622 *
6623 * parse a XML schema Union definition
6624 * *WARNING* this interface is highly subject to change
6625 *
William M. Bracke7091952004-05-11 15:09:58 +00006626 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006627 * 1 in case of success.
6628 */
6629static xmlSchemaTypePtr
6630xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006631 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006632{
6633 xmlSchemaTypePtr type, subtype, last = NULL;
6634 xmlNodePtr child = NULL;
6635 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006636 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006637
6638 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6639 return (NULL);
6640
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006641 snprintf((char *) name, 30, "#union%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006642 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006643 if (type == NULL)
6644 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006645 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00006646 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00006647 /*
6648 * Check for illegal attributes.
6649 */
6650 attr = node->properties;
6651 while (attr != NULL) {
6652 if (attr->ns == NULL) {
6653 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6654 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
6655 xmlSchemaPIllegalAttrErr(ctxt,
6656 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6657 NULL, type, attr);
6658 }
6659 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6660 xmlSchemaPIllegalAttrErr(ctxt,
6661 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6662 NULL, type, attr);
6663 }
6664 attr = attr->next;
6665 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006666 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006667 /*
6668 * Attribute "memberTypes". This is a list of QNames.
6669 * TODO: Validate the QNames.
6670 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00006671 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00006672 /*
6673 * And now for the children...
6674 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006675 child = node->children;
6676 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006677 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6678 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006679 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006680 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006681 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00006682 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006683 if (subtype != NULL) {
6684 if (last == NULL) {
6685 type->subtypes = subtype;
6686 last = subtype;
6687 } else {
6688 last->next = subtype;
6689 last = subtype;
6690 }
6691 last->next = NULL;
6692 }
6693 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006694 }
6695 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006696 /* TODO: Think about the error code. */
6697 xmlSchemaPContentErr(ctxt,
6698 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
6699 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006700 }
6701 return (type);
6702}
6703
6704/**
6705 * xmlSchemaParseList:
6706 * @ctxt: a schema validation context
6707 * @schema: the schema being built
6708 * @node: a subtree containing XML Schema informations
6709 *
6710 * parse a XML schema List definition
6711 * *WARNING* this interface is highly subject to change
6712 *
William M. Bracke7091952004-05-11 15:09:58 +00006713 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006714 * 1 in case of success.
6715 */
6716static xmlSchemaTypePtr
6717xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006718 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006719{
6720 xmlSchemaTypePtr type, subtype;
6721 xmlNodePtr child = NULL;
6722 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006723 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006724
6725 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6726 return (NULL);
6727
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006728 snprintf((char *) name, 30, "#list%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006729 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006730 if (type == NULL)
6731 return (NULL);
6732 type->node = node;
6733 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006734 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006735 /*
6736 * Check for illegal attributes.
6737 */
6738 attr = node->properties;
6739 while (attr != NULL) {
6740 if (attr->ns == NULL) {
6741 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6742 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
6743 xmlSchemaPIllegalAttrErr(ctxt,
6744 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6745 NULL, type, attr);
6746 }
6747 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6748 xmlSchemaPIllegalAttrErr(ctxt,
6749 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6750 NULL, type, attr);
6751 }
6752 attr = attr->next;
6753 }
6754 /*
6755 * Attribute "itemType".
6756 */
6757 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
6758 node, "itemType", &(type->baseNs), NULL, &(type->base));
6759 /*
6760 * And now for the children...
6761 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006762 child = node->children;
6763 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006764 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6765 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00006766 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006767 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006768 if (IS_SCHEMA(child, "simpleType")) {
6769 if (type->base != NULL) {
6770 xmlSchemaPCustomErr(ctxt,
6771 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
6772 NULL, type, node,
6773 "The attribute 'itemType' and the <simpleType> child "
6774 "are mutually exclusive", NULL);
6775 } else {
6776 subtype = (xmlSchemaTypePtr)
6777 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6778 type->subtypes = subtype;
6779 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006780 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006781 }
6782 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006783 /* TODO: Think about the error code. */
6784 xmlSchemaPContentErr(ctxt,
6785 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
6786 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006787 }
6788 return (type);
6789}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006790
Daniel Veillard4255d502002-04-16 15:50:10 +00006791/**
6792 * xmlSchemaParseSimpleType:
6793 * @ctxt: a schema validation context
6794 * @schema: the schema being built
6795 * @node: a subtree containing XML Schema informations
6796 *
6797 * parse a XML schema Simple Type definition
6798 * *WARNING* this interface is highly subject to change
6799 *
William M. Bracke7091952004-05-11 15:09:58 +00006800 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00006801 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00006802 */
6803static xmlSchemaTypePtr
6804xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006805 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006806{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006807 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00006808 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006809 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006810 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006811 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006812
6813 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6814 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006815
Daniel Veillardc0826a72004-08-10 14:17:33 +00006816 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006817 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006818 if (attr == NULL) {
6819 xmlSchemaPMissingAttrErr(ctxt,
6820 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006821 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006822 "name", NULL);
6823 return (NULL);
6824 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006825 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006826 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00006827 return (NULL);
6828 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006829 }
6830
6831 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006832 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006833
Daniel Veillard01fa6152004-06-29 17:04:39 +00006834 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006835 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00006836 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006837 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006838 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006839 if (type == NULL)
6840 return (NULL);
6841 type->node = node;
6842 type->type = XML_SCHEMA_TYPE_SIMPLE;
6843 /*
6844 * Check for illegal attributes.
6845 */
6846 attr = node->properties;
6847 while (attr != NULL) {
6848 if (attr->ns == NULL) {
6849 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
6850 xmlSchemaPIllegalAttrErr(ctxt,
6851 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006852 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00006853 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006854 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6855 xmlSchemaPIllegalAttrErr(ctxt,
6856 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006857 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006858 }
6859 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006860 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006861 } else {
6862 /*
6863 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006864 *
6865 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006866 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006867 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006868 if (type == NULL)
6869 return (NULL);
6870 type->node = node;
6871 type->type = XML_SCHEMA_TYPE_SIMPLE;
6872 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
6873 /*
6874 * Check for illegal attributes.
6875 */
6876 attr = node->properties;
6877 while (attr != NULL) {
6878 if (attr->ns == NULL) {
6879 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6880 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006881 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006882 xmlSchemaPIllegalAttrErr(ctxt,
6883 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006884 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006885 }
6886 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6887 xmlSchemaPIllegalAttrErr(ctxt,
6888 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006889 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006890 }
6891 attr = attr->next;
6892 }
6893 /*
6894 * Attribute "final".
6895 */
6896 attr = xmlSchemaGetPropNode(node, "final");
6897 if (attr == NULL) {
6898 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
6899 } else {
6900 attrValue = xmlSchemaGetProp(ctxt, node, "final");
6901 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
6902 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
6903 XML_SCHEMAS_TYPE_FINAL_LIST,
6904 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
6905
6906 xmlSchemaPSimpleTypeErr(ctxt,
6907 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006908 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006909 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006910 attrValue, NULL, NULL, NULL);
6911 }
6912 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006913 }
6914 type->targetNamespace = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006915 /* TODO: Check id. */
6916 type->id = xmlSchemaGetProp(ctxt, node, "id");
6917 /*
6918 * And now for the children...
6919 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006920 oldCtxtType = ctxt->ctxtType;
6921 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006922 ctxt->ctxtType = type;
6923 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00006924 child = node->children;
6925 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006926 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6927 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006928 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006929 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006930 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006931 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006932 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006933 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006934 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006935 subtype = (xmlSchemaTypePtr)
6936 xmlSchemaParseList(ctxt, schema, child);
6937 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006938 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006939 subtype = (xmlSchemaTypePtr)
6940 xmlSchemaParseUnion(ctxt, schema, child);
6941 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006942 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006943 type->subtypes = subtype;
6944 if ((child != NULL) || (subtype == NULL)) {
6945 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006946 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006947 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00006948 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006949 ctxt->parentItem = oldParentItem;
6950 ctxt->ctxtType = oldCtxtType;
6951 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006952
Daniel Veillard4255d502002-04-16 15:50:10 +00006953 return (type);
6954}
6955
6956
6957/**
6958 * xmlSchemaParseGroup:
6959 * @ctxt: a schema validation context
6960 * @schema: the schema being built
6961 * @node: a subtree containing XML Schema informations
6962 *
6963 * parse a XML schema Group definition
6964 * *WARNING* this interface is highly subject to change
6965 *
William M. Bracke7091952004-05-11 15:09:58 +00006966 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006967 * 1 in case of success.
6968 */
6969static xmlSchemaTypePtr
6970xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006971 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006972{
6973 xmlSchemaTypePtr type, subtype;
6974 xmlNodePtr child = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006975 const xmlChar *name, *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006976 const xmlChar *ref = NULL, *refNs = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006977 char buf[50];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006978 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00006979
6980 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6981 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006982 /*
6983 * TODO: Validate the element even if no item is created
6984 * (i.e. min/maxOccurs == 0).
6985 */
6986 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6987 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
6988 if ((minOccurs == 0) && (maxOccurs == 0)) {
6989 return (NULL);
6990 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006991 if (topLevel)
6992 ns = schema->targetNamespace;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006993 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006994 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006995 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
6996 if (ref == NULL) {
6997 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006998 XML_SCHEMAP_GROUP_NONAME_NOREF,
6999 "Group definition or particle: One of the attributes \"name\" "
7000 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007001 return (NULL);
7002 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007003 if (refNs == NULL)
7004 refNs = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007005 snprintf(buf, 49, "#grRef%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007006 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00007007 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007008 type = xmlSchemaAddGroup(ctxt, schema, name, ns, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007009 if (type == NULL)
7010 return (NULL);
7011 type->node = node;
7012 type->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007013 if (topLevel)
7014 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007015 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007016 type->ref = ref;
7017 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00007018 type->minOccurs = minOccurs;
7019 type->maxOccurs = maxOccurs;
7020 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007021 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00007022
7023 child = node->children;
7024 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007025 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7026 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007027 }
7028 subtype = NULL;
7029 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007030 subtype = (xmlSchemaTypePtr)
7031 xmlSchemaParseAll(ctxt, schema, child);
7032 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007033 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007034 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7035 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007036 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007037 subtype = (xmlSchemaTypePtr)
7038 xmlSchemaParseSequence(ctxt, schema, child);
7039 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007040 }
7041 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007042 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007043 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007044 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007045 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007046 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007047 }
7048
7049 return (type);
7050}
7051
7052/**
7053 * xmlSchemaParseAll:
7054 * @ctxt: a schema validation context
7055 * @schema: the schema being built
7056 * @node: a subtree containing XML Schema informations
7057 *
7058 * parse a XML schema All definition
7059 * *WARNING* this interface is highly subject to change
7060 *
William M. Bracke7091952004-05-11 15:09:58 +00007061 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007062 * 1 in case of success.
7063 */
7064static xmlSchemaTypePtr
7065xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007066 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007067{
7068 xmlSchemaTypePtr type, subtype, last = NULL;
7069 xmlNodePtr child = NULL;
7070 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007071 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007072
7073 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7074 return (NULL);
7075
7076
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007077 snprintf((char *) name, 30, "#all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007078 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007079 if (type == NULL)
7080 return (NULL);
7081 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00007082 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007083 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007084
7085 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
7086 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007087
7088 oldcontainer = ctxt->container;
7089 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007090 child = node->children;
7091 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007092 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7093 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007094 }
7095 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007096 subtype = (xmlSchemaTypePtr)
7097 xmlSchemaParseElement(ctxt, schema, child, 0);
7098 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00007099 if (subtype->minOccurs > 1)
7100 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007101 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007102 NULL, NULL);
7103 if (subtype->maxOccurs > 1)
7104 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007105 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007106 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007107 if (last == NULL) {
7108 type->subtypes = subtype;
7109 last = subtype;
7110 } else {
7111 last->next = subtype;
7112 last = subtype;
7113 }
7114 last->next = NULL;
7115 }
7116 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007117 }
7118 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007119 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007120 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007121 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007122 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007123 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007124 return (type);
7125}
7126
7127/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007128 * xmlSchemaCleanupDoc:
7129 * @ctxt: a schema validation context
7130 * @node: the root of the document.
7131 *
7132 * removes unwanted nodes in a schemas document tree
7133 */
7134static void
7135xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
7136{
7137 xmlNodePtr delete, cur;
7138
7139 if ((ctxt == NULL) || (root == NULL)) return;
7140
7141 /*
7142 * Remove all the blank text nodes
7143 */
7144 delete = NULL;
7145 cur = root;
7146 while (cur != NULL) {
7147 if (delete != NULL) {
7148 xmlUnlinkNode(delete);
7149 xmlFreeNode(delete);
7150 delete = NULL;
7151 }
7152 if (cur->type == XML_TEXT_NODE) {
7153 if (IS_BLANK_NODE(cur)) {
7154 if (xmlNodeGetSpacePreserve(cur) != 1) {
7155 delete = cur;
7156 }
7157 }
7158 } else if ((cur->type != XML_ELEMENT_NODE) &&
7159 (cur->type != XML_CDATA_SECTION_NODE)) {
7160 delete = cur;
7161 goto skip_children;
7162 }
7163
7164 /*
7165 * Skip to next node
7166 */
7167 if (cur->children != NULL) {
7168 if ((cur->children->type != XML_ENTITY_DECL) &&
7169 (cur->children->type != XML_ENTITY_REF_NODE) &&
7170 (cur->children->type != XML_ENTITY_NODE)) {
7171 cur = cur->children;
7172 continue;
7173 }
7174 }
7175 skip_children:
7176 if (cur->next != NULL) {
7177 cur = cur->next;
7178 continue;
7179 }
7180
7181 do {
7182 cur = cur->parent;
7183 if (cur == NULL)
7184 break;
7185 if (cur == root) {
7186 cur = NULL;
7187 break;
7188 }
7189 if (cur->next != NULL) {
7190 cur = cur->next;
7191 break;
7192 }
7193 } while (cur != NULL);
7194 }
7195 if (delete != NULL) {
7196 xmlUnlinkNode(delete);
7197 xmlFreeNode(delete);
7198 delete = NULL;
7199 }
7200}
7201
William M. Brack2f2a6632004-08-20 23:09:47 +00007202
7203/**
7204 * xmlSchemaImportSchema
7205 *
7206 * @ctxt: a schema validation context
7207 * @schemaLocation: an URI defining where to find the imported schema
7208 *
7209 * import a XML schema
7210 * *WARNING* this interface is highly subject to change
7211 *
7212 * Returns -1 in case of error and 1 in case of success.
7213 */
7214#if 0
7215static xmlSchemaImportPtr
7216xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
7217 const xmlChar *schemaLocation)
7218{
7219 xmlSchemaImportPtr import;
7220 xmlSchemaParserCtxtPtr newctxt;
7221
7222 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7223 if (newctxt == NULL) {
7224 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
7225 NULL);
7226 return (NULL);
7227 }
7228 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
7229 /* Keep the same dictionnary for parsing, really */
7230 xmlDictReference(ctxt->dict);
7231 newctxt->dict = ctxt->dict;
7232 newctxt->includes = 0;
7233 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
7234
7235 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
7236 ctxt->userData);
7237
7238 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7239 if (import == NULL) {
7240 xmlSchemaPErrMemory(NULL, "allocating imported schema",
7241 NULL);
7242 xmlSchemaFreeParserCtxt(newctxt);
7243 return (NULL);
7244 }
7245
7246 memset(import, 0, sizeof(xmlSchemaImport));
7247 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7248 import->schema = xmlSchemaParse(newctxt);
7249
7250 if (import->schema == NULL) {
7251 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00007252 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00007253 "Failed to import schema from location \"%s\".\n",
7254 schemaLocation, NULL);
7255
7256 xmlSchemaFreeParserCtxt(newctxt);
7257 /* The schemaLocation is held by the dictionary.
7258 if (import->schemaLocation != NULL)
7259 xmlFree((xmlChar *)import->schemaLocation);
7260 */
7261 xmlFree(import);
7262 return NULL;
7263 }
7264
7265 xmlSchemaFreeParserCtxt(newctxt);
7266 return import;
7267}
7268#endif
7269
7270static void
7271xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
7272{
7273 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7274 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
7275
7276 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
7277 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
7278
7279 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7280 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
7281 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7282 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
7283 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
7284 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
7285 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
7286 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
7287
7288 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7289 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
7290 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7291 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
7292 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7293 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
7294}
7295
7296static void
7297xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
7298 xmlSchemaPtr schema,
7299 xmlNodePtr node)
7300{
7301 xmlAttrPtr attr;
7302 const xmlChar *val;
7303
7304 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
7305 if (attr != NULL) {
7306 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7307 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7308 XML_SCHEMAS_QUALIF_ELEM) != 0) {
7309 xmlSchemaPSimpleTypeErr(ctxt,
7310 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
7311 NULL, NULL, (xmlNodePtr) attr, NULL,
7312 "(qualified | unqualified)", val, NULL, NULL, NULL);
7313 }
7314 }
7315
7316 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
7317 if (attr != NULL) {
7318 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7319 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7320 XML_SCHEMAS_QUALIF_ATTR) != 0) {
7321 xmlSchemaPSimpleTypeErr(ctxt,
7322 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
7323 NULL, NULL, (xmlNodePtr) attr, NULL,
7324 "(qualified | unqualified)", val, NULL, NULL, NULL);
7325 }
7326 }
7327
7328 attr = xmlSchemaGetPropNode(node, "finalDefault");
7329 if (attr != NULL) {
7330 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7331 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7332 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
7333 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
7334 -1,
7335 XML_SCHEMAS_FINAL_DEFAULT_LIST,
7336 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
7337 xmlSchemaPSimpleTypeErr(ctxt,
7338 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7339 NULL, NULL, (xmlNodePtr) attr, NULL,
7340 "(#all | List of (extension | restriction | list | union))",
7341 val, NULL, NULL, NULL);
7342 }
7343 }
7344
7345 attr = xmlSchemaGetPropNode(node, "blockDefault");
7346 if (attr != NULL) {
7347 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7348 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7349 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
7350 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
7351 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
7352 xmlSchemaPSimpleTypeErr(ctxt,
7353 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7354 NULL, NULL, (xmlNodePtr) attr, NULL,
7355 "(#all | List of (extension | restriction | substitution))",
7356 val, NULL, NULL, NULL);
7357 }
7358 }
7359}
7360
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007361/**
7362 * xmlSchemaParseSchemaTopLevel:
7363 * @ctxt: a schema validation context
7364 * @schema: the schemas
7365 * @nodes: the list of top level nodes
7366 *
7367 * Returns the internal XML Schema structure built from the resource or
7368 * NULL in case of error
7369 */
7370static void
7371xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
7372 xmlSchemaPtr schema, xmlNodePtr nodes)
7373{
7374 xmlNodePtr child;
7375 xmlSchemaAnnotPtr annot;
7376
7377 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
7378 return;
7379
7380 child = nodes;
7381 while ((IS_SCHEMA(child, "include")) ||
7382 (IS_SCHEMA(child, "import")) ||
7383 (IS_SCHEMA(child, "redefine")) ||
7384 (IS_SCHEMA(child, "annotation"))) {
7385 if (IS_SCHEMA(child, "annotation")) {
7386 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7387 if (schema->annot == NULL)
7388 schema->annot = annot;
7389 else
7390 xmlSchemaFreeAnnot(annot);
7391 } else if (IS_SCHEMA(child, "import")) {
7392 xmlSchemaParseImport(ctxt, schema, child);
7393 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007394 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007395 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007396 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007397 } else if (IS_SCHEMA(child, "redefine")) {
7398 TODO
7399 }
7400 child = child->next;
7401 }
7402 while (child != NULL) {
7403 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007404 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007405 child = child->next;
7406 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007407 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007408 child = child->next;
7409 } else if (IS_SCHEMA(child, "element")) {
7410 xmlSchemaParseElement(ctxt, schema, child, 1);
7411 child = child->next;
7412 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00007413 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007414 child = child->next;
7415 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007416 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007417 child = child->next;
7418 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007419 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007420 child = child->next;
7421 } else if (IS_SCHEMA(child, "notation")) {
7422 xmlSchemaParseNotation(ctxt, schema, child);
7423 child = child->next;
7424 } else {
7425 xmlSchemaPErr2(ctxt, NULL, child,
7426 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007427 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007428 child->name, NULL);
7429 child = child->next;
7430 }
7431 while (IS_SCHEMA(child, "annotation")) {
7432 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7433 if (schema->annot == NULL)
7434 schema->annot = annot;
7435 else
7436 xmlSchemaFreeAnnot(annot);
7437 child = child->next;
7438 }
7439 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007440 ctxt->parentItem = NULL;
7441 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007442}
7443
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007444static xmlSchemaImportPtr
7445xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
7446 xmlHashTablePtr *imports,
7447 const xmlChar *nsName)
7448{
7449 xmlSchemaImportPtr ret;
7450
7451 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00007452 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007453 if (*imports == NULL) {
7454 xmlSchemaPCustomErr(ctxt,
7455 XML_SCHEMAP_FAILED_BUILD_IMPORT,
7456 NULL, NULL, (xmlNodePtr) ctxt->doc,
7457 "Internal error: failed to build the import table",
7458 NULL);
7459 return (NULL);
7460 }
7461 }
7462 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7463 if (ret == NULL) {
7464 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
7465 return (NULL);
7466 }
7467 memset(ret, 0, sizeof(xmlSchemaImport));
7468 if (nsName == NULL)
7469 nsName = XML_SCHEMAS_NO_NAMESPACE;
7470 xmlHashAddEntry(*imports, nsName, ret);
7471
7472 return (ret);
7473}
7474
7475static int
7476xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007477 xmlSchemaPtr schema,
7478 xmlNodePtr node,
7479 const xmlChar *nsName,
7480 const xmlChar *location,
7481 xmlDocPtr *doc,
7482 const xmlChar **targetNamespace,
7483 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007484{
7485 xmlParserCtxtPtr parserCtxt;
7486 xmlSchemaImportPtr import;
7487 const xmlChar *ns;
7488 xmlNodePtr root;
7489
7490 /*
7491 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
7492 * <xsi:noNamespaceSchemaLocation>.
7493 */
7494 *doc = NULL;
7495 /*
7496 * Given that the schemaLocation [attribute] is only a hint, it is open
7497 * to applications to ignore all but the first <import> for a given
7498 * namespace, regardless of the ·actual value· of schemaLocation, but
7499 * such a strategy risks missing useful information when new
7500 * schemaLocations are offered.
7501 *
7502 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
7503 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
7504 * valid or not.
7505 * We will follow XSV here.
7506 */
7507 if (location == NULL) {
7508 /*
7509 * Schema Document Location Strategy:
7510 *
7511 * 3 Based on the namespace name, identify an existing schema document,
7512 * either as a resource which is an XML document or a <schema> element
7513 * information item, in some local schema repository;
7514 *
7515 * 5 Attempt to resolve the namespace name to locate such a resource.
7516 *
7517 * NOTE: Those stategies are not supported, so we will skip.
7518 */
7519 return (0);
7520 }
7521 if (nsName == NULL)
7522 ns = XML_SCHEMAS_NO_NAMESPACE;
7523 else
7524 ns = nsName;
7525
7526 import = xmlHashLookup(schema->schemasImports, ns);
7527 if (import != NULL) {
7528 /*
7529 * There was a valid resource for the specified namespace already
7530 * defined, so skip.
7531 * TODO: This might be changed someday to allow import of
7532 * components from multiple documents for a single target namespace.
7533 */
7534 return (0);
7535 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007536
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007537 /*
7538 * Schema Document Location Strategy:
7539 *
7540 * 2 Based on the location URI, identify an existing schema document,
7541 * either as a resource which is an XML document or a <schema> element
7542 * information item, in some local schema repository;
7543 *
7544 * 4 Attempt to resolve the location URI, to locate a resource on the
7545 * web which is or contains or references a <schema> element;
7546 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
7547 *
7548 */
7549 if ((absolute == 0) && (node != NULL)) {
7550 xmlChar *base, *URI;
7551
7552 base = xmlNodeGetBase(node->doc, node);
7553 if (base == NULL) {
7554 URI = xmlBuildURI(location, node->doc->URL);
7555 } else {
7556 URI = xmlBuildURI(location, base);
7557 xmlFree(base);
7558 }
7559 if (URI != NULL) {
7560 location = xmlDictLookup(ctxt->dict, URI, -1);
7561 xmlFree(URI);
7562 }
7563 }
7564 parserCtxt = xmlNewParserCtxt();
7565 if (parserCtxt == NULL) {
7566 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
7567 "allocating a parser context", NULL);
7568 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007569 }
7570
7571 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7572 xmlDictFree(parserCtxt->dict);
7573 parserCtxt->dict = ctxt->dict;
7574 xmlDictReference(parserCtxt->dict);
7575 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007576
7577 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
7578 NULL, SCHEMAS_PARSE_OPTIONS);
7579
7580 /*
7581 * 2.1 The referent is (a fragment of) a resource which is an
7582 * XML document (see clause 1.1), which in turn corresponds to
7583 * a <schema> element information item in a well-formed information
7584 * set, which in turn corresponds to a valid schema.
7585 * TODO: What to do with the "fragment" stuff?
7586 *
7587 * 2.2 The referent is a <schema> element information item in
7588 * a well-formed information set, which in turn corresponds
7589 * to a valid schema.
7590 * NOTE: 2.2 won't apply, since only XML documents will be processed
7591 * here.
7592 */
7593 if (*doc == NULL) {
7594 xmlErrorPtr lerr;
7595 /*
7596 * It is *not* an error for the application schema reference
7597 * strategy to fail.
7598 *
7599 * If the doc is NULL and the parser error is an IO error we
7600 * will assume that the resource could not be located or accessed.
7601 *
7602 * TODO: Try to find specific error codes to react only on
7603 * localisation failures.
7604 *
7605 * TODO, FIXME: Check the spec: is a namespace added to the imported
7606 * namespaces, even if the schemaLocation did not provide
7607 * a resource? I guess so, since omitting the "schemaLocation"
7608 * attribute, imports a namespace as well.
7609 */
7610 lerr = xmlGetLastError();
7611 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
7612 xmlFreeParserCtxt(parserCtxt);
7613 return(0);
7614 }
7615
7616 xmlSchemaPCustomErr(ctxt,
7617 XML_SCHEMAP_SRC_IMPORT_2_1,
7618 NULL, NULL, node,
7619 "Failed to parse the resource '%s' for import",
7620 location);
7621 xmlFreeParserCtxt(parserCtxt);
7622 return(XML_SCHEMAP_SRC_IMPORT_2_1);
7623 }
7624 xmlFreeParserCtxt(parserCtxt);
7625
7626 root = xmlDocGetRootElement(*doc);
7627 if (root == NULL) {
7628 xmlSchemaPCustomErr(ctxt,
7629 XML_SCHEMAP_SRC_IMPORT_2_1,
7630 NULL, NULL, node,
7631 "The XML document '%s' to be imported has no document "
7632 "element", location);
7633 xmlFreeDoc(*doc);
7634 *doc = NULL;
7635 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7636 }
7637
7638 xmlSchemaCleanupDoc(ctxt, root);
7639
7640 if (!IS_SCHEMA(root, "schema")) {
7641 xmlSchemaPCustomErr(ctxt,
7642 XML_SCHEMAP_SRC_IMPORT_2_1,
7643 NULL, NULL, node,
7644 "The XML document '%s' to be imported is not a XML schema document",
7645 location);
7646 xmlFreeDoc(*doc);
7647 *doc = NULL;
7648 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7649 }
7650 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
7651 /*
7652 * Schema Representation Constraint: Import Constraints and Semantics
7653 */
7654 if (nsName == NULL) {
7655 if (*targetNamespace != NULL) {
7656 xmlSchemaPCustomErr(ctxt,
7657 XML_SCHEMAP_SRC_IMPORT_3_2,
7658 NULL, NULL, node,
7659 "The XML schema to be imported is not expected "
7660 "to have a target namespace; this differs from "
7661 "its target namespace of '%s'", *targetNamespace);
7662 xmlFreeDoc(*doc);
7663 *doc = NULL;
7664 return (XML_SCHEMAP_SRC_IMPORT_3_2);
7665 }
7666 } else {
7667 if (*targetNamespace == NULL) {
7668 xmlSchemaPCustomErr(ctxt,
7669 XML_SCHEMAP_SRC_IMPORT_3_1,
7670 NULL, NULL, node,
7671 "The XML schema to be imported is expected to have a target "
7672 "namespace of '%s'", nsName);
7673 xmlFreeDoc(*doc);
7674 *doc = NULL;
7675 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7676 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
7677 xmlSchemaPCustomErrExt(ctxt,
7678 XML_SCHEMAP_SRC_IMPORT_3_1,
7679 NULL, NULL, node,
7680 "The XML schema to be imported is expected to have a "
7681 "target namespace of '%s'; this differs from "
7682 "its target namespace of '%s'",
7683 nsName, *targetNamespace, NULL);
7684 xmlFreeDoc(*doc);
7685 *doc = NULL;
7686 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7687 }
7688 }
7689
7690 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
7691 if (import == NULL) {
7692 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
7693 NULL, NULL, NULL,
7694 "Internal error: xmlSchemaAcquireSchemaDoc, "
7695 "failed to build import table", NULL);
7696 xmlFreeDoc(*doc);
7697 *doc = NULL;
7698 return (-1);
7699 }
7700 import->schemaLocation = location;
7701 import->doc = *doc;
7702 return (0);
7703}
William M. Brack2f2a6632004-08-20 23:09:47 +00007704
7705/**
7706 * xmlSchemaParseImport:
7707 * @ctxt: a schema validation context
7708 * @schema: the schema being built
7709 * @node: a subtree containing XML Schema informations
7710 *
7711 * parse a XML schema Import definition
7712 * *WARNING* this interface is highly subject to change
7713 *
7714 * Returns 0 in case of success, a positive error code if
7715 * not valid and -1 in case of an internal error.
7716 */
7717static int
7718xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7719 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007720{
7721 xmlNodePtr child;
7722 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007723 const xmlChar *schemaLocation = NULL;
7724 const xmlChar *targetNamespace, *oldTNS, *url;
7725 xmlAttrPtr attr;
7726 xmlDocPtr doc;
7727 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007728 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007729
7730
7731 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7732 return (-1);
7733
7734 /*
7735 * Check for illegal attributes.
7736 */
7737 attr = node->properties;
7738 while (attr != NULL) {
7739 if (attr->ns == NULL) {
7740 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7741 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7742 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7743 xmlSchemaPIllegalAttrErr(ctxt,
7744 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7745 NULL, NULL, attr);
7746 }
7747 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7748 xmlSchemaPIllegalAttrErr(ctxt,
7749 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7750 NULL, NULL, attr);
7751 }
7752 attr = attr->next;
7753 }
7754 /*
7755 * Extract and validate attributes.
7756 */
7757 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7758 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7759 &namespace) != 0) {
7760 xmlSchemaPSimpleTypeErr(ctxt,
7761 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
7762 NULL, NULL, node,
7763 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7764 NULL, namespace, NULL, NULL, NULL);
7765 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
7766 }
7767
7768 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7769 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7770 &schemaLocation) != 0) {
7771 xmlSchemaPSimpleTypeErr(ctxt,
7772 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
7773 NULL, NULL, node,
7774 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7775 NULL, namespace, NULL, NULL, NULL);
7776 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
7777 }
7778 /*
7779 * And now for the children...
7780 */
7781 child = node->children;
7782 if (IS_SCHEMA(child, "annotation")) {
7783 /*
7784 * the annotation here is simply discarded ...
7785 */
7786 child = child->next;
7787 }
7788 if (child != NULL) {
7789 xmlSchemaPContentErr(ctxt,
7790 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
7791 NULL, NULL, node, child, NULL,
7792 "(annotation?)");
7793 }
7794 /*
7795 * Apply additional constraints.
7796 */
7797 if (namespace != NULL) {
7798 /*
7799 * 1.1 If the namespace [attribute] is present, then its ·actual value·
7800 * must not match the ·actual value· of the enclosing <schema>'s
7801 * targetNamespace [attribute].
7802 */
7803 if (xmlStrEqual(schema->targetNamespace, namespace)) {
7804 xmlSchemaPCustomErr(ctxt,
7805 XML_SCHEMAP_SRC_IMPORT_1_1,
7806 NULL, NULL, node,
7807 "The value of the attribute 'namespace' must not match "
7808 "the target namespace '%s' of the importing schema",
7809 schema->targetNamespace);
7810 return (XML_SCHEMAP_SRC_IMPORT_1_1);
7811 }
7812 } else {
7813 /*
7814 * 1.2 If the namespace [attribute] is not present, then the enclosing
7815 * <schema> must have a targetNamespace [attribute].
7816 */
7817 if (schema->targetNamespace == NULL) {
7818 xmlSchemaPCustomErr(ctxt,
7819 XML_SCHEMAP_SRC_IMPORT_1_2,
7820 NULL, NULL, node,
7821 "The attribute 'namespace' must be existent if "
7822 "the importing schema has no target namespace",
7823 NULL);
7824 return (XML_SCHEMAP_SRC_IMPORT_1_2);
7825 }
7826 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007827 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007828 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00007829 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007830 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
7831 schemaLocation, &doc, &targetNamespace, 0);
7832 if (ret != 0) {
7833 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00007834 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007835 return (ret);
7836 } else if (doc != NULL) {
7837 /*
7838 * Save and reset the context & schema.
7839 */
7840 url = ctxt->URL;
7841 /* TODO: Is using the doc->URL here correct? */
7842 ctxt->URL = doc->URL;
7843 flags = schema->flags;
7844 oldTNS = schema->targetNamespace;
7845 /*
7846 * Parse the schema.
7847 */
7848 root = xmlDocGetRootElement(doc);
7849 xmlSchemaClearSchemaDefaults(schema);
7850 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
7851 schema->targetNamespace = targetNamespace;
7852 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
7853 /*
7854 * Restore the context & schema.
7855 */
7856 schema->flags = flags;
7857 schema->targetNamespace = oldTNS;
7858 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00007859 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007860
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007861 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007862}
7863
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007864/**
7865 * xmlSchemaParseInclude:
7866 * @ctxt: a schema validation context
7867 * @schema: the schema being built
7868 * @node: a subtree containing XML Schema informations
7869 *
7870 * parse a XML schema Include definition
7871 *
William M. Bracke7091952004-05-11 15:09:58 +00007872 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007873 * 1 in case of success.
7874 */
7875static int
7876xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7877 xmlNodePtr node)
7878{
7879 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007880 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007881 xmlDocPtr doc;
7882 xmlNodePtr root;
7883 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007884 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007885 xmlAttrPtr attr;
7886 int saveFlags;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007887 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007888
7889
7890 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7891 return (-1);
7892
7893 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007894 * Check for illegal attributes.
7895 */
7896 attr = node->properties;
7897 while (attr != NULL) {
7898 if (attr->ns == NULL) {
7899 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7900 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7901 xmlSchemaPIllegalAttrErr(ctxt,
7902 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7903 NULL, NULL, attr);
7904 }
7905 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7906 xmlSchemaPIllegalAttrErr(ctxt,
7907 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7908 NULL, NULL, attr);
7909 }
7910 attr = attr->next;
7911 }
7912 /*
7913 * Extract and validate attributes.
7914 */
7915 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007916 * Preliminary step, extract the URI-Reference for the include and
7917 * make an URI from the base.
7918 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007919 attr = xmlSchemaGetPropNode(node, "schemaLocation");
7920 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007921 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007922 xmlChar *uri = NULL;
7923
7924 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
7925 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
7926 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007927 base = xmlNodeGetBase(node->doc, node);
7928 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007929 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007930 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007931 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007932 xmlFree(base);
7933 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007934 if (uri != NULL) {
7935 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
7936 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007937 }
7938 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007939 xmlSchemaPMissingAttrErr(ctxt,
7940 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
7941 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007942 return (-1);
7943 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007944 /*
7945 * And now for the children...
7946 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007947 child = node->children;
7948 while (IS_SCHEMA(child, "annotation")) {
7949 /*
7950 * the annotations here are simply discarded ...
7951 */
7952 child = child->next;
7953 }
7954 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007955 xmlSchemaPContentErr(ctxt,
7956 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
7957 NULL, NULL, node, child, NULL,
7958 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007959 }
7960
7961 /*
7962 * First step is to parse the input document into an DOM/Infoset
7963 */
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007964 /*
7965 * TODO: Use xmlCtxtReadFile to share the dictionary.
7966 */
7967 parserCtxt = xmlNewParserCtxt();
7968 if (parserCtxt == NULL) {
7969 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
7970 "allocating a parser context", NULL);
7971 return(-1);
7972 }
7973
7974 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7975 xmlDictFree(parserCtxt->dict);
7976 parserCtxt->dict = ctxt->dict;
7977 xmlDictReference(parserCtxt->dict);
7978 }
7979
7980 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
7981 NULL, SCHEMAS_PARSE_OPTIONS);
7982 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007983 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007984 /*
7985 * TODO: It is not an error for the ·actual value· of the
7986 * schemaLocation [attribute] to fail to resolve it all, in which
7987 * case no corresponding inclusion is performed.
7988 * So do we need a warning report here?
7989 */
7990 xmlSchemaPCustomErr(ctxt,
7991 XML_SCHEMAP_FAILED_LOAD,
7992 NULL, NULL, node,
7993 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007994 return(-1);
7995 }
7996
7997 /*
7998 * Then extract the root of the schema
7999 */
8000 root = xmlDocGetRootElement(doc);
8001 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008002 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008003 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00008004 NULL, NULL, node,
8005 "The included document '%s' has no document "
8006 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008007 xmlFreeDoc(doc);
8008 return (-1);
8009 }
8010
8011 /*
8012 * Remove all the blank text nodes
8013 */
8014 xmlSchemaCleanupDoc(ctxt, root);
8015
8016 /*
8017 * Check the schemas top level element
8018 */
8019 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008020 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008021 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00008022 NULL, NULL, node,
8023 "The document '%s' to be included is not a schema document",
8024 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008025 xmlFreeDoc(doc);
8026 return (-1);
8027 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008028
William M. Brack2f2a6632004-08-20 23:09:47 +00008029 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008030 /*
8031 * 2.1 SII has a targetNamespace [attribute], and its ·actual
8032 * value· is identical to the ·actual value· of the targetNamespace
8033 * [attribute] of SIIÂ’ (which must have such an [attribute]).
8034 */
8035 if (targetNamespace != NULL) {
8036 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008037 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008038 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008039 NULL, NULL, node,
8040 "The target namespace of the included schema "
8041 "'%s' has to be absent, since the including schema "
8042 "has no target namespace",
8043 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008044 xmlFreeDoc(doc);
8045 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008046 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
8047 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008048 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008049 NULL, NULL, node,
8050 "The target namespace '%s' of the included schema '%s' "
8051 "differs from '%s' of the including schema",
8052 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008053 xmlFreeDoc(doc);
8054 return (-1);
8055 }
8056 } else if (schema->targetNamespace != NULL) {
8057 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
8058 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
8059 } else
8060 wasConvertingNs = 1;
8061 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008062 /*
8063 * register the include
8064 */
8065 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
8066 if (include == NULL) {
8067 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
8068 xmlFreeDoc(doc);
8069 return (-1);
8070 }
8071
8072 memset(include, 0, sizeof(xmlSchemaInclude));
8073 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8074 include->doc = doc;
8075 include->next = schema->includes;
8076 schema->includes = include;
8077
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008078 /*
8079 * parse the declarations in the included file like if they
8080 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008081 */
8082 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00008083 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008084 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008085 /*
8086 * The default values ("blockDefault", "elementFormDefault", etc.)
8087 * are set to the values of the included schema and restored afterwards.
8088 */
8089 saveFlags = schema->flags;
8090 xmlSchemaClearSchemaDefaults(schema);
8091 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008092 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00008093 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008094 /*
8095 * Remove the converting flag.
8096 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008097 if ((wasConvertingNs == 0) &&
8098 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00008099 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008100 return (1);
8101}
8102
8103/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008104 * xmlSchemaParseChoice:
8105 * @ctxt: a schema validation context
8106 * @schema: the schema being built
8107 * @node: a subtree containing XML Schema informations
8108 *
8109 * parse a XML schema Choice definition
8110 * *WARNING* this interface is highly subject to change
8111 *
William M. Bracke7091952004-05-11 15:09:58 +00008112 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008113 * 1 in case of success.
8114 */
8115static xmlSchemaTypePtr
8116xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008117 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008118{
8119 xmlSchemaTypePtr type, subtype, last = NULL;
8120 xmlNodePtr child = NULL;
8121 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008122 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008123 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008124
8125 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8126 return (NULL);
8127
8128
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008129 snprintf((char *) name, 30, "#ch%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008130 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008131 if (type == NULL)
8132 return (NULL);
8133 type->node = node;
8134 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008135 /*
8136 * Check for illegal attributes.
8137 */
8138 attr = node->properties;
8139 while (attr != NULL) {
8140 if (attr->ns == NULL) {
8141 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8142 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8143 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8144 xmlSchemaPIllegalAttrErr(ctxt,
8145 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8146 NULL, type, attr);
8147 }
8148 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8149 xmlSchemaPIllegalAttrErr(ctxt,
8150 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8151 NULL, type, attr);
8152 }
8153 attr = attr->next;
8154 }
8155 /*
8156 * Extract and validate attributes.
8157 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008158 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008159 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8160 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8161 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008162 /*
8163 * And now for the children...
8164 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008165 oldcontainer = ctxt->container;
8166 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008167 child = node->children;
8168 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008169 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8170 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008171 }
8172 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008173 (IS_SCHEMA(child, "group")) ||
8174 (IS_SCHEMA(child, "any")) ||
8175 (IS_SCHEMA(child, "choice")) ||
8176 (IS_SCHEMA(child, "sequence"))) {
8177 subtype = NULL;
8178 if (IS_SCHEMA(child, "element")) {
8179 subtype = (xmlSchemaTypePtr)
8180 xmlSchemaParseElement(ctxt, schema, child, 0);
8181 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008182 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008183 } else if (IS_SCHEMA(child, "any")) {
8184 subtype = xmlSchemaParseAny(ctxt, schema, child);
8185 } else if (IS_SCHEMA(child, "sequence")) {
8186 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8187 } else if (IS_SCHEMA(child, "choice")) {
8188 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8189 }
8190 if (subtype != NULL) {
8191 if (last == NULL) {
8192 type->subtypes = subtype;
8193 last = subtype;
8194 } else {
8195 last->next = subtype;
8196 last = subtype;
8197 }
8198 last->next = NULL;
8199 }
8200 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008201 }
8202 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008203 /* TODO: error code. */
8204 xmlSchemaPContentErr(ctxt,
8205 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
8206 NULL, type, node, child, NULL,
8207 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008208 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008209 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008210 return (type);
8211}
8212
8213/**
8214 * xmlSchemaParseSequence:
8215 * @ctxt: a schema validation context
8216 * @schema: the schema being built
8217 * @node: a subtree containing XML Schema informations
8218 *
8219 * parse a XML schema Sequence definition
8220 * *WARNING* this interface is highly subject to change
8221 *
William M. Bracke7091952004-05-11 15:09:58 +00008222 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008223 * 1 in case of success.
8224 */
8225static xmlSchemaTypePtr
8226xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008227 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008228{
8229 xmlSchemaTypePtr type, subtype, last = NULL;
8230 xmlNodePtr child = NULL;
8231 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008232 xmlAttrPtr attr;
8233 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008234
8235 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8236 return (NULL);
8237
William M. Brack2f2a6632004-08-20 23:09:47 +00008238 oldcontainer = ctxt->container;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008239 snprintf((char *) name, 30, "#seq%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008240 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008241 if (type == NULL)
8242 return (NULL);
8243 type->node = node;
8244 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008245 /*
8246 * Check for illegal attributes.
8247 */
8248 attr = node->properties;
8249 while (attr != NULL) {
8250 if (attr->ns == NULL) {
8251 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8252 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8253 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8254 xmlSchemaPIllegalAttrErr(ctxt,
8255 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8256 NULL, type, attr);
8257 }
8258 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8259 xmlSchemaPIllegalAttrErr(ctxt,
8260 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8261 NULL, type, attr);
8262 }
8263 attr = attr->next;
8264 }
8265 /*
8266 * Extract and validate attributes.
8267 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008268 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008269 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8270 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8271 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008272 /*
8273 * And now for the children...
8274 */
8275 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008276 child = node->children;
8277 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008278 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8279 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008280 }
8281 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008282 (IS_SCHEMA(child, "group")) ||
8283 (IS_SCHEMA(child, "any")) ||
8284 (IS_SCHEMA(child, "choice")) ||
8285 (IS_SCHEMA(child, "sequence"))) {
8286 subtype = NULL;
8287 if (IS_SCHEMA(child, "element")) {
8288 subtype = (xmlSchemaTypePtr)
8289 xmlSchemaParseElement(ctxt, schema, child, 0);
8290 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008291 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008292 } else if (IS_SCHEMA(child, "any")) {
8293 subtype = xmlSchemaParseAny(ctxt, schema, child);
8294 } else if (IS_SCHEMA(child, "choice")) {
8295 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8296 } else if (IS_SCHEMA(child, "sequence")) {
8297 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8298 }
8299 if (subtype != NULL) {
8300 if (last == NULL) {
8301 type->subtypes = subtype;
8302 last = subtype;
8303 } else {
8304 last->next = subtype;
8305 last = subtype;
8306 }
8307 last->next = NULL;
8308 }
8309 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008310 }
8311 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008312 xmlSchemaPContentErr(ctxt,
8313 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
8314 NULL, type, node, child, NULL,
8315 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008316 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008317 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008318
8319 return (type);
8320}
8321
8322/**
8323 * xmlSchemaParseRestriction:
8324 * @ctxt: a schema validation context
8325 * @schema: the schema being built
8326 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00008327 *
8328 * parse a XML schema Restriction definition
8329 * *WARNING* this interface is highly subject to change
8330 *
8331 * Returns the type definition or NULL in case of error
8332 */
8333static xmlSchemaTypePtr
8334xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008335 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008336{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008337 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00008338 xmlNodePtr child = NULL;
8339 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008340 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00008341 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008342
8343 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8344 return (NULL);
8345
8346 oldcontainer = ctxt->container;
8347
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008348 snprintf((char *) name, 30, "#restr%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008349 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008350 if (type == NULL)
8351 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008352 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008353 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00008354 /*
8355 * Check for illegal attributes.
8356 */
8357 attr = node->properties;
8358 while (attr != NULL) {
8359 if (attr->ns == NULL) {
8360 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8361 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
8362 xmlSchemaPIllegalAttrErr(ctxt,
8363 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8364 NULL, type, attr);
8365 }
8366 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8367 xmlSchemaPIllegalAttrErr(ctxt,
8368 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8369 NULL, type, attr);
8370 }
8371 attr = attr->next;
8372 }
8373 /*
8374 * Extract and validate attributes.
8375 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008376 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008377 /*
8378 * Attribute "base".
8379 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008380 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00008381 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00008382 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8383 /* TODO: Think about the error code. */
8384 xmlSchemaPMissingAttrErr(ctxt,
8385 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
8386 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008387 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008388 /*
8389 * And now for the children...
8390 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008391 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008392 child = node->children;
8393 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008394 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8395 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008396 }
8397 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008398 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8399 if (IS_SCHEMA(child, "all")) {
8400 subtype = (xmlSchemaTypePtr)
8401 xmlSchemaParseAll(ctxt, schema, child);
8402 child = child->next;
8403 type->subtypes = subtype;
8404 } else if (IS_SCHEMA(child, "choice")) {
8405 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8406 child = child->next;
8407 type->subtypes = subtype;
8408 } else if (IS_SCHEMA(child, "sequence")) {
8409 subtype = (xmlSchemaTypePtr)
8410 xmlSchemaParseSequence(ctxt, schema, child);
8411 child = child->next;
8412 type->subtypes = subtype;
8413 } else if (IS_SCHEMA(child, "group")) {
8414 subtype = (xmlSchemaTypePtr)
8415 xmlSchemaParseGroup(ctxt, schema, child, 0);
8416 child = child->next;
8417 type->subtypes = subtype;
8418 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008419 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
8420 if (IS_SCHEMA(child, "simpleType")) {
8421 if (type->base != NULL) {
8422 /*
8423 * src-restriction-base-or-simpleType
8424 * Either the base [attribute] or the simpleType [child] of the
8425 * <restriction> element must be present, but not both.
8426 */
8427 xmlSchemaPContentErr(ctxt,
8428 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
8429 NULL, NULL, type->node, child,
8430 "The attribute 'base' and the <simpleType> child are "
8431 "mutually exclusive", NULL);
8432 } else {
8433 subtype = (xmlSchemaTypePtr)
8434 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8435 type->baseType = subtype;
8436 }
8437 child = child->next;
8438 }
8439 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008440 if (IS_SCHEMA(child, "simpleType")) {
8441 subtype = (xmlSchemaTypePtr)
8442 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008443 type->subtypes = subtype;
8444 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00008445 }
8446 }
8447 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
8448 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
8449 xmlSchemaFacetPtr facet, lastfacet = NULL;
8450
Daniel Veillard01fa6152004-06-29 17:04:39 +00008451 /*
8452 * Add the facets to the parent simpleType/complexType.
8453 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008454 /*
8455 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
8456 * Simple Type Definition Schema Representation Constraint:
8457 * *Single Facet Value*
8458 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008459 while ((IS_SCHEMA(child, "minInclusive")) ||
8460 (IS_SCHEMA(child, "minExclusive")) ||
8461 (IS_SCHEMA(child, "maxInclusive")) ||
8462 (IS_SCHEMA(child, "maxExclusive")) ||
8463 (IS_SCHEMA(child, "totalDigits")) ||
8464 (IS_SCHEMA(child, "fractionDigits")) ||
8465 (IS_SCHEMA(child, "pattern")) ||
8466 (IS_SCHEMA(child, "enumeration")) ||
8467 (IS_SCHEMA(child, "whiteSpace")) ||
8468 (IS_SCHEMA(child, "length")) ||
8469 (IS_SCHEMA(child, "maxLength")) ||
8470 (IS_SCHEMA(child, "minLength"))) {
8471 facet = xmlSchemaParseFacet(ctxt, schema, child);
8472 if (facet != NULL) {
8473 if (lastfacet == NULL)
8474 ctxt->ctxtType->facets = facet;
8475 else
8476 lastfacet->next = facet;
8477 lastfacet = facet;
8478 lastfacet->next = NULL;
8479 }
8480 child = child->next;
8481 }
8482 /*
8483 * Create links for derivation and validation.
8484 */
8485 if (lastfacet != NULL) {
8486 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
8487
8488 facet = ctxt->ctxtType->facets;
8489 do {
8490 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
8491 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008492 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008493 xmlFree(facetLink);
8494 return (NULL);
8495 }
8496 facetLink->facet = facet;
8497 facetLink->next = NULL;
8498 if (lastFacetLink == NULL)
8499 ctxt->ctxtType->facetSet = facetLink;
8500 else
8501 lastFacetLink->next = facetLink;
8502 lastFacetLink = facetLink;
8503 facet = facet->next;
8504 } while (facet != NULL);
8505 }
8506 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008507 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
8508 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8509 if (IS_SCHEMA(child, "anyAttribute")) {
8510 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8511 child = child->next;
8512 }
8513 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008514 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008515 /* TODO: Think about the error code. */
8516 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8517 xmlSchemaPContentErr(ctxt,
8518 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8519 NULL, type, node, child, NULL,
8520 "annotation?, (group | all | choice | sequence)?, "
8521 "((attribute | attributeGroup)*, anyAttribute?))");
8522 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
8523 xmlSchemaPContentErr(ctxt,
8524 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8525 NULL, type, node, child, NULL,
8526 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8527 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8528 "length | minLength | maxLength | enumeration | whiteSpace | "
8529 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
8530 } else {
8531 /* Simple type */
8532 xmlSchemaPContentErr(ctxt,
8533 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8534 NULL, type, node, child, NULL,
8535 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8536 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8537 "length | minLength | maxLength | enumeration | whiteSpace | "
8538 "pattern)*))");
8539 }
8540 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008541 ctxt->container = oldcontainer;
8542 return (type);
8543}
8544
8545/**
8546 * xmlSchemaParseExtension:
8547 * @ctxt: a schema validation context
8548 * @schema: the schema being built
8549 * @node: a subtree containing XML Schema informations
8550 *
8551 * parse a XML schema Extension definition
8552 * *WARNING* this interface is highly subject to change
8553 *
8554 * Returns the type definition or NULL in case of error
8555 */
8556static xmlSchemaTypePtr
8557xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008558 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008559{
8560 xmlSchemaTypePtr type, subtype;
8561 xmlNodePtr child = NULL;
8562 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008563 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008564
8565 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8566 return (NULL);
8567
8568 oldcontainer = ctxt->container;
8569
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008570 snprintf((char *) name, 30, "#ext%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008571 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008572 if (type == NULL)
8573 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008574 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008575 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008576 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00008577 ctxt->container = name;
8578
8579 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
8580 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008581 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008582 "<extension>: The attribute \"base\" is missing.\n",
8583 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008584 }
8585 child = node->children;
8586 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008587 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8588 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008589 }
8590 subtype = NULL;
8591
8592 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008593 subtype = xmlSchemaParseAll(ctxt, schema, child);
8594 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008595 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008596 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8597 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008598 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008599 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8600 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008601 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008602 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008603 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008604 }
8605 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008606 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008607 if ((ctxt->ctxtType != NULL) &&
8608 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8609 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8610 if (IS_SCHEMA(child, "anyAttribute")) {
8611 ctxt->ctxtType->attributeWildcard =
8612 xmlSchemaParseAnyAttribute(ctxt, schema, child);
8613 child = child->next;
8614 }
8615 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008616 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008617 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008618 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
8619 "<extension> has unexpected content.\n", type->name,
8620 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008621 }
8622 ctxt->container = oldcontainer;
8623 return (type);
8624}
8625
8626/**
8627 * xmlSchemaParseSimpleContent:
8628 * @ctxt: a schema validation context
8629 * @schema: the schema being built
8630 * @node: a subtree containing XML Schema informations
8631 *
8632 * parse a XML schema SimpleContent definition
8633 * *WARNING* this interface is highly subject to change
8634 *
8635 * Returns the type definition or NULL in case of error
8636 */
8637static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008638xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
8639 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008640{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008641 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008642 xmlNodePtr child = NULL;
8643 xmlChar name[30];
8644
8645 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8646 return (NULL);
8647
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008648 snprintf((char *) name, 30, "#SC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008649 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008650 if (type == NULL)
8651 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008652 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00008653 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008654 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00008655
8656 child = node->children;
8657 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008658 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8659 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008660 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008661 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008662 ctxt->parentItem = type;
8663 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008664 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008665 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008666 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008667 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008668 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008669 subtype = (xmlSchemaTypePtr)
8670 xmlSchemaParseExtension(ctxt, schema, child);
8671 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008672 }
8673 type->subtypes = subtype;
8674 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008675 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008676 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
8677 "<simpleContent> has unexpected content.\n",
8678 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008679 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008680 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008681 return (type);
8682}
8683
8684/**
8685 * xmlSchemaParseComplexContent:
8686 * @ctxt: a schema validation context
8687 * @schema: the schema being built
8688 * @node: a subtree containing XML Schema informations
8689 *
8690 * parse a XML schema ComplexContent definition
8691 * *WARNING* this interface is highly subject to change
8692 *
8693 * Returns the type definition or NULL in case of error
8694 */
8695static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008696xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
8697 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008698{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008699 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008700 xmlNodePtr child = NULL;
8701 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008702 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008703
8704 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8705 return (NULL);
8706
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008707 snprintf((char *) name, 30, "#CC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008708 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008709 if (type == NULL)
8710 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008711 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008712 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008713 /*
8714 * Check for illegal attributes.
8715 */
8716 attr = node->properties;
8717 while (attr != NULL) {
8718 if (attr->ns == NULL) {
8719 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8720 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
8721 {
8722 xmlSchemaPIllegalAttrErr(ctxt,
8723 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8724 NULL, NULL, attr);
8725 }
8726 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8727 xmlSchemaPIllegalAttrErr(ctxt,
8728 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8729 NULL, NULL, attr);
8730 }
8731 attr = attr->next;
8732 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008733 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008734 /*
8735 * Handle attribute 'mixed'.
8736 */
8737 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
8738 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
8739 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
8740 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008741 child = node->children;
8742 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008743 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8744 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008745 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008746 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008747 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008748 subtype = NULL;
8749 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008750 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008751 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008752 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008753 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008754 subtype = (xmlSchemaTypePtr)
8755 xmlSchemaParseExtension(ctxt, schema, child);
8756 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008757 }
8758 type->subtypes = subtype;
8759 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008760 xmlSchemaPContentErr(ctxt,
8761 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8762 NULL, NULL, node, child,
8763 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008764 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008765 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008766 return (type);
8767}
8768
8769/**
8770 * xmlSchemaParseComplexType:
8771 * @ctxt: a schema validation context
8772 * @schema: the schema being built
8773 * @node: a subtree containing XML Schema informations
8774 *
8775 * parse a XML schema Complex Type definition
8776 * *WARNING* this interface is highly subject to change
8777 *
8778 * Returns the type definition or NULL in case of error
8779 */
8780static xmlSchemaTypePtr
8781xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008782 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008783{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008784 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008785 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008786 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008787 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008788 xmlAttrPtr attr;
8789 const xmlChar *attrValue;
8790 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00008791 char buf[40];
8792
Daniel Veillard4255d502002-04-16 15:50:10 +00008793
8794 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8795 return (NULL);
8796
Daniel Veillard01fa6152004-06-29 17:04:39 +00008797 ctxtType = ctxt->ctxtType;
8798
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008799 if (topLevel) {
8800 attr = xmlSchemaGetPropNode(node, "name");
8801 if (attr == NULL) {
8802 xmlSchemaPMissingAttrErr(ctxt,
8803 XML_SCHEMAP_S4S_ATTR_MISSING,
8804 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
8805 "name", NULL);
8806 return (NULL);
8807 } else if (xmlSchemaPValAttrNode(ctxt,
8808 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
8809 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8810 return (NULL);
8811 }
8812 }
8813
8814 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008815 /*
8816 * Parse as local complex type definition.
8817 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008818 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008819 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
8820 if (type == NULL)
8821 return (NULL);
8822 name = (const xmlChar *) buf;
8823 type->node = node;
8824 type->type = XML_SCHEMA_TYPE_COMPLEX;
8825 /*
8826 * TODO: We need the target namespace.
8827 */
8828 } else {
8829 /*
8830 * Parse as global complex type definition.
8831 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008832 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008833 if (type == NULL)
8834 return (NULL);
8835 type->node = node;
8836 type->type = XML_SCHEMA_TYPE_COMPLEX;
8837 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8838 /*
8839 * Set defaults.
8840 */
8841 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
8842 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008843 }
8844 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008845 /*
8846 * Handle attributes.
8847 */
8848 attr = node->properties;
8849 while (attr != NULL) {
8850 if (attr->ns == NULL) {
8851 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
8852 /*
8853 * Attribute "id".
8854 */
8855 type->id = xmlSchemaGetProp(ctxt, node, "id");
8856 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
8857 /*
8858 * Attribute "mixed".
8859 */
8860 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8861 (xmlNodePtr) attr))
8862 type->flags |= XML_SCHEMAS_TYPE_MIXED;
8863 } else if (topLevel) {
8864 /*
8865 * Attributes of global complex type definitions.
8866 */
8867 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
8868 /* Pass. */
8869 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
8870 /*
8871 * Attribute "abstract".
8872 */
8873 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8874 (xmlNodePtr) attr))
8875 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
8876 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
8877 /*
8878 * Attribute "final".
8879 */
8880 attrValue = xmlSchemaGetNodeContent(ctxt,
8881 (xmlNodePtr) attr);
8882 if (xmlSchemaPValAttrBlockFinal(attrValue,
8883 &(type->flags),
8884 -1,
8885 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
8886 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
8887 -1, -1, -1) != 0)
8888 {
8889 xmlSchemaPSimpleTypeErr(ctxt,
8890 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8891 &des, type, (xmlNodePtr) attr,
8892 NULL,
8893 "(#all | List of (extension | restriction))",
8894 attrValue, NULL, NULL, NULL);
8895 }
8896 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
8897 /*
8898 * Attribute "block".
8899 */
8900 attrValue = xmlSchemaGetNodeContent(ctxt,
8901 (xmlNodePtr) attr);
8902 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8903 -1,
8904 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
8905 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
8906 -1, -1, -1) != 0) {
8907 xmlSchemaPSimpleTypeErr(ctxt,
8908 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8909 &des, type, (xmlNodePtr) attr,
8910 NULL,
8911 "(#all | List of (extension | restriction)) ",
8912 attrValue, NULL, NULL, NULL);
8913 }
8914 } else {
8915 xmlSchemaPIllegalAttrErr(ctxt,
8916 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8917 &des, type, attr);
8918 }
8919 } else {
8920 xmlSchemaPIllegalAttrErr(ctxt,
8921 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8922 &des, type, attr);
8923 }
8924 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8925 xmlSchemaPIllegalAttrErr(ctxt,
8926 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8927 &des, type, attr);
8928 }
8929 attr = attr->next;
8930 }
8931 /*
8932 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008933 * This will be only changed if a complex type
8934 * inherits an attribute wildcard from a base type.
8935 */
8936 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008937 /*
8938 * And now for the children...
8939 */
8940 oldcontainer = ctxt->container;
8941 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008942 child = node->children;
8943 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008944 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8945 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008946 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008947 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008948 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008949 /*
8950 * 3.4.3 : 2.2
8951 * Specifying mixed='true' when the <simpleContent>
8952 * alternative is chosen has no effect
8953 */
William M. Bracke7091952004-05-11 15:09:58 +00008954 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
8955 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008956 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
8957 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008958 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008959 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
8960 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008961 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008962 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008963 /*
8964 * Parse model groups.
8965 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008966 if (IS_SCHEMA(child, "all")) {
8967 subtype = xmlSchemaParseAll(ctxt, schema, child);
8968 child = child->next;
8969 } else if (IS_SCHEMA(child, "choice")) {
8970 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8971 child = child->next;
8972 } else if (IS_SCHEMA(child, "sequence")) {
8973 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8974 child = child->next;
8975 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008976 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008977 child = child->next;
8978 }
8979 if (subtype != NULL)
8980 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008981 /*
8982 * Parse attribute decls/refs.
8983 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008984 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008985 /*
8986 * Parse attribute wildcard.
8987 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008988 if (IS_SCHEMA(child, "anyAttribute")) {
8989 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8990 child = child->next;
8991 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008992 }
8993 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008994 xmlSchemaPContentErr(ctxt,
8995 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8996 &des, type, node, child,
8997 NULL, "(annotation?, (simpleContent | complexContent | "
8998 "((group | all | choice | sequence)?, ((attribute | "
8999 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009000 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009001 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00009002 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009003 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009004 return (type);
9005}
9006
Daniel Veillard4255d502002-04-16 15:50:10 +00009007/**
9008 * xmlSchemaParseSchema:
9009 * @ctxt: a schema validation context
9010 * @node: a subtree containing XML Schema informations
9011 *
9012 * parse a XML schema definition from a node set
9013 * *WARNING* this interface is highly subject to change
9014 *
9015 * Returns the internal XML Schema structure built from the resource or
9016 * NULL in case of error
9017 */
9018static xmlSchemaPtr
9019xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
9020{
9021 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009022 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009023 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009024 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009025
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009026 /*
9027 * This one is called by xmlSchemaParse only and is used if
9028 * the schema to be parsed was specified via the API; i.e. not
9029 * automatically by the validated instance document.
9030 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009031 if ((ctxt == NULL) || (node == NULL))
9032 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009033 nberrors = ctxt->nberrors;
9034 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009035 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009036 xmlSchemaImportPtr import;
9037
Daniel Veillard4255d502002-04-16 15:50:10 +00009038 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009039 if (schema == NULL)
9040 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009041 /*
9042 * Disable build of list of items.
9043 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009044 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9045 if (attr != NULL) {
9046 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9047 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
9048 /*
9049 * TODO: Should we proceed with an invalid target namespace?
9050 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009051 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
9052 } else {
9053 schema->targetNamespace = NULL;
9054 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009055 /*
9056 * Add the current ns name and location to the import table;
9057 * this is needed to have a consistent mechanism, regardless
9058 * if all schemata are constructed dynamically fired by the
9059 * instance or if the schema to be used was specified via
9060 * the API.
9061 */
9062 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
9063 schema->targetNamespace);
9064 if (import == NULL) {
9065 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
9066 NULL, NULL, (xmlNodePtr) ctxt->doc,
9067 "Internal error: xmlSchemaParseSchema, "
9068 "failed to add an import entry", NULL);
9069 xmlSchemaFree(schema);
9070 schema = NULL;
9071 return (NULL);
9072 }
9073 import->schemaLocation = ctxt->URL;
9074 /*
9075 * NOTE: We won't set the doc here, otherwise it will be freed
9076 * if the import struct is freed.
9077 * import->doc = ctxt->doc;
9078 */
9079
Daniel Veillardc0826a72004-08-10 14:17:33 +00009080 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009081 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009082 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
9083 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
9084
William M. Brack2f2a6632004-08-20 23:09:47 +00009085 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009086 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
9087 } else {
9088 xmlDocPtr doc;
9089
9090 doc = node->doc;
9091
9092 if ((doc != NULL) && (doc->URL != NULL)) {
9093 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9094 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009095 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009096 } else {
9097 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9098 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009099 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009100 }
9101 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009102 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009103 if (ctxt->nberrors != 0) {
9104 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009105 xmlSchemaFree(schema);
9106 schema = NULL;
9107 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009108 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009109 if (schema != NULL)
9110 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009111 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00009112#ifdef DEBUG
9113 if (schema == NULL)
9114 xmlGenericError(xmlGenericErrorContext,
9115 "xmlSchemaParse() failed\n");
9116#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009117 return (schema);
9118}
9119
9120/************************************************************************
9121 * *
9122 * Validating using Schemas *
9123 * *
9124 ************************************************************************/
9125
9126/************************************************************************
9127 * *
9128 * Reading/Writing Schemas *
9129 * *
9130 ************************************************************************/
9131
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009132#if 0 /* Will be enabled if it is clear what options are needed. */
9133/**
9134 * xmlSchemaParserCtxtSetOptions:
9135 * @ctxt: a schema parser context
9136 * @options: a combination of xmlSchemaParserOption
9137 *
9138 * Sets the options to be used during the parse.
9139 *
9140 * Returns 0 in case of success, -1 in case of an
9141 * API error.
9142 */
9143static int
9144xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
9145 int options)
9146
9147{
9148 int i;
9149
9150 if (ctxt == NULL)
9151 return (-1);
9152 /*
9153 * WARNING: Change the start value if adding to the
9154 * xmlSchemaParseOption.
9155 */
9156 for (i = 1; i < (int) sizeof(int) * 8; i++) {
9157 if (options & 1<<i) {
9158 return (-1);
9159 }
9160 }
9161 ctxt->options = options;
9162 return (0);
9163}
9164
9165/**
9166 * xmlSchemaValidCtxtGetOptions:
9167 * @ctxt: a schema parser context
9168 *
9169 * Returns the option combination of the parser context.
9170 */
9171static int
9172xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
9173
9174{
9175 if (ctxt == NULL)
9176 return (-1);
9177 else
9178 return (ctxt->options);
9179}
9180
9181 void *curItems; /* used for dynamic addition of schemata */
9182 int nbCurItems; /* used for dynamic addition of schemata */
9183 int sizeCurItems; /* used for dynamic addition of schemata */
9184
9185#endif
9186
Daniel Veillard4255d502002-04-16 15:50:10 +00009187/**
9188 * xmlSchemaNewParserCtxt:
9189 * @URL: the location of the schema
9190 *
9191 * Create an XML Schemas parse context for that file/resource expected
9192 * to contain an XML Schemas file.
9193 *
9194 * Returns the parser context or NULL in case of error
9195 */
9196xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009197xmlSchemaNewParserCtxt(const char *URL)
9198{
Daniel Veillard4255d502002-04-16 15:50:10 +00009199 xmlSchemaParserCtxtPtr ret;
9200
9201 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009202 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009203
9204 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9205 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009206 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009207 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009208 return (NULL);
9209 }
9210 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009211 ret->dict = xmlDictCreate();
9212 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00009213 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009214 return (ret);
9215}
9216
9217/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009218 * xmlSchemaNewParserCtxtUseDict:
9219 * @URL: the location of the schema
9220 * @dict: the dictionary to be used
9221 *
9222 * Create an XML Schemas parse context for that file/resource expected
9223 * to contain an XML Schemas file.
9224 *
9225 * Returns the parser context or NULL in case of error
9226 */
9227static xmlSchemaParserCtxtPtr
9228xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9229{
9230 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009231 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009232 if (URL == NULL)
9233 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009234 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009235
9236 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9237 if (ret == NULL) {
9238 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9239 NULL);
9240 return (NULL);
9241 }
9242 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9243 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009244 xmlDictReference(dict);
9245 if (URL != NULL)
9246 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009247 ret->includes = 0;
9248 return (ret);
9249}
9250
9251
9252/**
Daniel Veillard6045c902002-10-09 21:13:59 +00009253 * xmlSchemaNewMemParserCtxt:
9254 * @buffer: a pointer to a char array containing the schemas
9255 * @size: the size of the array
9256 *
9257 * Create an XML Schemas parse context for that memory buffer expected
9258 * to contain an XML Schemas file.
9259 *
9260 * Returns the parser context or NULL in case of error
9261 */
9262xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009263xmlSchemaNewMemParserCtxt(const char *buffer, int size)
9264{
Daniel Veillard6045c902002-10-09 21:13:59 +00009265 xmlSchemaParserCtxtPtr ret;
9266
9267 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009268 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009269
9270 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9271 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009272 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009273 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009274 return (NULL);
9275 }
9276 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9277 ret->buffer = buffer;
9278 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009279 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00009280 return (ret);
9281}
9282
9283/**
Daniel Veillard9d751502003-10-29 13:21:47 +00009284 * xmlSchemaNewDocParserCtxt:
9285 * @doc: a preparsed document tree
9286 *
9287 * Create an XML Schemas parse context for that document.
9288 * NB. The document may be modified during the parsing process.
9289 *
9290 * Returns the parser context or NULL in case of error
9291 */
9292xmlSchemaParserCtxtPtr
9293xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
9294{
9295 xmlSchemaParserCtxtPtr ret;
9296
9297 if (doc == NULL)
9298 return (NULL);
9299
9300 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9301 if (ret == NULL) {
9302 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9303 NULL);
9304 return (NULL);
9305 }
9306 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9307 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009308 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00009309 /* The application has responsibility for the document */
9310 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00009311
9312 return (ret);
9313}
9314
9315/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009316 * xmlSchemaFreeParserCtxt:
9317 * @ctxt: the schema parser context
9318 *
9319 * Free the resources associated to the schema parser context
9320 */
9321void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009322xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
9323{
Daniel Veillard4255d502002-04-16 15:50:10 +00009324 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009325 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00009326 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009327 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009328 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009329 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009330 xmlFree(ctxt->assemble);
9331 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009332 if (ctxt->vctxt != NULL) {
9333 xmlSchemaFreeValidCtxt(ctxt->vctxt);
9334 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009335 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00009336 xmlFree(ctxt);
9337}
9338
9339/************************************************************************
9340 * *
9341 * Building the content models *
9342 * *
9343 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009344
Daniel Veillard4255d502002-04-16 15:50:10 +00009345/**
9346 * xmlSchemaBuildAContentModel:
9347 * @type: the schema type definition
9348 * @ctxt: the schema parser context
9349 * @name: the element name whose content is being built
9350 *
9351 * Generate the automata sequence needed for that type
9352 */
9353static void
9354xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009355 xmlSchemaParserCtxtPtr ctxt,
9356 const xmlChar * name)
9357{
Daniel Veillard4255d502002-04-16 15:50:10 +00009358 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009359 xmlGenericError(xmlGenericErrorContext,
9360 "Found unexpected type = NULL in %s content model\n",
9361 name);
9362 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009363 }
9364 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009365 case XML_SCHEMA_TYPE_ANY: {
9366 xmlAutomataStatePtr start, end;
9367 xmlSchemaWildcardPtr wild;
9368 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00009369
Daniel Veillardc0826a72004-08-10 14:17:33 +00009370 wild = type->attributeWildcard;
9371
9372 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009373 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009374 "Internal error: xmlSchemaBuildAContentModel, "
9375 "no wildcard on xsd:any.\n", NULL, NULL);
9376 return;
9377 }
9378
9379 start = ctxt->state;
9380 end = xmlAutomataNewState(ctxt->am);
9381
9382 if (type->maxOccurs == 1) {
9383 if (wild->any == 1) {
9384 /*
9385 * We need to add both transitions:
9386 *
9387 * 1. the {"*", "*"} for elements in a namespace.
9388 */
9389 ctxt->state =
9390 xmlAutomataNewTransition2(ctxt->am,
9391 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9392 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9393 /*
9394 * 2. the {"*"} for elements in no namespace.
9395 */
9396 ctxt->state =
9397 xmlAutomataNewTransition2(ctxt->am,
9398 start, NULL, BAD_CAST "*", NULL, type);
9399 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9400
9401 } else if (wild->nsSet != NULL) {
9402 ns = wild->nsSet;
9403 do {
9404 ctxt->state = start;
9405 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9406 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
9407 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9408 ns = ns->next;
9409 } while (ns != NULL);
9410
9411 } else if (wild->negNsSet != NULL) {
9412 xmlAutomataStatePtr deadEnd;
9413
9414 deadEnd = xmlAutomataNewState(ctxt->am);
9415 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9416 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9417 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9418 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9419 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9420 }
9421 } else {
9422 int counter;
9423 xmlAutomataStatePtr hop;
9424 int maxOccurs =
9425 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
9426 int minOccurs =
9427 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9428
9429 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9430 hop = xmlAutomataNewState(ctxt->am);
9431 if (wild->any == 1) {
9432 ctxt->state =
9433 xmlAutomataNewTransition2(ctxt->am,
9434 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9435 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9436 ctxt->state =
9437 xmlAutomataNewTransition2(ctxt->am,
9438 start, NULL, BAD_CAST "*", NULL, type);
9439 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9440 } else if (wild->nsSet != NULL) {
9441 ns = wild->nsSet;
9442 do {
9443 ctxt->state =
9444 xmlAutomataNewTransition2(ctxt->am,
9445 start, NULL, BAD_CAST "*", ns->value, type);
9446 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9447 ns = ns->next;
9448 } while (ns != NULL);
9449
9450 } else if (wild->negNsSet != NULL) {
9451 xmlAutomataStatePtr deadEnd;
9452
9453 deadEnd = xmlAutomataNewState(ctxt->am);
9454 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9455 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9456 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9457 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9458 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9459 }
9460 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
9461 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
9462 }
9463 if (type->minOccurs == 0) {
9464 xmlAutomataNewEpsilon(ctxt->am, start, end);
9465 }
9466 ctxt->state = end;
9467 break;
9468 }
9469 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009470 xmlAutomataStatePtr oldstate;
9471 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00009472
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009473 /*
9474 * IMPORTANT: This puts element declarations
9475 * (and never element decl. references) into the
9476 * automaton. This is crucial and should not be changed,
9477 * since validating functions rely now on it.
9478 */
9479 particle = (xmlSchemaElementPtr) type;
9480 if (particle->ref != NULL) {
9481 if (particle->refDecl == NULL) {
9482 /*
9483 * Skip content model creation if the reference
9484 * did not resolve to a declaration.
9485 */
9486 break;
9487 } else {
9488 /*
9489 * Referenced global element declaration.
9490 */
9491 elemDecl = particle->refDecl;
9492 }
9493 } else {
9494 /*
9495 * Anonymous element declaration.
9496 */
9497 elemDecl = particle;
9498 }
9499
9500 oldstate = ctxt->state;
9501
9502 if (particle->maxOccurs >= UNBOUNDED) {
9503 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009504 xmlAutomataStatePtr tmp;
9505 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009506
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009507 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009508 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009509 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009510 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009511 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00009512 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009513 xmlAutomataNewTransition2(ctxt->am,
9514 ctxt->state, NULL,
9515 elemDecl->name,
9516 elemDecl->targetNamespace,
9517 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009518 tmp = ctxt->state;
9519 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009520 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009521 ctxt->state =
9522 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009523 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00009524
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009525 } else {
9526 ctxt->state =
9527 xmlAutomataNewTransition2(ctxt->am,
9528 ctxt->state, NULL,
9529 elemDecl->name,
9530 elemDecl->targetNamespace,
9531 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009532 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9533 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009534 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009535 /* basically an elem* */
9536 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9537 ctxt->state);
9538 }
9539 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009540 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009541 xmlAutomataStatePtr tmp;
9542 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009543
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009544 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9545 oldstate, NULL);
9546 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009547 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009548 particle->minOccurs - 1,
9549 particle->maxOccurs - 1);
9550 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9551 ctxt->state,
9552 NULL,
9553 elemDecl->name,
9554 elemDecl->targetNamespace,
9555 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009556 tmp = ctxt->state;
9557 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009558 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009559 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009560 NULL, counter);
9561 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009562 /* basically an elem? */
9563 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009564 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009565 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00009566
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009567 } else {
9568 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9569 ctxt->state,
9570 NULL,
9571 elemDecl->name,
9572 elemDecl->targetNamespace,
9573 (xmlSchemaTypePtr) elemDecl);
9574 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009575 /* basically an elem? */
9576 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009577 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009578 }
9579 }
9580 break;
9581 }
9582 case XML_SCHEMA_TYPE_SEQUENCE:{
9583 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009584
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009585 /*
9586 * If max and min occurances are default (1) then
9587 * simply iterate over the subtypes
9588 */
9589 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
9590 subtypes = type->subtypes;
9591 while (subtypes != NULL) {
9592 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9593 subtypes = subtypes->next;
9594 }
9595 } else {
9596 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009597
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009598 if (type->maxOccurs >= UNBOUNDED) {
9599 if (type->minOccurs > 1) {
9600 xmlAutomataStatePtr tmp;
9601 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009602
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009603 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9604 oldstate,
9605 NULL);
9606 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009607
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009608 counter = xmlAutomataNewCounter(ctxt->am,
9609 type->
9610 minOccurs - 1,
9611 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009612
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009613 subtypes = type->subtypes;
9614 while (subtypes != NULL) {
9615 xmlSchemaBuildAContentModel(subtypes, ctxt,
9616 name);
9617 subtypes = subtypes->next;
9618 }
9619 tmp = ctxt->state;
9620 xmlAutomataNewCountedTrans(ctxt->am, tmp,
9621 oldstate, counter);
9622 ctxt->state =
9623 xmlAutomataNewCounterTrans(ctxt->am, tmp,
9624 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009625
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009626 } else {
9627 subtypes = type->subtypes;
9628 while (subtypes != NULL) {
9629 xmlSchemaBuildAContentModel(subtypes, ctxt,
9630 name);
9631 subtypes = subtypes->next;
9632 }
9633 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9634 oldstate);
9635 if (type->minOccurs == 0) {
9636 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9637 ctxt->state);
9638 }
9639 }
9640 } else if ((type->maxOccurs > 1)
9641 || (type->minOccurs > 1)) {
9642 xmlAutomataStatePtr tmp;
9643 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009644
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009645 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9646 oldstate,
9647 NULL);
9648 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00009649
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009650 counter = xmlAutomataNewCounter(ctxt->am,
9651 type->minOccurs -
9652 1,
9653 type->maxOccurs -
9654 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009655
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009656 subtypes = type->subtypes;
9657 while (subtypes != NULL) {
9658 xmlSchemaBuildAContentModel(subtypes, ctxt,
9659 name);
9660 subtypes = subtypes->next;
9661 }
9662 tmp = ctxt->state;
9663 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
9664 counter);
9665 ctxt->state =
9666 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
9667 counter);
9668 if (type->minOccurs == 0) {
9669 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9670 ctxt->state);
9671 }
Daniel Veillardb509f152002-04-17 16:28:10 +00009672
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009673 } else {
9674 subtypes = type->subtypes;
9675 while (subtypes != NULL) {
9676 xmlSchemaBuildAContentModel(subtypes, ctxt,
9677 name);
9678 subtypes = subtypes->next;
9679 }
9680 if (type->minOccurs == 0) {
9681 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9682 ctxt->state);
9683 }
9684 }
9685 }
9686 break;
9687 }
9688 case XML_SCHEMA_TYPE_CHOICE:{
9689 xmlSchemaTypePtr subtypes;
9690 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00009691
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009692 start = ctxt->state;
9693 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00009694
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009695 /*
9696 * iterate over the subtypes and remerge the end with an
9697 * epsilon transition
9698 */
9699 if (type->maxOccurs == 1) {
9700 subtypes = type->subtypes;
9701 while (subtypes != NULL) {
9702 ctxt->state = start;
9703 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9704 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9705 subtypes = subtypes->next;
9706 }
9707 } else {
9708 int counter;
9709 xmlAutomataStatePtr hop;
9710 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9711 UNBOUNDED : type->maxOccurs - 1;
9712 int minOccurs =
9713 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00009714
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009715 /*
9716 * use a counter to keep track of the number of transtions
9717 * which went through the choice.
9718 */
9719 counter =
9720 xmlAutomataNewCounter(ctxt->am, minOccurs,
9721 maxOccurs);
9722 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00009723
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009724 subtypes = type->subtypes;
9725 while (subtypes != NULL) {
9726 ctxt->state = start;
9727 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9728 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9729 subtypes = subtypes->next;
9730 }
9731 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9732 counter);
9733 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9734 counter);
9735 }
9736 if (type->minOccurs == 0) {
9737 xmlAutomataNewEpsilon(ctxt->am, start, end);
9738 }
9739 ctxt->state = end;
9740 break;
9741 }
9742 case XML_SCHEMA_TYPE_ALL:{
9743 xmlAutomataStatePtr start;
9744 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009745
Daniel Veillard3646d642004-06-02 19:19:14 +00009746 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009747 int lax;
9748
9749 subtypes = type->subtypes;
9750 if (subtypes == NULL)
9751 break;
9752 start = ctxt->state;
9753 while (subtypes != NULL) {
9754 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00009755 /*
9756 * the following 'if' was needed to fix bug 139897
9757 * not quite sure why it only needs to be done for
9758 * elements with a 'ref', but it seems to work ok.
9759 */
9760 if (subtypes->ref != NULL)
9761 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009762 elem = (xmlSchemaElementPtr) subtypes;
9763 /*
9764 * NOTE: The {max occurs} of all the particles in the
9765 * {particles} of the group must be 0 or 1.
9766 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009767 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009768 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
9769 ctxt->state,
9770 elem->name,
9771 elem->targetNamespace,
9772 1, 1, subtypes);
9773 } else if ((elem->minOccurs == 0) &&
9774 (elem->maxOccurs == 1)) {
9775
9776 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
9777 ctxt->state,
9778 elem->name,
9779 elem->targetNamespace,
9780 0,
9781 1,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009782 subtypes);
9783 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009784 /*
9785 * NOTE: if maxOccurs == 0 then no transition will be
9786 * created.
9787 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009788 subtypes = subtypes->next;
9789 }
9790 lax = type->minOccurs == 0;
9791 ctxt->state =
9792 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
9793 lax);
9794 break;
9795 }
9796 case XML_SCHEMA_TYPE_RESTRICTION:
9797 if (type->subtypes != NULL)
9798 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9799 break;
9800 case XML_SCHEMA_TYPE_EXTENSION:
9801 if (type->baseType != NULL) {
9802 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009803
9804 /*
9805 * TODO: Circular definitions will be checked at the
9806 * constraint level. So remove this when the complex type
9807 * constraints are implemented.
9808 */
Daniel Veillardf7627552004-04-22 07:15:40 +00009809 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009810 /* TODO: Change the error code. */
9811 xmlSchemaPCustomErr(ctxt,
9812 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
9813 NULL, type, type->node,
9814 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00009815 return;
9816 }
9817 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009818 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00009819 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009820 subtypes = type->subtypes;
9821 while (subtypes != NULL) {
9822 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9823 subtypes = subtypes->next;
9824 }
9825 } else if (type->subtypes != NULL)
9826 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9827 break;
9828 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00009829 /*
9830 * Handle model group definition references.
9831 * NOTE: type->subtypes is the referenced model grop definition;
9832 * and type->subtypes->subtypes is the model group (i.e. <all> or
9833 * <choice> or <sequence>).
9834 */
9835 if ((type->ref != NULL) && (type->subtypes != NULL) &&
9836 (type->subtypes->subtypes != NULL)) {
9837 xmlSchemaTypePtr modelGr;
9838 xmlAutomataStatePtr start, end;
9839
9840 modelGr = type->subtypes->subtypes;
9841 start = ctxt->state;
9842 end = xmlAutomataNewState(ctxt->am);
9843 if (type->maxOccurs == 1) {
9844 ctxt->state = start;
9845 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9846 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9847 } else {
9848 int counter;
9849 xmlAutomataStatePtr hop;
9850 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9851 UNBOUNDED : type->maxOccurs - 1;
9852 int minOccurs =
9853 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9854
9855 counter =
9856 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9857 hop = xmlAutomataNewState(ctxt->am);
9858 ctxt->state = start;
9859 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9860 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9861 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9862 counter);
9863 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9864 counter);
9865 }
9866 if (type->minOccurs == 0) {
9867 xmlAutomataNewEpsilon(ctxt->am, start, end);
9868 }
9869 ctxt->state = end;
9870 break;
9871 }
9872 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009873 case XML_SCHEMA_TYPE_COMPLEX:
9874 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
9875 if (type->subtypes != NULL)
9876 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9877 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00009878 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
9879 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009880 default:
9881 xmlGenericError(xmlGenericErrorContext,
9882 "Found unexpected type %d in %s content model\n",
9883 type->type, name);
9884 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009885 }
9886}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009887
Daniel Veillard4255d502002-04-16 15:50:10 +00009888/**
9889 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009890 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +00009891 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009892 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00009893 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009894 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +00009895 */
9896static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009897xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009898 xmlSchemaParserCtxtPtr ctxt,
9899 const xmlChar * name)
9900{
Daniel Veillard4255d502002-04-16 15:50:10 +00009901 xmlAutomataStatePtr start;
9902
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009903 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
9904 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
9905 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
9906 (type->contModel != NULL))
9907 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009908
9909#ifdef DEBUG_CONTENT
9910 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009911 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009912#endif
9913
Daniel Veillard4255d502002-04-16 15:50:10 +00009914 ctxt->am = xmlNewAutomata();
9915 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009916 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009917 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009918 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009919 }
9920 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009921 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00009922 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009923 type->contModel = xmlAutomataCompile(ctxt->am);
9924 if (type->contModel == NULL) {
9925 xmlSchemaPCustomErr(ctxt,
9926 XML_SCHEMAP_INTERNAL,
9927 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009928 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009929 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009930 xmlSchemaPCustomErr(ctxt,
9931 XML_SCHEMAP_NOT_DETERMINISTIC,
9932 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009933 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009934 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00009935 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00009936#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009937 xmlGenericError(xmlGenericErrorContext,
9938 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009939 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00009940#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00009941 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009942 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009943 xmlFreeAutomata(ctxt->am);
9944 ctxt->am = NULL;
9945}
9946
9947/**
9948 * xmlSchemaRefFixupCallback:
9949 * @elem: the schema element context
9950 * @ctxt: the schema parser context
9951 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00009952 * Resolves the references of an element declaration
9953 * or particle, which has an element declaration as it's
9954 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00009955 */
9956static void
9957xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009958 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009959 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009960 const xmlChar * context ATTRIBUTE_UNUSED,
9961 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00009962{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009963 if ((ctxt == NULL) || (elem == NULL) ||
9964 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009965 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009966 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00009967 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009968 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00009969
Daniel Veillardc0826a72004-08-10 14:17:33 +00009970 /*
9971 * TODO: Evaluate, what errors could occur if the declaration is not
9972 * found. It might be possible that the "typefixup" might crash if
9973 * no ref declaration was found.
9974 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009975 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009976 if (elemDecl == NULL) {
9977 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009978 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009979 NULL, (xmlSchemaTypePtr) elem, elem->node,
9980 "ref", elem->ref, elem->refNs,
9981 XML_SCHEMA_TYPE_ELEMENT, NULL);
9982 } else
9983 elem->refDecl = elemDecl;
9984 } else {
9985 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
9986 xmlSchemaTypePtr type;
9987
9988 /* (type definition) ... otherwise the type definition ·resolved·
9989 * to by the ·actual value· of the type [attribute] ...
9990 */
9991 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
9992 elem->namedTypeNs);
9993 if (type == NULL) {
9994 xmlSchemaPResCompAttrErr(ctxt,
9995 XML_SCHEMAP_SRC_RESOLVE,
9996 NULL, (xmlSchemaTypePtr) elem, elem->node,
9997 "type", elem->namedType, elem->namedTypeNs,
9998 XML_SCHEMA_TYPE_BASIC, "type definition");
9999 } else
10000 elem->subtypes = type;
10001 }
10002 if (elem->substGroup != NULL) {
10003 xmlSchemaElementPtr substHead;
10004
10005 /*
10006 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
10007 * substitutionGroup?
10008 */
10009 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010010 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010011 if (substHead == NULL) {
10012 xmlSchemaPResCompAttrErr(ctxt,
10013 XML_SCHEMAP_SRC_RESOLVE,
10014 NULL, (xmlSchemaTypePtr) elem, NULL,
10015 "substitutionGroup", elem->substGroup, elem->substGroupNs,
10016 XML_SCHEMA_TYPE_ELEMENT, NULL);
10017 } else {
10018 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
10019 /*
10020 * (type definition)...otherwise the {type definition} of the
10021 * element declaration ·resolved· to by the ·actual value· of
10022 * the substitutionGroup [attribute], if present
10023 */
10024 if (elem->subtypes == NULL)
10025 elem->subtypes = substHead->subtypes;
10026 }
10027 }
10028 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
10029 (elem->substGroup == NULL))
10030 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10031 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010032}
10033
William M. Bracke7091952004-05-11 15:09:58 +000010034/**
10035 * xmlSchemaParseListRefFixup:
10036 * @type: the schema type definition
10037 * @ctxt: the schema parser context
10038 *
10039 * Fixup of the itemType reference of the list type.
10040 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010041static void
William M. Bracke7091952004-05-11 15:09:58 +000010042xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010043{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010044
Daniel Veillard01fa6152004-06-29 17:04:39 +000010045 if (((type->base == NULL) &&
10046 (type->subtypes == NULL)) ||
10047 ((type->base != NULL) &&
10048 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010049 /*
10050 * src-list-itemType-or-simpleType
10051 * Either the itemType [attribute] or the <simpleType> [child] of
10052 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010053 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010054 /*
10055 * TODO: Move this to the parse function.
10056 */
10057 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010058 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010059 NULL, type, type->node,
10060 "The attribute 'itemType' and the <simpleType> child "
10061 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010062 } else if (type->base!= NULL) {
10063 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
10064 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010065 xmlSchemaPResCompAttrErr(ctxt,
10066 XML_SCHEMAP_SRC_RESOLVE,
10067 NULL, type, type->node,
10068 "itemType", type->base, type->baseNs,
10069 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010070 }
10071 }
10072 if ((type->subtypes != NULL) &&
10073 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
10074 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +000010075}
10076
10077/**
10078 * xmlSchemaParseUnionRefCheck:
10079 * @typeDecl: the schema type definition
10080 * @ctxt: the schema parser context
10081 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000010082 * Checks and builds the memberTypes of the union type.
10083 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000010084 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010085static int
William M. Bracke7091952004-05-11 15:09:58 +000010086xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +000010087 xmlSchemaParserCtxtPtr ctxt)
10088{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010089
Daniel Veillard01fa6152004-06-29 17:04:39 +000010090 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
10091 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000010092
Daniel Veillard01fa6152004-06-29 17:04:39 +000010093 /* 1 If the <union> alternative is chosen, then [Definition:]
10094 * define the explicit members as the type definitions ·resolved·
10095 * to by the items in the ·actual value· of the memberTypes [attribute],
10096 * if any, followed by the type definitions corresponding to the
10097 * <simpleType>s among the [children] of <union>, if any.
10098 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010099
Daniel Veillard01fa6152004-06-29 17:04:39 +000010100 if (type->type != XML_SCHEMA_TYPE_UNION)
10101 return (-1);
10102 if (ctxt->ctxtType == NULL) {
10103 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010104 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010105 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
10106 "available", NULL, NULL);
10107 return (-1);
10108 }
10109 /*
10110 * src-union-memberTypes-or-simpleTypes
10111 * Either the memberTypes [attribute] of the <union> element must
10112 * be non-empty or there must be at least one simpleType [child].
10113 */
10114 if ((type->base == NULL) &&
10115 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010116 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010117 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010118 NULL, NULL, type->node,
10119 "Either the attribute 'memberTypes' must be non-empty "
10120 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010121 }
10122
10123 ctxtType = ctxt->ctxtType;
10124 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010125 xmlAttrPtr attr;
10126 const xmlChar *cur, *end;
10127 xmlChar *tmp;
10128 const xmlChar *localName, *uri;
10129
10130 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010131 cur = type->base;
10132 do {
10133 while (IS_BLANK_CH(*cur))
10134 cur++;
10135 end = cur;
10136 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
10137 end++;
10138 if (end == cur)
10139 break;
10140 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010141 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
10142 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
10143 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010144 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010145 xmlSchemaPResCompAttrErr(ctxt,
10146 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
10147 NULL, NULL, type->node, "memberTypes", localName, uri,
10148 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010149 } else {
10150 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10151 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10152 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10153 if (link == NULL) {
10154 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10155 return (-1);
10156 }
10157 link->type = memberType;
10158 link->next = NULL;
10159 if (lastLink == NULL)
10160 ctxtType->memberTypes = link;
10161 else
10162 lastLink->next = link;
10163 lastLink = link;
10164 }
10165 xmlFree(tmp);
10166 cur = end;
10167 } while (*cur != 0);
10168 }
10169 /*
10170 * Add local simple types,
10171 */
10172 memberType = type->subtypes;
10173 while (memberType != NULL) {
10174 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10175 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10176 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10177 if (link == NULL) {
10178 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10179 return (-1);
10180 }
10181 link->type = memberType;
10182 link->next = NULL;
10183 if (lastLink == NULL)
10184 ctxtType->memberTypes = link;
10185 else
10186 lastLink->next = link;
10187 lastLink = link;
10188 memberType = memberType->next;
10189 }
10190 /*
10191 * The actual value is then formed by replacing any union type
10192 * definition in the ·explicit members· with the members of their
10193 * {member type definitions}, in order.
10194 */
10195 link = ctxtType->memberTypes;
10196 while (link != NULL) {
10197 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10198 subLink = link->type->memberTypes;
10199 if (subLink != NULL) {
10200 link->type = subLink->type;
10201 if (subLink->next != NULL) {
10202 lastLink = link->next;
10203 subLink = subLink->next;
10204 prevLink = link;
10205 while (subLink != NULL) {
10206 newLink = (xmlSchemaTypeLinkPtr)
10207 xmlMalloc(sizeof(xmlSchemaTypeLink));
10208 if (newLink == NULL) {
10209 xmlSchemaPErrMemory(ctxt, "allocating a type link",
10210 NULL);
10211 return (-1);
10212 }
10213 newLink->type = memberType;
10214 prevLink->next = newLink;
10215 prevLink = newLink;
10216 newLink->next = lastLink;
10217
10218 subLink = subLink->next;
10219 }
10220 }
10221 }
10222 }
10223 link = link->next;
10224 }
10225
10226 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000010227}
10228
Daniel Veillard4255d502002-04-16 15:50:10 +000010229/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010230 * xmlSchemaIsDerivedFromBuiltInType:
10231 * @ctxt: the schema parser context
10232 * @type: the type definition
10233 * @valType: the value type
10234 *
10235 *
10236 * Returns 1 if the type has the given value type, or
10237 * is derived from such a type.
10238 */
William M. Brack803812b2004-06-03 02:11:24 +000010239static int
Daniel Veillard3646d642004-06-02 19:19:14 +000010240xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
10241 xmlSchemaTypePtr type, int valType)
10242{
10243 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010244 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000010245 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010246 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000010247 return(1);
10248 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
10249 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
10250 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
10251 ((xmlSchemaAttributePtr) type)->subtypes, valType));
10252 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
10253 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
10254 if (type->baseType != NULL)
10255 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
10256 valType));
10257 } else if ((type->subtypes != NULL) &&
10258 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
10259 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10260 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
10261 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
10262 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
10263 valType));
10264 }
10265
10266 return (0);
10267}
10268
10269/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010270 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000010271 * @type: the simpleType definition
10272 *
10273 * Returns the primitive type of the given type or
10274 * NULL in case of error.
10275 */
10276static xmlSchemaTypePtr
10277xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
10278{
10279 while (type != NULL) {
10280 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
10281 return (type);
10282 type = type->baseType;
10283 }
10284
10285 return (NULL);
10286}
10287
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010288/**
10289 * xmlSchemaGetBuiltInTypeAncestor:
10290 * @type: the simpleType definition
10291 *
10292 * Returns the primitive type of the given type or
10293 * NULL in case of error.
10294 */
10295static xmlSchemaTypePtr
10296xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
10297{
10298 while (type != NULL) {
10299 if (type->type == XML_SCHEMA_TYPE_BASIC)
10300 return (type);
10301 type = type->baseType;
10302 }
10303
10304 return (NULL);
10305}
10306
Daniel Veillard01fa6152004-06-29 17:04:39 +000010307
10308/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010309 * xmlSchemaBuildAttributeUsesOwned:
10310 * @ctxt: the schema parser context
10311 * @type: the complex type definition
10312 * @cur: the attribute declaration list
10313 * @lastUse: the top of the attribute use list
10314 *
10315 * Builds the attribute uses list on the given complex type.
10316 * This one is supposed to be called by
10317 * xmlSchemaBuildAttributeValidation only.
10318 */
10319static int
10320xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
10321 xmlSchemaAttributePtr cur,
10322 xmlSchemaAttributeLinkPtr *uses,
10323 xmlSchemaAttributeLinkPtr *lastUse)
10324{
10325 xmlSchemaAttributeLinkPtr tmp;
10326 while (cur != NULL) {
10327 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10328 /*
10329 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
10330 * to by the ·actual value·s of the ref [attribute] of the
10331 * <attributeGroup> [children], if any."
10332 */
10333 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
10334 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
10335 lastUse) == -1) {
10336 return (-1);
10337 }
10338 } else {
10339 /* W3C: "1 The set of attribute uses corresponding to the
10340 * <attribute> [children], if any."
10341 */
10342 tmp = (xmlSchemaAttributeLinkPtr)
10343 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10344 if (tmp == NULL) {
10345 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
10346 return (-1);
10347 }
10348 tmp->attr = cur;
10349 tmp->next = NULL;
10350 if (*uses == NULL)
10351 *uses = tmp;
10352 else
10353 (*lastUse)->next = tmp;
10354 *lastUse = tmp;
10355 }
10356 cur = cur->next;
10357 }
10358 return (0);
10359}
10360
Daniel Veillard50355f02004-06-08 17:52:16 +000010361/**
10362 * xmlSchemaCloneWildcardNsConstraints:
10363 * @ctxt: the schema parser context
10364 * @dest: the destination wildcard
10365 * @source: the source wildcard
10366 *
10367 * Clones the namespace constraints of source
10368 * and assignes them to dest.
10369 * Returns -1 on internal error, 0 otherwise.
10370 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010371static int
10372xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
10373 xmlSchemaWildcardPtr *dest,
10374 xmlSchemaWildcardPtr source)
10375{
10376 xmlSchemaWildcardNsPtr cur, tmp, last;
10377
10378 if ((source == NULL) || (*dest == NULL))
10379 return(-1);
10380 (*dest)->any = source->any;
10381 cur = source->nsSet;
10382 last = NULL;
10383 while (cur != NULL) {
10384 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10385 if (tmp == NULL)
10386 return(-1);
10387 tmp->value = cur->value;
10388 if (last == NULL)
10389 (*dest)->nsSet = tmp;
10390 else
10391 last->next = tmp;
10392 last = tmp;
10393 cur = cur->next;
10394 }
10395 if ((*dest)->negNsSet != NULL)
10396 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
10397 if (source->negNsSet != NULL) {
10398 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10399 if ((*dest)->negNsSet == NULL)
10400 return(-1);
10401 (*dest)->negNsSet->value = source->negNsSet->value;
10402 } else
10403 (*dest)->negNsSet = NULL;
10404 return(0);
10405}
10406
Daniel Veillard50355f02004-06-08 17:52:16 +000010407/**
10408 * xmlSchemaUnionWildcards:
10409 * @ctxt: the schema parser context
10410 * @completeWild: the first wildcard
10411 * @curWild: the second wildcard
10412 *
10413 * Unions the namespace constraints of the given wildcards.
10414 * @completeWild will hold the resulting union.
10415 * Returns a positive error code on failure, -1 in case of an
10416 * internal error, 0 otherwise.
10417 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010418static int
10419xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
10420 xmlSchemaWildcardPtr completeWild,
10421 xmlSchemaWildcardPtr curWild)
10422{
10423 xmlSchemaWildcardNsPtr cur, curB, tmp;
10424
10425 /*
10426 * 1 If O1 and O2 are the same value, then that value must be the
10427 * value.
10428 */
10429 if ((completeWild->any == curWild->any) &&
10430 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10431 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10432
10433 if ((completeWild->negNsSet == NULL) ||
10434 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10435
10436 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010437 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010438
10439 /*
10440 * Check equality of sets.
10441 */
10442 cur = completeWild->nsSet;
10443 while (cur != NULL) {
10444 found = 0;
10445 curB = curWild->nsSet;
10446 while (curB != NULL) {
10447 if (cur->value == curB->value) {
10448 found = 1;
10449 break;
10450 }
10451 curB = curB->next;
10452 }
10453 if (!found)
10454 break;
10455 cur = cur->next;
10456 }
10457 if (found)
10458 return(0);
10459 } else
10460 return(0);
10461 }
10462 }
10463 /*
10464 * 2 If either O1 or O2 is any, then any must be the value
10465 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010466 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010467 if (completeWild->any == 0) {
10468 completeWild->any = 1;
10469 if (completeWild->nsSet != NULL) {
10470 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10471 completeWild->nsSet = NULL;
10472 }
10473 if (completeWild->negNsSet != NULL) {
10474 xmlFree(completeWild->negNsSet);
10475 completeWild->negNsSet = NULL;
10476 }
10477 }
Daniel Veillard50355f02004-06-08 17:52:16 +000010478 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010479 }
10480 /*
10481 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
10482 * then the union of those sets must be the value.
10483 */
10484 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10485 int found;
10486 xmlSchemaWildcardNsPtr start;
10487
10488 cur = curWild->nsSet;
10489 start = completeWild->nsSet;
10490 while (cur != NULL) {
10491 found = 0;
10492 curB = start;
10493 while (curB != NULL) {
10494 if (cur->value == curB->value) {
10495 found = 1;
10496 break;
10497 }
10498 curB = curB->next;
10499 }
10500 if (!found) {
10501 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10502 if (tmp == NULL)
10503 return (-1);
10504 tmp->value = cur->value;
10505 tmp->next = completeWild->nsSet;
10506 completeWild->nsSet = tmp;
10507 }
10508 cur = cur->next;
10509 }
10510
10511 return(0);
10512 }
10513 /*
10514 * 4 If the two are negations of different values (namespace names
10515 * or ·absent·), then a pair of not and ·absent· must be the value.
10516 */
10517 if ((completeWild->negNsSet != NULL) &&
10518 (curWild->negNsSet != NULL) &&
10519 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
10520 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000010521
10522 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010523 }
10524 /*
10525 * 5.
10526 */
10527 if (((completeWild->negNsSet != NULL) &&
10528 (completeWild->negNsSet->value != NULL) &&
10529 (curWild->nsSet != NULL)) ||
10530 ((curWild->negNsSet != NULL) &&
10531 (curWild->negNsSet->value != NULL) &&
10532 (completeWild->nsSet != NULL))) {
10533
10534 int nsFound, absentFound = 0;
10535
10536 if (completeWild->nsSet != NULL) {
10537 cur = completeWild->nsSet;
10538 curB = curWild->negNsSet;
10539 } else {
10540 cur = curWild->nsSet;
10541 curB = completeWild->negNsSet;
10542 }
10543 nsFound = 0;
10544 while (cur != NULL) {
10545 if (cur->value == NULL)
10546 absentFound = 1;
10547 else if (cur->value == curB->value)
10548 nsFound = 1;
10549 if (nsFound && absentFound)
10550 break;
10551 cur = cur->next;
10552 }
10553
10554 if (nsFound && absentFound) {
10555 /*
10556 * 5.1 If the set S includes both the negated namespace
10557 * name and ·absent·, then any must be the value.
10558 */
10559 completeWild->any = 1;
10560 if (completeWild->nsSet != NULL) {
10561 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10562 completeWild->nsSet = NULL;
10563 }
10564 if (completeWild->negNsSet != NULL) {
10565 xmlFree(completeWild->negNsSet);
10566 completeWild->negNsSet = NULL;
10567 }
10568 } else if (nsFound && (!absentFound)) {
10569 /*
10570 * 5.2 If the set S includes the negated namespace name
10571 * but not ·absent·, then a pair of not and ·absent· must
10572 * be the value.
10573 */
10574 if (completeWild->nsSet != NULL) {
10575 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10576 completeWild->nsSet = NULL;
10577 }
10578 if (completeWild->negNsSet == NULL) {
10579 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10580 if (completeWild->negNsSet == NULL)
10581 return (-1);
10582 }
10583 completeWild->negNsSet->value = NULL;
10584 } else if ((!nsFound) && absentFound) {
10585 /*
10586 * 5.3 If the set S includes ·absent· but not the negated
10587 * namespace name, then the union is not expressible.
10588 */
10589 xmlSchemaPErr(ctxt, completeWild->node,
10590 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010591 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010592 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010593 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010594 } else if ((!nsFound) && (!absentFound)) {
10595 /*
10596 * 5.4 If the set S does not include either the negated namespace
10597 * name or ·absent·, then whichever of O1 or O2 is a pair of not
10598 * and a namespace name must be the value.
10599 */
10600 if (completeWild->negNsSet == NULL) {
10601 if (completeWild->nsSet != NULL) {
10602 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10603 completeWild->nsSet = NULL;
10604 }
10605 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10606 if (completeWild->negNsSet == NULL)
10607 return (-1);
10608 completeWild->negNsSet->value = curWild->negNsSet->value;
10609 }
10610 }
10611 return (0);
10612 }
10613 /*
10614 * 6.
10615 */
10616 if (((completeWild->negNsSet != NULL) &&
10617 (completeWild->negNsSet->value == NULL) &&
10618 (curWild->nsSet != NULL)) ||
10619 ((curWild->negNsSet != NULL) &&
10620 (curWild->negNsSet->value == NULL) &&
10621 (completeWild->nsSet != NULL))) {
10622
10623 if (completeWild->nsSet != NULL) {
10624 cur = completeWild->nsSet;
10625 } else {
10626 cur = curWild->nsSet;
10627 }
10628 while (cur != NULL) {
10629 if (cur->value == NULL) {
10630 /*
10631 * 6.1 If the set S includes ·absent·, then any must be the
10632 * value.
10633 */
10634 completeWild->any = 1;
10635 if (completeWild->nsSet != NULL) {
10636 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10637 completeWild->nsSet = NULL;
10638 }
10639 if (completeWild->negNsSet != NULL) {
10640 xmlFree(completeWild->negNsSet);
10641 completeWild->negNsSet = NULL;
10642 }
10643 return (0);
10644 }
10645 cur = cur->next;
10646 }
10647 if (completeWild->negNsSet == NULL) {
10648 /*
10649 * 6.2 If the set S does not include ·absent·, then a pair of not
10650 * and ·absent· must be the value.
10651 */
10652 if (completeWild->nsSet != NULL) {
10653 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10654 completeWild->nsSet = NULL;
10655 }
10656 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10657 if (completeWild->negNsSet == NULL)
10658 return (-1);
10659 completeWild->negNsSet->value = NULL;
10660 }
10661 return (0);
10662 }
10663 return (0);
10664
10665}
10666
Daniel Veillard50355f02004-06-08 17:52:16 +000010667/**
10668 * xmlSchemaIntersectWildcards:
10669 * @ctxt: the schema parser context
10670 * @completeWild: the first wildcard
10671 * @curWild: the second wildcard
10672 *
10673 * Intersects the namespace constraints of the given wildcards.
10674 * @completeWild will hold the resulting intersection.
10675 * Returns a positive error code on failure, -1 in case of an
10676 * internal error, 0 otherwise.
10677 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010678static int
10679xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
10680 xmlSchemaWildcardPtr completeWild,
10681 xmlSchemaWildcardPtr curWild)
10682{
William M. Brack803812b2004-06-03 02:11:24 +000010683 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010684
10685 /*
10686 * 1 If O1 and O2 are the same value, then that value must be the
10687 * value.
10688 */
10689 if ((completeWild->any == curWild->any) &&
10690 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10691 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10692
10693 if ((completeWild->negNsSet == NULL) ||
10694 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10695
10696 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010697 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010698
10699 /*
10700 * Check equality of sets.
10701 */
10702 cur = completeWild->nsSet;
10703 while (cur != NULL) {
10704 found = 0;
10705 curB = curWild->nsSet;
10706 while (curB != NULL) {
10707 if (cur->value == curB->value) {
10708 found = 1;
10709 break;
10710 }
10711 curB = curB->next;
10712 }
10713 if (!found)
10714 break;
10715 cur = cur->next;
10716 }
10717 if (found)
10718 return(0);
10719 } else
10720 return(0);
10721 }
10722 }
10723 /*
10724 * 2 If either O1 or O2 is any, then the other must be the value.
10725 */
10726 if ((completeWild->any != curWild->any) && (completeWild->any)) {
10727 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10728 return(-1);
10729 return(0);
10730 }
10731 /*
10732 * 3 If either O1 or O2 is a pair of not and a value (a namespace
10733 * name or ·absent·) and the other is a set of (namespace names or
10734 * ·absent·), then that set, minus the negated value if it was in
10735 * the set, minus ·absent· if it was in the set, must be the value.
10736 */
10737 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
10738 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
10739 const xmlChar *neg;
10740
10741 if (completeWild->nsSet == NULL) {
10742 neg = completeWild->negNsSet->value;
10743 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10744 return(-1);
10745 } else
10746 neg = curWild->negNsSet->value;
10747 /*
10748 * Remove absent and negated.
10749 */
10750 prev = NULL;
10751 cur = completeWild->nsSet;
10752 while (cur != NULL) {
10753 if (cur->value == NULL) {
10754 if (prev == NULL)
10755 completeWild->nsSet = cur->next;
10756 else
10757 prev->next = cur->next;
10758 xmlFree(cur);
10759 break;
10760 }
10761 prev = cur;
10762 cur = cur->next;
10763 }
10764 if (neg != NULL) {
10765 prev = NULL;
10766 cur = completeWild->nsSet;
10767 while (cur != NULL) {
10768 if (cur->value == neg) {
10769 if (prev == NULL)
10770 completeWild->nsSet = cur->next;
10771 else
10772 prev->next = cur->next;
10773 xmlFree(cur);
10774 break;
10775 }
10776 prev = cur;
10777 cur = cur->next;
10778 }
10779 }
10780
10781 return(0);
10782 }
10783 /*
10784 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
10785 * then the intersection of those sets must be the value.
10786 */
10787 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10788 int found;
10789
10790 cur = completeWild->nsSet;
10791 prev = NULL;
10792 while (cur != NULL) {
10793 found = 0;
10794 curB = curWild->nsSet;
10795 while (curB != NULL) {
10796 if (cur->value == curB->value) {
10797 found = 1;
10798 break;
10799 }
10800 curB = curB->next;
10801 }
10802 if (!found) {
10803 if (prev == NULL)
10804 completeWild->nsSet = cur->next;
10805 else
10806 prev->next = cur->next;
10807 tmp = cur->next;
10808 xmlFree(cur);
10809 cur = tmp;
10810 continue;
10811 }
10812 prev = cur;
10813 cur = cur->next;
10814 }
10815
10816 return(0);
10817 }
10818 /* 5 If the two are negations of different namespace names,
10819 * then the intersection is not expressible
10820 */
10821 if ((completeWild->negNsSet != NULL) &&
10822 (curWild->negNsSet != NULL) &&
10823 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
10824 (completeWild->negNsSet->value != NULL) &&
10825 (curWild->negNsSet->value != NULL)) {
10826
10827 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010828 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010829 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010830 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010831 }
10832 /*
10833 * 6 If the one is a negation of a namespace name and the other
10834 * is a negation of ·absent·, then the one which is the negation
10835 * of a namespace name must be the value.
10836 */
10837 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
10838 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
10839 (completeWild->negNsSet->value == NULL)) {
10840 completeWild->negNsSet->value = curWild->negNsSet->value;
10841 }
10842 return(0);
10843}
10844
Daniel Veillard50355f02004-06-08 17:52:16 +000010845/**
10846 * xmlSchemaIsWildcardNsConstraintSubset:
10847 * @ctxt: the schema parser context
10848 * @wildA: the first wildcard
10849 * @wildB: the second wildcard
10850 *
10851 * Returns 1 if the namespace constraint of @wildA is an intensional
10852 * subset of @wildB, 0 otherwise.
10853 */
10854static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000010855xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
10856 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000010857{
Daniel Veillard3646d642004-06-02 19:19:14 +000010858
Daniel Veillard50355f02004-06-08 17:52:16 +000010859 /*
10860 * Schema Component Constraint: Wildcard Subset
10861 */
10862 /*
10863 * 1 super must be any.
10864 */
10865 if (wildB->any)
10866 return (1);
10867 /*
10868 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
10869 * 2.2 super must be a pair of not and the same value.
10870 */
10871 if ((wildA->negNsSet != NULL) &&
10872 (wildB->negNsSet != NULL) &&
10873 (wildA->negNsSet->value == wildA->negNsSet->value))
10874 return (1);
10875 /*
10876 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
10877 */
10878 if (wildA->nsSet != NULL) {
10879 /*
10880 * 3.2.1 super must be the same set or a superset thereof.
10881 */
10882 if (wildB->nsSet != NULL) {
10883 xmlSchemaWildcardNsPtr cur, curB;
10884 int found = 0;
10885
10886 cur = wildA->nsSet;
10887 while (cur != NULL) {
10888 found = 0;
10889 curB = wildB->nsSet;
10890 while (curB != NULL) {
10891 if (cur->value == curB->value) {
10892 found = 1;
10893 break;
10894 }
10895 curB = curB->next;
10896 }
10897 if (!found)
10898 return (0);
10899 cur = cur->next;
10900 }
10901 if (found)
10902 return (1);
10903 } else if (wildB->negNsSet != NULL) {
10904 xmlSchemaWildcardNsPtr cur;
10905 /*
10906 * 3.2.2 super must be a pair of not and a namespace name or
10907 * ·absent· and that value must not be in sub's set.
10908 */
10909 cur = wildA->nsSet;
10910 while (cur != NULL) {
10911 if (cur->value == wildB->negNsSet->value)
10912 return (0);
10913 cur = cur->next;
10914 }
10915 return (1);
10916 }
10917 }
10918 return (0);
10919}
10920
10921/**
10922 * xmlSchemaBuildCompleteAttributeWildcard:
10923 * @ctxt: the schema parser context
10924 * @attrs: the attribute list
10925 * @completeWild: the resulting complete wildcard
10926 *
10927 * Returns -1 in case of an internal error, 0 otherwise.
10928 */
10929static int
10930xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
10931 xmlSchemaAttributePtr attrs,
10932 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000010933{
10934 while (attrs != NULL) {
10935 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10936 xmlSchemaAttributeGroupPtr group;
10937
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010938 group = (xmlSchemaAttributeGroupPtr) attrs;
10939 /*
10940 * Handle attribute group references.
10941 */
10942 if (group->ref != NULL) {
10943 if (group->refItem == NULL) {
10944 /*
10945 * TODO: Should we raise a warning here?
10946 */
10947 /*
10948 * The referenced attribute group definition could not
10949 * be resolved beforehand, so skip.
10950 */
10951 attrs = attrs->next;
10952 continue;
10953 } else
10954 group = group->refItem;
10955 }
10956 /*
10957 * For every attribute group definition, an intersected wildcard
10958 * will be created (assumed that a wildcard exists on the
10959 * particular attr. gr. def. or on any contained attr. gr. def
10960 * at all).
10961 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
10962 * that the intersection will be performed only once.
10963 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010964 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
10965 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010966 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10967 group->attributes, &group->attributeWildcard) == -1)
10968 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010969 }
10970 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
10971 }
10972 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010973 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010974 /*
10975 * Copy the first encountered wildcard as context, except for the annotation.
10976 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010977 *completeWild = xmlSchemaAddWildcard(ctxt);
10978 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
10979 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
10980 completeWild, group->attributeWildcard) == -1)
10981 return (-1);
10982 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000010983 /*
10984 * Although the complete wildcard might not correspond to any
10985 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010986 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000010987 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010988 (*completeWild)->node = group->attributeWildcard->node;
10989
10990 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
10991 xmlSchemaFreeWildcard(*completeWild);
10992 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010993 }
10994 }
10995 }
10996 attrs = attrs->next;
10997 }
10998
Daniel Veillard50355f02004-06-08 17:52:16 +000010999 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011000}
11001
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011002static int
11003xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
11004 int *fixed,
11005 const xmlChar **value,
11006 xmlSchemaValPtr *val)
11007{
11008 *fixed = 0;
11009 *value = NULL;
11010 if (val != 0)
11011 *val = NULL;
11012
11013 if (item->defValue == NULL)
11014 item = item->refDecl;
11015
11016 if (item == NULL)
11017 return (0);
11018
11019 if (item->defValue != NULL) {
11020 *value = item->defValue;
11021 if (val != 0)
11022 *val = item->defVal;
11023 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
11024 *fixed = 1;
11025 return (1);
11026 }
11027 return (0);
11028}
Daniel Veillard3646d642004-06-02 19:19:14 +000011029/**
11030 * xmlSchemaMatchesWildcardNs:
11031 * @wild: the wildcard
11032 * @ns: the namespace
11033 *
11034 *
11035 * Returns 1 if the given namespace matches the wildcard,
11036 * 0 otherwise.
11037 */
11038static int
11039xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
11040{
11041 if (wild == NULL)
11042 return(0);
11043
11044 if (wild->any)
11045 return(1);
11046 else if (wild->nsSet != NULL) {
11047 xmlSchemaWildcardNsPtr cur;
11048
11049 cur = wild->nsSet;
11050 while (cur != NULL) {
11051 if (xmlStrEqual(cur->value, ns))
11052 return(1);
11053 cur = cur->next;
11054 }
11055 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
11056 (!xmlStrEqual(wild->negNsSet->value, ns)))
11057 return(1);
11058
11059 return(0);
11060}
11061
11062/**
11063 * xmlSchemaBuildAttributeValidation:
11064 * @ctxt: the schema parser context
11065 * @type: the complex type definition
11066 *
11067 *
11068 * Builds the wildcard and the attribute uses on the given complex type.
11069 * Returns -1 if an internal error occurs, 0 otherwise.
11070 */
11071static int
11072xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
11073{
11074 xmlSchemaTypePtr baseType = NULL;
11075 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000011076 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000011077 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011078 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000011079 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011080 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011081 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011082
Daniel Veillard01fa6152004-06-29 17:04:39 +000011083 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011084 /*
11085 * Complex Type Definition with complex content Schema Component.
11086 *
11087 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011088 * TODO: Add checks for absent referenced attribute declarations and
11089 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000011090 */
11091 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011092 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011093 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000011094 "attribute uses already builded.\n",
11095 NULL, NULL);
11096 return (-1);
11097 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011098 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011099 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011100 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011101 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011102 type->name, NULL);
11103 return (-1);
11104 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011105 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011106 if (baseType == anyType)
11107 baseIsAnyType = 1;
11108 /*
11109 * Inherit the attribute uses of the base type.
11110 */
11111 /*
11112 * NOTE: It is allowed to "extend" the anyType complex type.
11113 */
11114 if (!baseIsAnyType) {
11115 if (baseType != NULL) {
11116 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
11117 tmp = (xmlSchemaAttributeLinkPtr)
11118 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11119 if (tmp == NULL) {
11120 xmlSchemaPErrMemory(ctxt,
11121 "building attribute uses of complexType", NULL);
11122 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011123 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011124 tmp->attr = cur->attr;
11125 tmp->next = NULL;
11126 if (type->attributeUses == NULL) {
11127 type->attributeUses = tmp;
11128 } else
11129 lastBaseUse->next = tmp;
11130 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011131 }
11132 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011133 }
11134 if ((type->subtypes != NULL) &&
11135 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11136 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011137 /*
11138 * type --> (<simpleContent>|<complexContent>)
11139 * --> (<restriction>|<extension>) --> attributes
11140 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011141 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011142 } else {
11143 /* Short hand form of the complexType. */
11144 attrs = type->attributes;
11145 }
11146 /*
11147 * Handle attribute wildcards.
11148 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011149 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11150 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011151 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011152 * NOTE: During the parse time, the wildcard is created on the complexType
11153 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011154 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011155 if (err == -1) {
11156 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
11157 "Internal error: xmlSchemaBuildAttributeValidation: "
11158 "failed to build an intersected attribute wildcard.\n",
11159 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011160 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011161 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011162
11163 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
11164 ((baseIsAnyType) ||
11165 ((baseType != NULL) &&
11166 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11167 (baseType->attributeWildcard != NULL)))) {
11168 if (type->attributeWildcard != NULL) {
11169 /*
11170 * Union the complete wildcard with the base wildcard.
11171 */
11172 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
11173 baseType->attributeWildcard) == -1)
11174 return (-1);
11175 } else {
11176 /*
11177 * Just inherit the wildcard.
11178 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011179 /*
11180 * NOTE: This is the only case where an attribute
11181 * wildcard is shared.
11182 */
11183 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
11184 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011185 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000011186 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011187 }
11188
11189 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11190 if (type->attributeWildcard != NULL) {
11191 /*
11192 * Derivation Valid (Restriction, Complex)
11193 * 4.1 The {base type definition} must also have one.
11194 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011195 if (baseType->attributeWildcard == NULL) {
11196 xmlSchemaPCustomErr(ctxt,
11197 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
11198 NULL, type, NULL,
11199 "The type has an attribute wildcard, "
11200 "but the base type %s does not have one",
11201 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11202 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011203 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011204 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011205 type->attributeWildcard, baseType->attributeWildcard) == 0) {
11206 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011207 xmlSchemaPCustomErr(ctxt,
11208 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
11209 NULL, type, NULL,
11210 "The attribute wildcard is not a valid "
11211 "subset of the wildcard in the base type %s",
11212 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11213 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011214 return (1);
11215 }
11216 /* 4.3 Unless the {base type definition} is the ·ur-type
11217 * definition·, the complex type definition's {attribute
11218 * wildcard}'s {process contents} must be identical to or
11219 * stronger than the {base type definition}'s {attribute
11220 * wildcard}'s {process contents}, where strict is stronger
11221 * than lax is stronger than skip.
11222 */
11223 if ((type->baseType != anyType) &&
11224 (type->attributeWildcard->processContents <
11225 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011226 xmlSchemaPCustomErr(ctxt,
11227 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
11228 NULL, type, NULL,
11229 "The 'process contents' of the attribute wildcard is weaker than "
11230 "the one in the base type %s",
11231 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11232 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011233 return (1);
11234 }
11235 }
11236 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11237 /*
11238 * Derivation Valid (Extension)
11239 * At this point the type and the base have both, either
11240 * no wildcard or a wildcard.
11241 */
11242 if ((baseType->attributeWildcard != NULL) &&
11243 (baseType->attributeWildcard != type->attributeWildcard)) {
11244 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011245 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011246 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011247 xmlSchemaPCustomErr(ctxt,
11248 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
11249 NULL, type, NULL,
11250 "The attribute wildcard is not a valid "
11251 "superset of the one in the base type %s",
11252 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11253 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011254 return (1);
11255 }
11256 }
11257 }
11258
Daniel Veillard3646d642004-06-02 19:19:14 +000011259 /*
11260 * Gather attribute uses defined by this type.
11261 */
11262 if (attrs != NULL) {
11263 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
11264 &uses, &lastUse) == -1) {
11265 return (-1);
11266 }
11267 }
11268 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
11269 * "Two distinct attribute declarations in the {attribute uses} must
11270 * not have identical {name}s and {target namespace}s."
11271 *
11272 * For "extension" this is done further down.
11273 */
11274 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
11275 cur = uses;
11276 while (cur != NULL) {
11277 tmp = cur->next;
11278 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011279 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11280 xmlSchemaGetAttrName(tmp->attr))) &&
11281 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11282 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
11283
11284 xmlSchemaPAttrUseErr(ctxt,
11285 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11286 NULL, type, NULL, cur->attr,
11287 "Duplicate attribute use %s specified",
11288 xmlSchemaFormatNsUriLocal(&str,
11289 xmlSchemaGetAttrTargetNsURI(tmp->attr),
11290 xmlSchemaGetAttrName(tmp->attr))
11291 );
11292 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011293 break;
11294 }
11295 tmp = tmp->next;
11296 }
11297 cur = cur->next;
11298 }
11299 }
11300 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11301 /*
11302 * Derive by restriction.
11303 */
11304 if (baseIsAnyType) {
11305 type->attributeUses = uses;
11306 } else {
11307 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011308 const xmlChar *bEffValue;
11309 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000011310
11311 cur = uses;
11312 while (cur != NULL) {
11313 found = 0;
11314 base = type->attributeUses;
11315 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011316 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11317 xmlSchemaGetAttrName(base->attr)) &&
11318 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
11319 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011320
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011321 found = 1;
11322
Daniel Veillard3646d642004-06-02 19:19:14 +000011323 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
11324 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11325 /*
11326 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000011327 */
11328 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011329 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011330 NULL, type, NULL, cur->attr,
11331 "The 'optional' use is inconsistent with a matching "
11332 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011333 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
11334 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11335 /*
11336 * derivation-ok-restriction 3
11337 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011338 xmlSchemaPCustomErr(ctxt,
11339 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
11340 NULL, type, NULL,
11341 "A matching attribute use for the 'required' "
11342 "attribute use %s of the base type is missing",
11343 xmlSchemaFormatNsUriLocal(&str,
11344 xmlSchemaGetAttrTargetNsURI(base->attr),
11345 xmlSchemaGetAttrName(base->attr)));
11346 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011347 } else {
11348 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011349 * 2.1.3 [Definition:] Let the effective value
11350 * constraint of an attribute use be its {value
11351 * constraint}, if present, otherwise its {attribute
11352 * declaration}'s {value constraint} .
11353 */
11354 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11355 &bEffValue, 0);
11356 /*
11357 * 2.1.3 ... one of the following must be true
11358 *
11359 * 2.1.3.1 B's ·effective value constraint· is
11360 * ·absent· or default.
11361 */
11362 if ((bEffValue != NULL) &&
11363 (effFixed == 1)) {
11364 const xmlChar *rEffValue = NULL;
11365
11366 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11367 &rEffValue, 0);
11368 /*
11369 * 2.1.3.2 R's ·effective value constraint· is
11370 * fixed with the same string as B's.
11371 */
11372 if ((effFixed == 0) ||
11373 (! xmlStrEqual(rEffValue, bEffValue))) {
11374 xmlSchemaPAttrUseErr(ctxt,
11375 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
11376 NULL, type, NULL, cur->attr,
11377 "The effective value constraint of the "
11378 "attribute use is inconsistent with "
11379 "its correspondent of the base type",
11380 NULL);
11381 }
11382 }
11383 /*
11384 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
11385 */
11386 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011387 * Override the attribute use.
11388 */
11389 base->attr = cur->attr;
11390 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011391
Daniel Veillard3646d642004-06-02 19:19:14 +000011392 break;
11393 }
11394 base = base->next;
11395 }
11396
11397 if (!found) {
11398 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11399 /*
11400 * derivation-ok-restriction 2.2
11401 */
11402 if ((type->attributeWildcard != NULL) &&
11403 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
11404 cur->attr->targetNamespace))
11405 found = 1;
11406
11407 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011408 xmlSchemaPAttrUseErr(ctxt,
11409 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
11410 NULL, type, NULL, cur->attr,
11411 "Neither a matching attribute use, "
11412 "nor a matching wildcard in the base type does exist",
11413 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011414 } else {
11415 /*
11416 * Add the attribute use.
11417 *
11418 * Note that this may lead to funny derivation error reports, if
11419 * multiple equal attribute uses exist; but this is not
11420 * allowed anyway, and it will be reported beforehand.
11421 */
11422 tmp = cur;
11423 if (prev != NULL)
11424 prev->next = cur->next;
11425 else
11426 uses = cur->next;
11427 cur = cur->next;
11428 if (type->attributeUses == NULL) {
11429 type->attributeUses = tmp;
11430 } else
11431 lastBaseUse->next = tmp;
11432 lastBaseUse = tmp;
11433
11434 continue;
11435 }
11436 }
11437 }
11438 prev = cur;
11439 cur = cur->next;
11440 }
11441 if (uses != NULL)
11442 xmlSchemaFreeAttributeUseList(uses);
11443 }
11444 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11445 /*
11446 * The spec allows only appending, and not other kinds of extensions.
11447 *
11448 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
11449 */
11450 if (uses != NULL) {
11451 if (type->attributeUses == NULL) {
11452 type->attributeUses = uses;
11453 } else
11454 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011455 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011456 } else {
11457 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000011458 * Derive implicitely from the ur-type.
11459 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011460 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011461 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011462 /*
11463 * 3.4.6 -> Complex Type Definition Properties Correct
11464 */
11465 if (type->attributeUses != NULL) {
11466 cur = type->attributeUses;
11467 prev = NULL;
11468 while (cur != NULL) {
11469 /*
11470 * 4. Two distinct attribute declarations in the {attribute uses} must
11471 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000011472 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011473 * Note that this was already done for "restriction" and types derived from
11474 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000011475 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011476 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11477 tmp = cur->next;
11478 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011479 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11480 xmlSchemaGetAttrName(tmp->attr))) &&
11481 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11482 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011483
Daniel Veillardc0826a72004-08-10 14:17:33 +000011484 xmlSchemaPAttrUseErr(ctxt,
11485 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11486 NULL, type, NULL, tmp->attr,
11487 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011488 break;
11489 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011490 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011491 }
11492 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011493 /*
11494 * 5. Two distinct attribute declarations in the {attribute uses} must
11495 * not have {type definition}s which are or are derived from ID.
11496 */
11497 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000011498 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011499 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011500 xmlSchemaPAttrUseErr(ctxt,
11501 XML_SCHEMAP_CT_PROPS_CORRECT_5,
11502 NULL, type, NULL, cur->attr,
11503 "There must not exist more than one attribute use, "
11504 "declared of type 'ID' or derived from it",
11505 NULL);
11506 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000011507 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011508 id = cur;
11509 }
11510 /*
11511 * Remove "prohibited" attribute uses. The reason this is done at this late
11512 * stage is to be able to catch dublicate attribute uses. So we had to keep
11513 * prohibited uses in the list as well.
11514 */
11515 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11516 tmp = cur;
11517 if (prev == NULL)
11518 type->attributeUses = cur->next;
11519 else
11520 prev->next = cur->next;
11521 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011522 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000011523 } else {
11524 prev = cur;
11525 cur = cur->next;
11526 }
11527 }
11528 }
11529 /*
11530 * TODO: This check should be removed if we are 100% sure of
11531 * the base type attribute uses already being built.
11532 */
11533 if ((baseType != NULL) && (!baseIsAnyType) &&
11534 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11535 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011536 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011537 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011538 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011539 baseType->name, NULL);
11540 }
11541 return (0);
11542}
11543
11544/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000011545 * xmlSchemaTypeFinalContains:
11546 * @schema: the schema
11547 * @type: the type definition
11548 * @final: the final
11549 *
11550 * Evaluates if a type definition contains the given "final".
11551 * This does take "finalDefault" into account as well.
11552 *
11553 * Returns 1 if the type does containt the given "final",
11554 * 0 otherwise.
11555 */
11556static int
11557xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
11558{
11559 int tfinal = final, tflags = type->flags;
11560
11561 if (type == NULL)
11562 return (0);
11563 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
11564 switch (final) {
11565 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
11566 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
11567 break;
11568 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
11569 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
11570 break;
11571 case XML_SCHEMAS_TYPE_FINAL_LIST:
11572 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
11573 break;
11574 case XML_SCHEMAS_TYPE_FINAL_UNION:
11575 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
11576 break;
11577 }
11578 tflags = schema->flags;
11579 }
11580 if (tflags & tfinal)
11581 return (1);
11582 else
11583 return (0);
11584
11585}
11586
11587/**
11588 * xmlSchemaGetUnionSimpleTypeMemberTypes:
11589 * @type: the Union Simple Type
11590 *
11591 * Returns a list of member types of @type if existing,
11592 * returns NULL otherwise.
11593 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011594static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000011595xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
11596{
11597 while (type != NULL) {
11598 if (type->memberTypes != NULL)
11599 return (type->memberTypes);
11600 else
11601 type = type->baseType;
11602 }
11603 return (NULL);
11604}
11605
11606/**
11607 * xmlSchemaGetListSimpleTypeItemType:
11608 * @type: the simple type definition
11609 *
11610 * Returns the item type definition of the list simple type.
11611 */
11612static xmlSchemaTypePtr
11613xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
11614{
11615 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
11616 return (NULL);
11617 /*
11618 * Note: In libxml2, the built-in types do not reflect
11619 * the datatype hierarchy (yet?) - we have to treat them
11620 * in a special way.
11621 */
11622 if (type->type == XML_SCHEMA_TYPE_BASIC)
11623 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
11624 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
11625 /* 1 If the <list> alternative is chosen, then the type
11626 * definition ·resolved· to by the ·actual value· of the
11627 * itemType [attribute] of <list>, if present, otherwise
11628 * the type definition corresponding to the <simpleType>
11629 * among the [children] of <list>.
11630 */
11631 return (type->subtypes->subtypes);
11632 else {
11633 /* 2 If the <restriction> option is chosen, then the
11634 * {item type definition} of the {base type definition}.
11635 */
11636 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
11637 }
11638}
11639
11640/**
11641 * xmlSchemaCheckCOSSTDerivedOK:
11642 * @type: the derived simple type definition
11643 * @baseType: the base type definition
11644 *
11645 * Checks wheter @type can be validly
11646 * derived from @baseType.
11647 *
11648 * Returns 0 on success, an positive error code otherwise.
11649 */
11650static int
11651xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
11652 xmlSchemaTypePtr type,
11653 xmlSchemaTypePtr baseType,
11654 int subset)
11655{
11656 /*
11657 * Schema Component Constraint: Type Derivation OK (Simple)
11658 *
11659 *
11660 * 1 They are the same type definition.
11661 * TODO: The identy check might have to be more complex than this.
11662 */
11663 if (type == baseType)
11664 return (0);
11665 /*
11666 * 2.1 restriction is not in the subset, or in the {final}
11667 * of its own {base type definition};
11668 */
11669 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
11670 (xmlSchemaTypeFinalContains(schema,
11671 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
11672 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
11673 }
11674 /* 2.2 */
11675 if (type->baseType == baseType) {
11676 /*
11677 * 2.2.1 D's ·base type definition· is B.
11678 */
11679 return (0);
11680 }
11681 /*
11682 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
11683 * and is validly derived from B given the subset, as defined by this
11684 * constraint.
11685 */
11686 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
11687 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
11688 return (0);
11689 }
11690 /*
11691 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
11692 * definition·.
11693 */
11694 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
11695 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
11696 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
11697 return (0);
11698 }
11699 /*
11700 * 2.2.4 B's {variety} is union and D is validly derived from a type
11701 * definition in B's {member type definitions} given the subset, as
11702 * defined by this constraint.
11703 *
11704 * NOTE: This seems not to involve built-in types, since there is no
11705 * built-in Union Simple Type.
11706 */
11707 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11708 xmlSchemaTypeLinkPtr cur;
11709
11710 cur = baseType->memberTypes;
11711 while (cur != NULL) {
11712 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
11713 cur->type, subset) == 0)
11714 return (0);
11715 cur = cur->next;
11716 }
11717 }
11718
11719 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
11720}
11721
11722
11723/**
11724 * xmlSchemaCheckSTPropsCorrect:
11725 * @ctxt: the schema parser context
11726 * @type: the simple type definition
11727 *
11728 * Checks st-props-correct.
11729 *
11730 * Returns 0 if the properties are correct,
11731 * if not, a positive error code and -1 on internal
11732 * errors.
11733 */
11734static int
11735xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
11736 xmlSchemaTypePtr type)
11737{
11738 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
11739 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011740 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011741
Daniel Veillardc0826a72004-08-10 14:17:33 +000011742 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011743 /*
11744 * Schema Component Constraint: Simple Type Definition Properties Correct
11745 *
11746 * NOTE: This is somehow redundant, since we actually built a simple type
11747 * to have all the needed information; this acts as an self test.
11748 */
11749 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11750 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11751 /*
11752 * TODO: 1 The values of the properties of a simple type definition must be as
11753 * described in the property tableau in Datatype definition, modulo the
11754 * impact of Missing Sub-components (§5.3).
11755 */
11756 /* Base type: If the datatype has been ·derived· by ·restriction·
11757 * then the Simple Type Definition component from which it is ·derived·,
11758 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
11759 */
11760 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011761 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011762 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011763 NULL, type, NULL,
11764 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011765 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11766 }
11767 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
11768 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
11769 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011770 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011771 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011772 NULL, type, NULL,
11773 "The base type %s is not a simple type",
11774 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11775 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011776 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11777 }
11778 if ((baseType != anySimpleType) &&
11779 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011780 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011781 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011782 NULL, type, NULL,
11783 "A type, derived by list or union, must have"
11784 "the simple ur-type definition as base type, not %s",
11785 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11786 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011787 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11788 }
11789 /*
11790 * Variety: One of {atomic, list, union}.
11791 */
11792 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11793 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
11794 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011795 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011796 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011797 NULL, type, NULL,
11798 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011799 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11800 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011801 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011802
11803 /*
11804 * 2 All simple type definitions must be derived ultimately from the ·simple
11805 * ur-type definition (so· circular definitions are disallowed). That is, it
11806 * must be possible to reach a built-in primitive datatype or the ·simple
11807 * ur-type definition· by repeatedly following the {base type definition}.
11808 */
11809 baseType = type->baseType;
11810 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
11811 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11812 xmlSchemaTypeFixup(baseType, ctxt, NULL);
11813 if (baseType == anySimpleType)
11814 break;
11815 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011816 xmlSchemaPCustomErr(ctxt,
11817 XML_SCHEMAP_ST_PROPS_CORRECT_2,
11818 NULL, type, NULL,
11819 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011820 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
11821 }
11822 baseType = baseType->baseType;
11823 }
11824 /*
11825 * 3 The {final} of the {base type definition} must not contain restriction.
11826 */
11827 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
11828 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011829 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011830 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011831 NULL, type, NULL,
11832 "The 'final' of its base type %s must not contain "
11833 "'restriction'",
11834 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11835 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011836 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
11837 }
11838 return (0);
11839}
11840
11841/**
11842 * xmlSchemaCheckDerivationValidSimpleRestriction:
11843 * @ctxt: the schema parser context
11844 * @type: the simple type definition
11845 *
11846 * Checks if the given @type (simpleType) is derived
11847 * validly by restriction.
11848 *
11849 * Returns -1 on internal errors, 0 if the type is validly derived,
11850 * a positive error code otherwise.
11851 */
11852static int
11853xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011854 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011855{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011856 xmlChar *str = NULL;
11857
11858 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011859
11860 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
11861 xmlSchemaPErr(ctxt, type->node,
11862 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011863 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
11864 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011865 type->name, NULL);
11866 return (-1);
11867 }
11868
11869 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
11870 xmlSchemaTypePtr primitive;
11871 /*
11872 * 1.1 The {base type definition} must be an atomic simple
11873 * type definition or a built-in primitive datatype.
11874 */
11875 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011876 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011877 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011878 NULL, type, NULL,
11879 "The base type %s is not an atomic simple type",
11880 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11881 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011882 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
11883 }
11884 /* 1.2 The {final} of the {base type definition} must not contain
11885 * restriction.
11886 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011887 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011888 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11889 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011890 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011891 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011892 NULL, type, NULL,
11893 "The final of its base type %s must not contain 'restriction'",
11894 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11895 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011896 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
11897 }
11898
11899 /*
11900 * 1.3.1 DF must be an allowed constraining facet for the {primitive
11901 * type definition}, as specified in the appropriate subsection of 3.2
11902 * Primitive datatypes.
11903 */
11904 if (type->facets != NULL) {
11905 xmlSchemaFacetPtr facet;
11906 int ok = 1;
11907
11908 primitive = xmlSchemaGetPrimitiveType(type);
11909 if (primitive == NULL) {
11910 xmlSchemaPErr(ctxt, type->node,
11911 XML_ERR_INTERNAL_ERROR,
11912 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011913 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011914 type->name, NULL);
11915 return (-1);
11916 }
11917 facet = type->facets;
11918 do {
11919 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011920 ok = 0;
11921 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011922 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011923 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011924 }
11925 facet = facet->next;
11926 } while (facet != NULL);
11927 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000011928 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011929 }
11930 /*
11931 * TODO: 1.3.2 (facet derivation)
11932 */
11933 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11934 xmlSchemaTypePtr itemType = NULL;
11935
11936 itemType = xmlSchemaGetListSimpleTypeItemType(type);
11937 if (itemType == NULL) {
11938 xmlSchemaPErr(ctxt, type->node,
11939 XML_ERR_INTERNAL_ERROR,
11940 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011941 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011942 type->name, NULL);
11943 return (-1);
11944 }
11945 /*
11946 * 2.1 The {item type definition} must have a {variety} of atomic or
11947 * union (in which case all the {member type definitions}
11948 * must be atomic).
11949 */
11950 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11951 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011952 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011953 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011954 NULL, type, NULL,
11955 "The item type %s must have a variety of atomic or union",
11956 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11957 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011958 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11959 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11960 xmlSchemaTypeLinkPtr member;
11961
11962 member = itemType->memberTypes;
11963 while (member != NULL) {
11964 if ((member->type->flags &
11965 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011966 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011967 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011968 NULL, type, NULL,
11969 "The item type is a union type, but the "
11970 "member type %s of this item type is not atomic",
11971 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11972 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011973 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11974 }
11975 member = member->next;
11976 }
11977 }
11978
11979 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11980 xmlSchemaFacetPtr facet;
11981 /*
11982 * This is the case if we have: <simpleType><list ..
11983 */
11984 /*
11985 * 2.3.1
11986 * 2.3.1.1 The {final} of the {item type definition} must not
11987 * contain list.
11988 */
11989 if (xmlSchemaTypeFinalContains(ctxt->schema,
11990 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011991 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011992 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011993 NULL, type, NULL,
11994 "The final of its item type %s must not contain 'list'",
11995 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11996 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011997 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
11998 }
11999 /*
12000 * 2.3.1.2 The {facets} must only contain the whiteSpace
12001 * facet component.
12002 */
12003 if (type->facets != NULL) {
12004 facet = type->facets;
12005 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012006 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
12007 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012008 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012009 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012010 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
12011 }
12012 facet = facet->next;
12013 } while (facet != NULL);
12014 }
12015 /*
12016 * TODO: Datatypes states:
12017 * A ·list· datatype can be ·derived· from an ·atomic· datatype
12018 * whose ·lexical space· allows space (such as string or anyURI)or
12019 * a ·union· datatype any of whose {member type definitions}'s
12020 * ·lexical space· allows space.
12021 */
12022 } else {
12023 /*
12024 * This is the case if we have: <simpleType><restriction ...
12025 */
12026 /*
12027 * 2.3.2
12028 * 2.3.2.1 The {base type definition} must have a {variety} of list.
12029 */
12030 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012031 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012032 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012033 NULL, type, NULL,
12034 "The base type %s must be a list type",
12035 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12036 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012037 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
12038 }
12039 /*
12040 * 2.3.2.2 The {final} of the {base type definition} must not
12041 * contain restriction.
12042 */
12043 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12044 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012045 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012046 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012047 NULL, type, NULL,
12048 "The final of the base type %s must not contain 'restriction'",
12049 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12050 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012051 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
12052 }
12053 /*
12054 * 2.3.2.3 The {item type definition} must be validly derived
12055 * from the {base type definition}'s {item type definition} given
12056 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
12057 */
12058 {
12059 xmlSchemaTypePtr baseItemType;
12060
12061 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
12062 if (baseItemType == NULL) {
12063 xmlSchemaPErr(ctxt, type->node,
12064 XML_ERR_INTERNAL_ERROR,
12065 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012066 "List simple type '%s': Failed to "
12067 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012068 type->name, type->baseType->name);
12069 return (-1);
12070 }
12071 if ((itemType != baseItemType) &&
12072 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
12073 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012074 xmlChar *strBIT = NULL, *strBT = NULL;
12075 xmlSchemaPCustomErrExt(ctxt,
12076 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
12077 NULL, type, NULL,
12078 "The item type %s is not validly derived from the "
12079 "item type %s of the base type %s",
12080 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
12081 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
12082 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12083
12084 FREE_AND_NULL(str)
12085 FREE_AND_NULL(strBIT)
12086 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012087 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
12088 }
12089 }
12090
12091 if (type->facets != NULL) {
12092 xmlSchemaFacetPtr facet;
12093 int ok = 1;
12094 /*
12095 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
12096 * and enumeration facet components are allowed among the {facets}.
12097 */
12098 facet = type->facets;
12099 do {
12100 switch (facet->type) {
12101 case XML_SCHEMA_FACET_LENGTH:
12102 case XML_SCHEMA_FACET_MINLENGTH:
12103 case XML_SCHEMA_FACET_MAXLENGTH:
12104 case XML_SCHEMA_FACET_WHITESPACE:
12105 /*
12106 * TODO: 2.5.1.2 List datatypes
12107 * The value of ·whiteSpace· is fixed to the value collapse.
12108 */
12109 case XML_SCHEMA_FACET_PATTERN:
12110 case XML_SCHEMA_FACET_ENUMERATION:
12111 break;
12112 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012113 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012114 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012115 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012116 /*
12117 * We could return, but it's nicer to report all
12118 * invalid facets.
12119 */
12120 ok = 0;
12121 }
12122 }
12123 facet = facet->next;
12124 } while (facet != NULL);
12125 if (ok == 0)
12126 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
12127 /*
12128 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
12129 * is a facet of the same kind in the {facets} of the {base type
12130 * definition} (call this BF),then the DF's {value} must be a valid
12131 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
12132 */
12133 }
12134
12135
12136 }
12137 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12138 /*
12139 * 3.1 The {member type definitions} must all have {variety} of
12140 * atomic or list.
12141 */
12142 xmlSchemaTypeLinkPtr member;
12143
12144 member = type->memberTypes;
12145 while (member != NULL) {
12146 if (((member->type->flags &
12147 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12148 ((member->type->flags &
12149 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012150 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012151 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012152 NULL, type, NULL,
12153 "The member type %s is neither an atomic, nor a list type",
12154 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12155 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012156 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
12157 }
12158 member = member->next;
12159 }
12160 /*
12161 * 3.3.1 If the {base type definition} is the ·simple ur-type
12162 * definition·
12163 */
12164 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12165 /*
12166 * 3.3.1.1 All of the {member type definitions} must have a
12167 * {final} which does not contain union.
12168 */
12169 member = type->memberTypes;
12170 while (member != NULL) {
12171 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
12172 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012173 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012174 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012175 NULL, type, NULL,
12176 "The final of member type %s contains 'union'",
12177 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12178 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012179 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
12180 }
12181 member = member->next;
12182 }
12183 /*
12184 * 3.3.1.2 The {facets} must be empty.
12185 */
12186 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012187 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012188 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012189 NULL, type, NULL,
12190 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012191 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
12192 }
12193 } else {
12194 /*
12195 * 3.3.2.1 The {base type definition} must have a {variety} of union.
12196 */
12197 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012198 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012199 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012200 NULL, type, NULL,
12201 "The base type %s is not a union type",
12202 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12203 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012204 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
12205 }
12206 /*
12207 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
12208 */
12209 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12210 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012211 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012212 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012213 NULL, type, NULL,
12214 "The final of its base type %s must not contain 'restriction'",
12215 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12216 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012217 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
12218 }
12219 /*
12220 * 3.3.2.3 The {member type definitions}, in order, must be validly
12221 * derived from the corresponding type definitions in the {base
12222 * type definition}'s {member type definitions} given the empty set,
12223 * as defined in Type Derivation OK (Simple) (§3.14.6).
12224 */
12225 {
12226 xmlSchemaTypeLinkPtr baseMember;
12227
12228 /*
12229 * OPTIMIZE: if the type is restricting, it has no local defined
12230 * member types and inherits the member types of the base type;
12231 * thus a check for equality can be skipped.
12232 */
12233 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012234 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000012235 * union simple type can have other member types as the member
12236 * types of it's base type. This check seems not necessary with
12237 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012238 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012239 */
12240 if (type->memberTypes != NULL) {
12241 member = type->memberTypes;
12242 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
12243 if ((member == NULL) && (baseMember != NULL)) {
12244 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012245 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012246 "Internal error: "
12247 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012248 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012249 "of member types in the base type\n",
12250 type->name, NULL);
12251 }
12252 while (member != NULL) {
12253 if (baseMember == NULL) {
12254 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012255 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012256 "Internal error: "
12257 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012258 "(3.3.2.3), union simple type '%s', unequal number "
12259 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012260 type->name, NULL);
12261 }
12262 if ((member->type != baseMember->type) &&
12263 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
12264 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012265 xmlChar *strBMT = NULL, *strBT = NULL;
12266
12267 xmlSchemaPCustomErrExt(ctxt,
12268 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
12269 NULL, type, NULL,
12270 "The member type %s is not validly derived from its "
12271 "corresponding member type %s of the base type %s",
12272 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
12273 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
12274 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12275 FREE_AND_NULL(str)
12276 FREE_AND_NULL(strBMT)
12277 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012278 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
12279 }
12280 member = member->next;
12281 baseMember = baseMember->next;
12282 }
12283 }
12284 }
12285 /*
12286 * 3.3.2.4 Only pattern and enumeration facet components are
12287 * allowed among the {facets}.
12288 */
12289 if (type->facets != NULL) {
12290 xmlSchemaFacetPtr facet;
12291 int ok = 1;
12292
12293 facet = type->facets;
12294 do {
12295 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
12296 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012297 xmlSchemaPIllegalFacetListUnionErr(ctxt,
12298 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
12299 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012300 ok = 0;
12301 }
12302 facet = facet->next;
12303 } while (facet != NULL);
12304 if (ok == 0)
12305 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
12306
12307 }
12308 /*
12309 * TODO: 3.3.2.5 (facet derivation)
12310 */
12311 }
12312 }
12313
12314 return (0);
12315}
12316
12317/**
12318 * xmlSchemaCheckSRCSimpleType:
12319 * @ctxt: the schema parser context
12320 * @type: the simple type definition
12321 *
12322 * Checks crc-simple-type constraints.
12323 *
12324 * Returns 0 if the constraints are satisfied,
12325 * if not a positive error code and -1 on internal
12326 * errors.
12327 */
12328static int
12329xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
12330 xmlSchemaTypePtr type)
12331{
12332 /*
12333 * NOTE: src-simple-type 2-4 are redundant, since the checks
12334 * were are done for the corresponding <restriction>, <list> and <union>
12335 * elements, but W3C wants a <simpleType> error as well, so it gets one.
12336 * Maby this can be skipped in the future, if we get sure it's not needed.
12337 */
12338 if (type->subtypes == NULL) {
12339 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012340 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012341 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012342 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012343 type->name, NULL);
12344 return (-1);
12345 }
12346 /*
12347 * src-simple-type.1 The corresponding simple type definition, if any,
12348 * must satisfy the conditions set out in Constraints on Simple Type
12349 * Definition Schema Components (§3.14.6).
12350 */
12351 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
12352 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
12353 /*
12354 * TODO: Removed this, since it got annoying to get an
12355 * extra error report, if anything failed until now.
12356 * Enable this if needed.
12357 */
12358 /*
12359 xmlSchemaPErr(ctxt, type->node,
12360 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012361 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012362 "on simple type definitions.\n",
12363 type->name, NULL);
12364 */
12365 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
12366 }
12367
12368 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
12369 /*
12370 * src-simple-type.2 If the <restriction> alternative is chosen,
12371 * either it must have a base [attribute] or a <simpleType> among its
12372 * [children], but not both.
12373 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012374 /*
12375 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
12376 * NOTE: This was removed, since this will be already handled
12377 * in the parse function for <restriction>.
12378 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012379 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
12380 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
12381 * an itemType [attribute] or a <simpleType> among its [children],
12382 * but not both.
12383 * NOTE: baseType is set to the local simple type definiton,
12384 * if existent, at parse time. This is a hack and not nice.
12385 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012386 /*
12387 * TODO: Remove this, and add the check to the parse function of <list>.
12388 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012389 if (((type->subtypes->base == NULL) &&
12390 (type->baseType == NULL)) ||
12391 ((type->subtypes->base != NULL) &&
12392 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012393 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012394 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012395 NULL, type, NULL,
12396 "Either the attribute 'itemType' or the <simpleType> child "
12397 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012398 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
12399 }
12400
12401
12402 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
12403 xmlSchemaTypeLinkPtr member;
12404 xmlSchemaTypePtr ancestor, anySimpleType;
12405
12406 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12407
12408 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
12409 * the <union> alternative is chosen, there must not be any entries
12410 * in the memberTypes [attribute] at any depth which resolve to the
12411 * component corresponding to the <simpleType>.
12412 */
12413 member = type->memberTypes;
12414 while (member != NULL) {
12415 ancestor = member->type;
12416 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
12417 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12418 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
12419 if (ancestor == anySimpleType)
12420 break;
12421 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012422 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012423 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012424 NULL, type, NULL,
12425 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012426 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
12427 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12428 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012429 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000012430 * type as item type, which in turn has a list ST as member
12431 * type, we will assume this here as well, since this check
12432 * was not yet performed.
12433 */
12434
12435 }
12436 ancestor = ancestor->baseType;
12437 }
12438 member = member->next;
12439 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012440 }
12441
12442 return (0);
12443}
12444
William M. Brack2f2a6632004-08-20 23:09:47 +000012445#if 0 /* Not yet used code for CT schema validation */
12446static int
12447xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
12448 const xmlChar * value,
12449 xmlSchemaTypePtr type,
12450 int fireErrors)
12451{
12452 int ret;
12453 /*
12454 * 3.14.4 Simple Type Definition Validation Rules
12455 * Validation Rule: String Valid
12456 */
12457 /*
12458 * 1 It is schema-valid with respect to that definition as defined
12459 * by Datatype Valid in [XML Schemas: Datatypes].
12460 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012461 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
12462 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000012463 return (ret);
12464 /*
12465 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
12466 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
12467 * the string must be a ·declared entity name·.
12468 */
12469 /*
12470 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
12471 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
12472 * then every whitespace-delimited substring of the string must be a ·declared
12473 * entity name·.
12474 */
12475 /*
12476 * 2.3 otherwise no further condition applies.
12477 */
12478
12479 return (0);
12480}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012481#endif
12482
William M. Brack2f2a6632004-08-20 23:09:47 +000012483
12484static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012485xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
12486{
12487 if (vctxt->pctxt == NULL) {
12488 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
12489 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
12490 if (vctxt->pctxt == NULL) {
12491 xmlSchemaVErr(vctxt, NULL,
12492 XML_SCHEMAV_INTERNAL,
12493 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12494 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000012495 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012496 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012497 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012498 /* TODO: Pass user data. */
12499 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
12500 }
12501 return (0);
12502}
12503
12504static int
12505xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
12506{
12507 if (ctxt->vctxt == NULL) {
12508 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
12509 if (ctxt->vctxt == NULL) {
12510 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012511 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012512 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12513 "failed to create a temp. validation context.\n",
12514 NULL, NULL);
12515 return (-1);
12516 }
12517 /* TODO: Pass user data. */
12518 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
12519 }
12520 return (0);
12521}
12522
12523/**
12524 * xmlSchemaCheckCOSValidDefault:
12525 * @ctxt: the schema parser context
12526 * @type: the simple type definition
12527 * @value: the default value
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000012528 * @val: the precomputed value to be returned
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012529 * @node: an optional node (the holder of the value)
12530 *
12531 * Checks the "cos-valid-default" constraints.
12532 *
12533 * Returns 0 if the constraints are satisfied,
12534 * if not, a positive error code and -1 on internal
12535 * errors.
12536 */
12537static int
12538xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
12539 xmlSchemaValidCtxtPtr vctxt,
12540 xmlSchemaTypePtr type,
12541 const xmlChar *value,
12542 xmlNodePtr node)
12543{
12544 int ret = 0;
12545
12546 /*
12547 * cos-valid-default:
12548 * Schema Component Constraint: Element Default Valid (Immediate)
12549 * For a string to be a valid default with respect to a type
12550 * definition the appropriate case among the following must be true:
12551 */
12552 /*
12553 * NOTE: This has to work without a given node (the holder of the
12554 * value), since it should work on the component, i.e. an underlying
12555 * DOM must not be mandatory.
12556 */
12557 if ((pctxt == NULL) || (vctxt == NULL)) {
12558 xmlSchemaPErr(pctxt, node,
12559 XML_SCHEMAP_INTERNAL,
12560 "Internal error: xmlSchemaCheckCOSValidDefault, "
12561 "bad arguments: the parser and/or validation context is "
12562 "missing.\n",
12563 NULL, NULL);
12564 return (-1);
12565 }
12566 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012567 /*
12568 * Complex type.
12569 *
12570 * 2.1 its {content type} must be a simple type definition or mixed.
12571 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012572 /*
12573 * TODO: Adjust this when the content type will be computed
12574 * correctly.
12575 */
12576 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
12577 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
12578 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
12579 xmlSchemaPSimpleTypeErr(pctxt,
12580 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
12581 NULL, NULL, node,
12582 type, NULL, NULL,
12583 "If the type of a constraint value is complex, its content "
12584 "type must be mixed or a simple type",
12585 NULL, NULL);
12586 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
12587 }
12588 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012589 /*
12590 * 2.2.2 If the {content type} is mixed, then the {content type}'s
12591 * particle must be ·emptiable· as defined by Particle Emptiable
12592 * (§3.9.6).
12593 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012594
William M. Brack2f2a6632004-08-20 23:09:47 +000012595 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012596 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000012597 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012598 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000012599 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012600 }
12601 /*
12602 * 1 If the type definition is a simple type definition, then the string
12603 * must be ·valid· with respect to that definition as defined by String
12604 * Valid (§3.14.4).
12605 *
12606 * AND
12607 *
12608 * 2.2.1 If the {content type} is a simple type definition, then the
12609 * string must be ·valid· with respect to that simple type definition
12610 * as defined by String Valid (§3.14.4).
12611 */
12612 vctxt->node = node;
12613 vctxt->cur = NULL;
12614 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
12615 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
12616 if (ret < 0) {
12617 xmlSchemaPErr(pctxt, node,
12618 /* NOTNICE: error code: This function will be used during
12619 * schema construction and xsi:type validation.
12620 */
12621 XML_SCHEMAP_INTERNAL,
12622 "Internal error: xmlSchemaCheckCOSValidDefault, "
12623 "while validating a value constaint value.\n",
12624 NULL, NULL);
12625
12626 }
12627 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000012628}
12629
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012630#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000012631/**
12632 * xmlSchemaGetSTContentOfCT:
12633 * @ctxt: the schema parser context
12634 * @type: the complex type definition
12635 *
12636 *
12637 * Returns the corresponding simple type for the content of
12638 * the complex type.
12639 */
12640static xmlSchemaTypePtr
12641xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
12642 xmlSchemaTypePtr type)
12643{
12644 xmlSchemaTypePtr orig = type, anyType;
12645
12646 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12647 while ((type != NULL) && (type != anyType) &&
12648 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
12649 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
12650 return(type);
12651 type = type->baseType;
12652 }
12653 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012654 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012655 NULL, orig, NULL,
12656 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
12657 "no simple type for the content of complex type '%s' could be "
12658 "computed", orig->name);
12659 return (NULL);
12660}
12661
12662
William M. Brack2f2a6632004-08-20 23:09:47 +000012663
William M. Brack2f2a6632004-08-20 23:09:47 +000012664
12665/**
12666 * xmlSchemaCheckCOSCTExtends:
12667 * @ctxt: the schema parser context
12668 * @type: the complex type definition
12669 *
12670 * Schema Component Constraint: Derivation Valid (Extension)
12671 *
12672 * Returns 0 if the constraints are satisfied, a positive
12673 * error code if not and -1 if an internal error occured.
12674 */
12675static int
12676xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
12677 xmlSchemaTypePtr type)
12678{
12679 xmlSchemaTypePtr base;
12680 /*
12681 * 1 If the {base type definition} is a complex type definition,
12682 * then all of the following must be true:
12683 */
12684 base = type->baseType;
12685 if (base == NULL) {
12686 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012687 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012688 NULL, type, NULL,
12689 "Internal error: xmlSchemaCheckCOSCTExtends, "
12690 "the complex type '%s' has no base type", type->name);
12691 return (-1);
12692 }
12693 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
12694 /*
12695 * 1.1 The {final} of the {base type definition} must not
12696 * contain extension.
12697 */
12698 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
12699 xmlSchemaPCustomErr(ctxt,
12700 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
12701 NULL, type, NULL,
12702 "The 'final' of the base type definition "
12703 "contains extension", NULL);
12704 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
12705 }
12706 /*
12707 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
12708 * of the complex type definition itself, that is, for every attribute
12709 * use in the {attribute uses} of the {base type definition}, there
12710 * must be an attribute use in the {attribute uses} of the complex
12711 * type definition itself whose {attribute declaration} has the same
12712 * {name}, {target namespace} and {type definition} as its attribute
12713 * declaration
12714 *
12715 * NOTE: This will be already satisfied by the way the attribute uses
12716 * are extended in xmlSchemaBuildAttributeValidation; thus this check
12717 * is not needed.
12718 */
12719
12720 /*
12721 * 1.3 If it has an {attribute wildcard}, the complex type definition
12722 * must also have one, and the base type definition's {attribute
12723 * wildcard}'s {namespace constraint} must be a subset of the complex
12724 * type definition's {attribute wildcard}'s {namespace constraint},
12725 * as defined by Wildcard Subset (§3.10.6).
12726 *
12727 * This is already checked in xmlSchemaBuildAttributeValidation; thus
12728 * this check is not needed.
12729 */
12730
12731 /*
12732 * 1.4 One of the following must be true:
12733 *
12734 * 1.4.1 The {content type} of the {base type definition} and the
12735 * {content type} of the complex type definition itself must be the same
12736 * simple type definition
12737 */
12738
12739
12740
12741 } else {
12742 /*
12743 * 2 If the {base type definition} is a simple type definition,
12744 * then all of the following must be true:
12745 */
12746 /*
12747 * 2.1 The {content type} must be the same simple type definition.
12748 */
12749 /*
12750 * 2.2 The {final} of the {base type definition} must not contain
12751 * extension
12752 */
12753 }
12754
12755}
12756
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012757static int
12758xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
12759 xmlSchemaTypePtr type)
12760{
12761 xmlSchemaTypePtr base, content;
12762 int OK = 0;
12763
12764 /*
12765 * TODO: Adjust the error codes here, as I used
12766 * XML_SCHEMAP_SRC_CT_1 only yet.
12767 */
12768 /*
12769 * Schema Representation Constraint:
12770 * Complex Type Definition Representation OK
12771 */
12772 base = type->baseType;
12773 if (base == NULL) {
12774 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
12775 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
12776 type->name);
12777 return (-1);
12778 }
12779
12780 if (type->subtypes != NULL) {
12781 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
12782 if IS_COMPLEX_TYPE(base) {
12783 /*
12784 * 1 If the <complexContent> alternative is chosen, the type definition
12785 * ·resolved· to by the ·actual value· of the base [attribute]
12786 * must be a complex type definition;
12787 */
12788 xmlSchemaPCustomErr(ctxt,
12789 XML_SCHEMAP_SRC_CT_1,
12790 NULL, type, NULL,
12791 "The base type is not a complex type", NULL);
12792 return (XML_SCHEMAP_SRC_CT_1);
12793 }
12794 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
12795
12796 if IS_SIMPLE_TYPE(base) {
12797 if (type->flags &
12798 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12799 /*
12800 * 2.1.3 only if the <extension> alternative is also
12801 * chosen, a simple type definition.
12802 */
12803 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
12804 xmlSchemaPCustomErr(ctxt,
12805 XML_SCHEMAP_SRC_CT_1,
12806 NULL, type, NULL,
12807 "A complex type (simple content) cannot restrict "
12808 "an other simple type",
12809 NULL);
12810 return (XML_SCHEMAP_SRC_CT_1);
12811 }
12812 OK = 1;
12813
12814 } else { /* if IS_SIMPLE_TYPE(base) */
12815 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
12816 /*
12817 * 2.1.2 only if the <restriction> alternative is also
12818 * chosen, a complex type definition whose {content type}
12819 * is mixed and a particle emptyable.
12820 */
12821 /*
12822 * FIXME TODO: Check for *empiable particle* is missing.
12823 */
12824 if ((type->flags &
12825 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
12826 xmlSchemaPCustomErr(ctxt,
12827 XML_SCHEMAP_SRC_CT_1,
12828 NULL, type, NULL,
12829 "A complex type (simple content) cannot "
12830 "extend an other complex type which has a "
12831 "content type of: 'mixed' and emptiable particle",
12832 NULL);
12833 return (XML_SCHEMAP_SRC_CT_1);
12834 }
12835 /*
12836 * NOTE: This will be fired as well, if the base type
12837 * is *'anyType'*.
12838 * NOTE: type->subtypes->subtypes will be the
12839 * <restriction> item.
12840 */
12841 if (type->subtypes->subtypes == NULL) {
12842 /* Yes, this is paranoid programming. */
12843 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12844 NULL, type, NULL,
12845 "Internal error: xmlSchemaCheckSRCCT, "
12846 "'%s', <simpleContent> has no <restriction>",
12847 type->name);
12848 return (-1);
12849 }
12850 /*
12851 * 2.2 If clause 2.1.2 above is satisfied, then there
12852 * must be a <simpleType> among the [children] of
12853 * <restriction>.
12854 */
12855 if (type->subtypes->subtypes->type !=
12856 XML_SCHEMA_TYPE_SIMPLE) {
12857 /* TODO: Change error code to ..._SRC_CT_2_2. */
12858 xmlSchemaPCustomErr(ctxt,
12859 XML_SCHEMAP_SRC_CT_1,
12860 NULL, type, NULL,
12861 "A <simpleType> is expected among the children "
12862 "of <restriction>", NULL);
12863 return (XML_SCHEMAP_SRC_CT_1);
12864 }
12865 OK = 1;
12866 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
12867 /*
12868 * 2.1.1 a complex type definition whose {content type} is a
12869 * simple type definition;
12870 */
12871 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
12872 xmlSchemaPCustomErr(ctxt,
12873 XML_SCHEMAP_SRC_CT_1,
12874 NULL, type, NULL,
12875 "A complex type (simple content) cannot "
12876 "be derived from the complex type '%s'",
12877 base->name);
12878 return (XML_SCHEMAP_SRC_CT_1);
12879 }
12880 content = base->contentTypeDef;
12881 if (content == NULL) {
12882 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12883 NULL, type, NULL,
12884 "Internal error: xmlSchemaCheckSRCCT, "
12885 "'%s', base type has no content type",
12886 type->name);
12887 return (-1);
12888 }
12889 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
12890 xmlSchemaPCustomErr(ctxt,
12891 XML_SCHEMAP_SRC_CT_1,
12892 NULL, type, NULL,
12893 "A complex type (simple content) cannot "
12894 "be derived from the complex type '%s'",
12895 base->name);
12896 return (XML_SCHEMAP_SRC_CT_1);
12897 }
12898 }
12899 }
12900 }
12901 }
12902 /*
12903 * TODO: 3 The corresponding complex type definition component must
12904 * satisfy the conditions set out in Constraints on Complex Type
12905 * Definition Schema Components (§3.4.6);
12906 *
12907 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
12908 * above for {attribute wildcard} is satisfied, the intensional
12909 * intersection must be expressible, as defined in Attribute Wildcard
12910 * Intersection (§3.10.6).
12911 */
12912
12913}
William M. Brack2f2a6632004-08-20 23:09:47 +000012914#endif
12915
Daniel Veillard01fa6152004-06-29 17:04:39 +000012916/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012917 * xmlSchemaGroupDefFixup:
12918 * @typeDecl: the schema model group definition
12919 * @ctxt: the schema parser context
12920 *
12921 * Fixes model group definitions.
12922 */
12923static void
12924xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
12925 xmlSchemaParserCtxtPtr ctxt,
12926 const xmlChar * name ATTRIBUTE_UNUSED)
12927{
12928 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
12929 if ((group->ref != NULL) && (group->subtypes == NULL)) {
12930 xmlSchemaTypePtr groupDef;
12931 /*
12932 * Resolve the reference.
12933 */
12934 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
12935 group->refNs);
12936 if (groupDef == NULL) {
12937 xmlSchemaPResCompAttrErr(ctxt,
12938 XML_SCHEMAP_SRC_RESOLVE,
12939 NULL, group, NULL,
12940 "ref", group->ref, group->refNs,
12941 XML_SCHEMA_TYPE_GROUP, NULL);
12942 return;
12943 }
12944 group->subtypes = groupDef;
12945 }
12946}
12947
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012948#if 0 /* Enable when the content type will be computed. */
12949static int
12950xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
12951 xmlSchemaTypePtr type)
12952{
12953 xmlSchemaTypePtr base, res = NULL;
12954
12955 base = type->baseType;
12956 if (base == NULL) {
12957 xmlSchemaPCustomErr(ctxt,
12958 XML_SCHEMAP_INTERNAL,
12959 NULL, type, NULL,
12960 "Internal error: xmlSchemaGetContentType, "
12961 "the complex type '%s' has no base type", type->name);
12962 return (-1);
12963 }
12964 if (IS_ANYTYPE(base) || (type->subtypes->type ==
12965 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
12966 xmlSchemaTypePtr start;
12967 /*
12968 * Effective 'mixed'.
12969 */
12970 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12971 type->contentType = XML_SCHEMA_CONTENT_MIXED;
12972 /*
12973 * Effective content.
12974 */
12975 if (IS_ANYTYPE(base))
12976 start = type;
12977 else
12978 start = type->subtypes;
12979
12980 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
12981 xmlSchemaTypePtr baseContentItem;
12982
12983 /*
12984 * Complex type with simple content.
12985 */
12986 if IS_COMPLEX_TYPE(base) {
12987 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12988 /*
12989 * Summary: a complex type (simple content) can *restrict*
12990 * a complex type with the following content type:
12991 * 1. 'mixed' and an emptiable particle
12992 * 2. simple type
12993 */
12994 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
12995 /*
12996 * 2 if the {content type} of the base type is mixed and a
12997 * particle which is ·emptiable·,
12998 * [...]
12999 * then starting from the simple type definition
13000 * corresponding to the <simpleType> among the [children]
13001 * of <restriction> (**which must be present**)
13002 *
13003 * FIXME TODO: Handle "emptiable particle".
13004 */
13005 res = type->subtypes->subtypes;
13006 if (res == NULL) {
13007 xmlSchemaPCustomErr(ctxt,
13008 XML_SCHEMAP_INTERNAL,
13009 NULL, type, NULL,
13010 "Internal error: xmlSchemaGetContentType, "
13011 "CT '%s' (restricting): <simpleContent> has no "
13012 "<restriction>",
13013 type->name);
13014 return (-1);
13015 }
13016
13017 res->subtypes;
13018 if (res == NULL) {
13019 xmlSchemaPCustomErr(ctxt,
13020 XML_SCHEMAP_INTERNAL,
13021 NULL, type, NULL,
13022 "Internal error: xmlSchemaGetContentType, "
13023 "CT '%s' (restricting): <restriction> has no "
13024 "mandatory <simpleType>",
13025 type->name);
13026 return (-1);
13027 }
13028 } else {
13029 baseContentItem = base->contentTypeDef;
13030 if (baseContentItem == NULL) {
13031 xmlSchemaPCustomErr(ctxt,
13032 XML_SCHEMAP_INTERNAL,
13033 NULL, type, NULL,
13034 "Internal error: xmlSchemaGetContentType, "
13035 "CT '%s' (restricting), the base type has no "
13036 "content type", type->name);
13037 return (-1);
13038 }
13039 if IS_SIMPLE_TYPE(baseContentItem) {
13040 /*
13041 * 1 If the base type is a complex type whose own
13042 * {content type} is a simple type and the <restriction>
13043 * alternative is chosen
13044 */
13045 /* type->subtypes->subtypes will be the restriction item.*/
13046 res = type->subtypes->subtypes;
13047 if (res == NULL) {
13048 xmlSchemaPCustomErr(ctxt,
13049 XML_SCHEMAP_INTERNAL,
13050 NULL, type, NULL,
13051 "Internal error: xmlSchemaGetContentType, "
13052 "CT '%s' (restricting): <simpleType> has no "
13053 "<restriction>", type->name);
13054 return (-1);
13055 }
13056 /*
13057 * 1.1 the simple type definition corresponding to the
13058 * <simpleType> among the [children] of <restriction>if
13059 * there is one;
13060 */
13061 res = res->subtypes;
13062 if (res == NULL) {
13063 /*
13064 * 1.2 otherwise the {content type}
13065 * of the base type .
13066 */
13067 res = baseContentItem;
13068 }
13069 }
13070 }
13071 /*
13072 * SPECIAL TODO: If *restricting* the spec wants us to
13073 * create an *additional* simple type which restricts the
13074 * located simple type; we won't do this yet, and look how
13075 * far we get with it.
13076 */
13077 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
13078 /*
13079 * Summary: a complex type (simple content) can *extend*
13080 * only a complex base with a simple type as content.
13081 */
13082 /*
13083 * 3 If the type definition ·resolved· to by the ·actual
13084 * value· of the base [attribute] is a complex type
13085 * definition (whose own {content type} *must be* a simple
13086 * type definition, see below) and the *<extension>*
13087 * alternative is chosen, then the {content type} of that
13088 * complex type definition;
13089 */
13090 res = base->contentTypeDef;
13091 if (res == NULL) {
13092 xmlSchemaPCustomErr(ctxt,
13093 XML_SCHEMAP_INTERNAL,
13094 NULL, type, NULL,
13095 "Internal error: xmlSchemaGetContentType, "
13096 "CT '%s' (extending), the base type has no content "
13097 "type", type->name);
13098 return (-1);
13099 }
13100 if (! IS_SIMPLE_TYPE(res)) {
13101 xmlSchemaPCustomErr(ctxt,
13102 XML_SCHEMAP_INTERNAL,
13103 NULL, type, NULL,
13104 "Internal error: xmlSchemaGetContentType, "
13105 "CT '%s' (extending), the content type of the "
13106 "base is not a simple type", type->name);
13107 return (-1);
13108 }
13109 }
13110 } else /* if IS_COMPLEX_TYPE(base) */
13111 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
13112 /*
13113 * 4 otherwise (the type definition ·resolved· to by the
13114 * ·actual value· of the base [attribute] is a simple type
13115 * definition and the <extension> alternative is chosen),
13116 * then that simple type definition.
13117 */
13118 res = base;
13119 }
13120 type->contentTypeDef = res;
13121 if (res == NULL) {
13122 xmlSchemaPCustomErr(ctxt,
13123 XML_SCHEMAP_INTERNAL,
13124 NULL, type, NULL,
13125 "Internal error: xmlSchemaGetContentType, "
13126 "'%s', the content type could not be determined",
13127 type->name);
13128 return (-1);
13129 }
13130
13131 }
13132
13133}
13134#endif
13135
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013136/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013137 * xmlSchemaTypeFixup:
13138 * @typeDecl: the schema type definition
13139 * @ctxt: the schema parser context
13140 *
13141 * Fixes the content model of the type.
13142 */
13143static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013144xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013145 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013146{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013147 xmlSchemaTypePtr ctxtType;
13148
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013149 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013150 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013151 /*
13152 * Do not allow the following types to be typefixed, prior to
13153 * the corresponding simple/complex types.
13154 */
13155 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013156 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013157 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13158 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13159 case XML_SCHEMA_TYPE_UNION:
13160 case XML_SCHEMA_TYPE_RESTRICTION:
13161 case XML_SCHEMA_TYPE_EXTENSION:
13162 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013163 default:
13164 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013165 }
13166 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013167 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013168 name = item->name;
13169 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
13170 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013171 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013172 if (item->subtypes != NULL) {
13173 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013174 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013175 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013176 NULL);
13177 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013178 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013179 XML_SCHEMA_CONTENT_SIMPLE;
13180 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013181 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013182 break;
13183 }
13184 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013185 xmlSchemaTypePtr base = NULL;
13186
13187 ctxt->ctxtType->flags |=
13188 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013189 if (item->baseType != NULL)
13190 base = item->baseType;
13191 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013192 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013193 xmlSchemaGetType(ctxt->schema, item->base,
13194 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013195 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013196 xmlSchemaPResCompAttrErr(ctxt,
13197 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000013198 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013199 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
13200 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013201 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013202 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000013203 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013204 xmlSchemaTypeFixup(base, ctxt, NULL);
13205 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013206 }
13207 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013208 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
13209 /*
13210 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000013211 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013212 /*
13213 * Content type.
13214 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013215 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013216 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013217 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13218 else if ((item->subtypes->subtypes == NULL) &&
13219 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013220 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013221 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013222 XML_SCHEMA_TYPE_SEQUENCE)))
13223 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013224 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13225 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013226 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013227 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013228 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013229 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013230 else {
13231 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013232 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013233 XML_SCHEMA_CONTENT_ELEMENTS;
13234 }
13235 } else {
13236 /*
13237 * SimpleType restriction.
13238 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013239 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013240 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013241 break;
13242 }
13243 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013244 xmlSchemaTypePtr base = NULL;
13245 xmlSchemaContentType explicitContentType;
13246
13247 /*
13248 * An extension does exist on a complexType only.
13249 */
13250 ctxt->ctxtType->flags |=
13251 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013252 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013253 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013254 xmlSchemaPCustomErr(ctxt,
13255 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013256 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013257 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000013258 return;
13259 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013260 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013261 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013262 xmlSchemaGetType(ctxt->schema, item->base,
13263 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013264 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013265 xmlSchemaPResCompAttrErr(ctxt,
13266 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013267 NULL, item, item->node,
13268 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013269 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013270 } else if (base->contentType ==
13271 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013272 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013273 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013274 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013275 }
13276 /*
13277 * The type definition ·resolved· to by the ·actual
13278 * value· of the base [attribute]
13279 */
13280 ctxt->ctxtType->baseType = base;
13281 /*
13282 * TODO: This one is still needed for computation of
13283 * the content model by xmlSchemaBuildAContentModel.
13284 * Try to get rid of it.
13285 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013286 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013287 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013288 if ((item->subtypes != NULL) &&
13289 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
13290 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013291
13292 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013293 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013294 /* 1.1.1 */
13295 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013296 else if ((item->subtypes->subtypes == NULL) &&
13297 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013298 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013299 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013300 XML_SCHEMA_TYPE_SEQUENCE)))
13301 /* 1.1.2 */
13302 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013303 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013304 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013305 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013306 /* 1.1.3 */
13307 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
13308 if (base != NULL) {
13309 /* It will be reported later, if the base is missing. */
13310 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
13311 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013312 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013313 } else if (base->contentType ==
13314 XML_SCHEMA_CONTENT_EMPTY) {
13315 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013316 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013317 XML_SCHEMA_CONTENT_ELEMENTS;
13318 } else {
13319 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013320 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013321 XML_SCHEMA_CONTENT_ELEMENTS;
13322 }
13323 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013324 break;
13325 }
13326 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013327 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013328 ctxt->ctxtType = item;
13329 /*
13330 * Start with an empty content-type type.
13331 */
13332 if (item->subtypes == NULL)
13333 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13334
13335 if ((item->subtypes == NULL) ||
13336 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013337 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013338 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013339 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
13340 /*
13341 * This case is understood as shorthand for complex
13342 * content restricting the ur-type definition, and
13343 * the details of the mappings should be modified as
13344 * necessary.
13345 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013346 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13347 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013348 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013349 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013350 * Assume that we inherit the content-type type
13351 * from 'anyType', which is 'mixed' and a particle
13352 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013353 */
13354 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013355 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013356 /*
13357 * Fixup the sub components.
13358 */
13359 if ((item->subtypes != NULL) &&
13360 (item->subtypes->contentType ==
13361 XML_SCHEMA_CONTENT_UNKNOWN)) {
13362 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013363 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013364 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13365 item->contentType = XML_SCHEMA_CONTENT_MIXED;
13366 } else if (item->subtypes != NULL) {
13367 /*
13368 * Use the content-type type of the model groups
13369 * defined, if 'mixed' is not set. If 'mixed' is set
13370 * it will expand the content-type by allowing character
13371 * content to appear.
13372 */
13373 item->contentType =
13374 item->subtypes->contentType;
13375 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013376
13377 /*
13378 * Some optimization for validation:
13379 * If there are no facets beside the "whitespace" facet,
13380 * then a value needs not to checked against against a
13381 * facet, thus no computed value is needed.
13382 * TODO URGENT: This is just a workaround, we need to
13383 * introduce the correct usage of contentType to store the
13384 * facets in!
13385 */
Daniel Veillardd3210bc2005-01-28 17:56:39 +000013386 if ((item->baseType != NULL) &&
13387 (item->baseType->flags &
13388 XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013389 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13390 else {
13391 xmlSchemaFacetLinkPtr cur;
13392
13393 for (cur = item->facetSet; cur != NULL;
13394 cur = cur->next) {
13395 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13396 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13397 break;
13398 }
13399 }
13400 }
13401
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013402 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013403 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013404 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013405 break;
13406 }
13407 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013408 if (item->subtypes == NULL) {
13409 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13410 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
13411 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000013412 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013413 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013414 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13415 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013416 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000013417 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013418 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013419 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013420 if (item->subtypes != NULL)
13421 item->contentType =
13422 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013423 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013424 /*
13425 * Removed due to implementation of the build of attribute uses.
13426 */
13427 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013428 if (item->attributes == NULL)
13429 item->attributes =
13430 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000013431 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013432 }
13433 break;
13434 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013435 case XML_SCHEMA_TYPE_SIMPLE:
13436 /*
13437 * Simple Type Definition Schema Component
13438 *
13439 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013440 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013441 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13442 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013443 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013444 ctxt->ctxtType = item;
13445 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013446 }
13447 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013448 if ((item->baseType != NULL) &&
13449 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013450 XML_SCHEMA_CONTENT_UNKNOWN)) {
13451 /* OPTIMIZE: Actually this one will never by hit, since
13452 * the base type is already type-fixed in <restriction>.
13453 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013454 ctxt->ctxtType = item;
13455 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013456 }
13457 /* Base type:
13458 * 2 If the <list> or <union> alternative is chosen,
13459 * then the ·simple ur-type definition·.
13460 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013461 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013462 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013463 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13464 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13465 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013466 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013467 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13468 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
13469 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013470 XML_SCHEMA_TYPE_RESTRICTION) {
13471 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
13472
13473 /*
13474 * Variety
13475 * If the <restriction> alternative is chosen, then the
13476 * {variety} of the {base type definition}.
13477 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013478 if (item->baseType != NULL) {
13479 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013480 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013481 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
13482 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013483 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013484 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13485 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013486 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013487 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013488 /*
13489 * Schema Component Constraint: Simple Type Restriction
13490 * (Facets)
13491 * NOTE: Satisfaction of 1 and 2 arise from the fixup
13492 * applied beforehand.
13493 *
13494 * 3 The {facets} of R are the union of S and the {facets}
13495 * of B, eliminating duplicates. To eliminate duplicates,
13496 * when a facet of the same kind occurs in both S and the
13497 * {facets} of B, the one in the {facets} of B is not
13498 * included, with the exception of enumeration and pattern
13499 * facets, for which multiple occurrences with distinct values
13500 * are allowed.
13501 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013502 if (item->baseType->facetSet != NULL) {
13503 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013504 if (last != NULL)
13505 while (last->next != NULL)
13506 last = last->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013507 cur = item->baseType->facetSet;
13508 for (; cur != NULL; cur = cur->next) {
13509 /*
13510 * Base patterns won't be add here:
13511 * they are ORed in a type and
13512 * ANDed in derived types. This will
13513 * happed at validation level by
13514 * walking the base axis of the type.
13515 */
13516 if (cur->facet->type ==
13517 XML_SCHEMA_FACET_PATTERN)
13518 continue;
13519 facet = NULL;
13520 if ((item->facetSet != NULL) &&
13521 /* REMOVED: a check for
13522 * XML_SCHEMA_FACET_PATTERN was already
13523 * performed above.
13524
13525 * (cur->facet->type !=
13526 * XML_SCHEMA_FACET_PATTERN) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000013527 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013528 (cur->facet->type !=
13529 XML_SCHEMA_FACET_ENUMERATION)) {
13530 facet = item->facetSet;
13531 do {
13532 if (cur->facet->type ==
13533 facet->facet->type)
13534 break;
13535 facet = facet->next;
13536 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013537 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013538 if (facet == NULL) {
13539 facet = (xmlSchemaFacetLinkPtr)
13540 xmlMalloc(sizeof(xmlSchemaFacetLink));
13541 if (facet == NULL) {
13542 xmlSchemaPErrMemory(ctxt,
13543 "fixing simpleType", NULL);
13544 return;
13545 }
13546 /*
13547 * The facets are not copied but referenced
13548 * via the facet link.
13549 */
13550 facet->facet = cur->facet;
13551 facet->next = NULL;
13552 if (last == NULL)
13553 item->facetSet = facet;
13554 else
13555 last->next = facet;
13556 last = facet;
13557 }
13558 }
13559 }
13560 /*
13561 * Some optimization for validation:
13562 * If there are no facets beside the "whitespace" facet,
13563 * then a value needs not to checked against against a
13564 * facet, thus no computed value is needed.
13565 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000013566 if (item->baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013567 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13568 else {
13569 for (cur = item->facetSet; cur != NULL;
13570 cur = cur->next) {
13571 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13572 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13573 break;
13574 }
13575 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013576 }
13577 }
13578 }
13579 /*
13580 * Check constraints.
13581 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013582 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013583 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013584 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013585 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013586 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013587 case XML_SCHEMA_TYPE_ALL:
13588 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013589 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013590 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013591 case XML_SCHEMA_TYPE_GROUP:
13592 /*
13593 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
13594 */
13595 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013596 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013597 xmlSchemaParseListRefFixup(item, ctxt);
13598 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013599 break;
13600 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013601 xmlSchemaParseUnionRefCheck(item, ctxt);
13602 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013603 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013604 case XML_SCHEMA_TYPE_BASIC:
13605 case XML_SCHEMA_TYPE_ANY:
13606 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013607 case XML_SCHEMA_TYPE_UR:
13608 case XML_SCHEMA_TYPE_ELEMENT:
13609 case XML_SCHEMA_TYPE_ATTRIBUTE:
13610 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000013611 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013612 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013613 case XML_SCHEMA_FACET_MININCLUSIVE:
13614 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13615 case XML_SCHEMA_FACET_MAXINCLUSIVE:
13616 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13617 case XML_SCHEMA_FACET_TOTALDIGITS:
13618 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13619 case XML_SCHEMA_FACET_PATTERN:
13620 case XML_SCHEMA_FACET_ENUMERATION:
13621 case XML_SCHEMA_FACET_WHITESPACE:
13622 case XML_SCHEMA_FACET_LENGTH:
13623 case XML_SCHEMA_FACET_MAXLENGTH:
13624 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013625 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13626 if (item->subtypes != NULL)
13627 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013628 break;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000013629 case XML_SCHEMA_TYPE_IDC_UNIQUE:
13630 case XML_SCHEMA_TYPE_IDC_KEY:
13631 case XML_SCHEMA_TYPE_IDC_KEYREF:
13632 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013633 }
13634 }
Daniel Veillard8651f532002-04-17 09:06:27 +000013635#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013636 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013637 xmlGenericError(xmlGenericErrorContext,
13638 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013639 item->node->doc->URL,
13640 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013641 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013642 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013643 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013644 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013645 case XML_SCHEMA_CONTENT_SIMPLE:
13646 xmlGenericError(xmlGenericErrorContext, "simple\n");
13647 break;
13648 case XML_SCHEMA_CONTENT_ELEMENTS:
13649 xmlGenericError(xmlGenericErrorContext, "elements\n");
13650 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013651 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013652 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
13653 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013654 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013655 xmlGenericError(xmlGenericErrorContext, "empty\n");
13656 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013657 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013658 xmlGenericError(xmlGenericErrorContext, "mixed\n");
13659 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013660 /* Removed, since not used. */
13661 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000013662 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013663 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
13664 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013665 */
Daniel Veillard8651f532002-04-17 09:06:27 +000013666 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013667 xmlGenericError(xmlGenericErrorContext, "basic\n");
13668 break;
13669 default:
13670 xmlGenericError(xmlGenericErrorContext,
13671 "not registered !!!\n");
13672 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013673 }
13674#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013675}
13676
13677/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013678 * xmlSchemaCheckFacet:
13679 * @facet: the facet
13680 * @typeDecl: the schema type definition
13681 * @ctxt: the schema parser context or NULL
13682 * @name: name of the type
13683 *
13684 * Checks the default values types, especially for facets
13685 *
13686 * Returns 0 if okay or -1 in cae of error
13687 */
13688int
13689xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013690 xmlSchemaTypePtr typeDecl,
13691 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013692{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013693 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013694 int ret = 0, reuseValCtxt = 0;
13695
Daniel Veillardce682bc2004-11-05 17:22:25 +000013696 if ((facet == NULL) || (typeDecl == NULL))
13697 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013698 /*
13699 * TODO: will the parser context be given if used from
13700 * the relaxNG module?
13701 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013702
13703 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013704 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013705 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013706 }
13707 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013708 case XML_SCHEMA_FACET_MININCLUSIVE:
13709 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13710 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013711 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13712 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013713 /*
13714 * Okay we need to validate the value
13715 * at that point.
13716 */
13717 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013718 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013719
13720 /* 4.3.5.5 Constraints on enumeration Schema Components
13721 * Schema Component Constraint: enumeration valid restriction
13722 * It is an ·error· if any member of {value} is not in the
13723 * ·value space· of {base type definition}.
13724 *
13725 * minInclusive, maxInclusive, minExclusive, maxExclusive:
13726 * The value ·must· be in the
13727 * ·value space· of the ·base type·.
13728 */
13729 /*
13730 * This function is intended to deliver a compiled value
13731 * on the facet. In XML Schemas the type holding a facet,
13732 * cannot be a built-in type. Thus to ensure that other API
13733 * calls (relaxng) do work, if the given type is a built-in
13734 * type, we will assume that the given built-in type *is
13735 * already* the base type.
13736 */
13737 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
13738 base = typeDecl->baseType;
13739 if (base == NULL) {
13740 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013741 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013742 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013743 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013744 typeDecl->name, NULL);
13745 return (-1);
13746 }
13747 } else
13748 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013749 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013750 * This avoids perseverative creation of the
13751 * validation context if a parser context is
13752 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013753 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013754 if (ctxt != NULL) {
13755 reuseValCtxt = 1;
13756 if (ctxt->vctxt == NULL) {
13757 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13758 return (-1);
13759 }
13760 vctxt = ctxt->vctxt;
13761 } else {
13762 vctxt = xmlSchemaNewValidCtxt(NULL);
13763 if (vctxt == NULL) {
13764 xmlSchemaPErr(ctxt, typeDecl->node,
13765 XML_SCHEMAP_INTERNAL,
13766 "Internal error: xmlSchemaCheckFacet, "
13767 "creating a new validation context.\n",
13768 NULL, NULL);
13769 return (-1);
13770 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013771 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013772
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013773 vctxt->node = facet->node;
13774 vctxt->cur = NULL;
13775 /*
13776 * NOTE: This call does not check the content nodes,
13777 * since they are not available:
13778 * facet->node is just the node holding the facet
13779 * definition, *not* the attribute holding the *value*
13780 * of the facet.
13781 */
13782 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
13783 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013784 facet->val = vctxt->value;
13785 vctxt->value = NULL;
13786 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013787 /* error code */
13788 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013789 xmlSchemaPErrExt(ctxt, facet->node,
13790 XML_SCHEMAP_INVALID_FACET,
13791 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013792 "Type definition '%s': The value '%s' of the "
13793 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013794 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013795 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000013796 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013797 }
13798 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013799 } else if (ret < 0) {
13800 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013801 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013802 NULL, NULL, NULL,
13803 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013804 "failed to validate the value '%s' name of the "
13805 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013806 facet->value,
13807 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
13808 base->name, NULL, NULL);
13809 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013810 }
13811 if (reuseValCtxt == 0)
13812 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013813 break;
13814 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013815 case XML_SCHEMA_FACET_PATTERN:
13816 facet->regexp = xmlRegexpCompile(facet->value);
13817 if (facet->regexp == NULL) {
13818 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013819 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013820 "Type definition '%s': The value '%s' of the "
13821 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013822 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013823 ret = -1;
13824 }
13825 break;
13826 case XML_SCHEMA_FACET_TOTALDIGITS:
13827 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13828 case XML_SCHEMA_FACET_LENGTH:
13829 case XML_SCHEMA_FACET_MAXLENGTH:
13830 case XML_SCHEMA_FACET_MINLENGTH:{
13831 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013832
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013833 tmp =
13834 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
13835 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013836 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013837 if (tmp != 0) {
13838 /* error code */
13839 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013840 xmlSchemaPErrExt(ctxt, facet->node,
13841 XML_SCHEMAP_INVALID_FACET_VALUE,
13842 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013843 "Type definition '%s': The value '%s' of the "
13844 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013845 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013846 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000013847 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013848 }
13849 ret = -1;
13850 }
13851 break;
13852 }
13853 case XML_SCHEMA_FACET_WHITESPACE:{
13854 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
13855 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
13856 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
13857 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
13858 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
13859 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
13860 } else {
13861 if (ctxt != NULL) {
13862 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013863 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013864 "Type definition '%s': The value '%s' of the "
13865 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013866 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013867 }
13868 ret = -1;
13869 }
13870 }
13871 default:
13872 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013873 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013874 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013875}
13876
13877/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013878 * xmlSchemaCheckDefaults:
13879 * @typeDecl: the schema type definition
13880 * @ctxt: the schema parser context
13881 *
13882 * Checks the default values types, especially for facets
13883 */
13884static void
13885xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013886 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013887{
Daniel Veillard4255d502002-04-16 15:50:10 +000013888 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013889 name = typeDecl->name;
13890 /*
13891 * NOTE: It is intended to use the facets list, instead
13892 * of facetSet.
13893 */
13894 if (typeDecl->facets != NULL) {
13895 xmlSchemaFacetPtr facet = typeDecl->facets;
13896
13897 while (facet != NULL) {
13898 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
13899 facet = facet->next;
13900 }
13901 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013902}
13903
13904/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013905 * xmlSchemaGetCircModelGrDefRef:
13906 * @ctxtGr: the searched model group
13907 * @list: the list of model groups to be processed
13908 *
13909 * This one is intended to be used by
13910 * xmlSchemaCheckGroupDefCircular only.
13911 *
13912 * Returns the circular model group definition reference, otherwise NULL.
13913 */
13914static xmlSchemaTypePtr
13915xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
13916 xmlSchemaTypePtr gr)
13917{
13918 xmlSchemaTypePtr circ = NULL;
13919 int marked;
13920 /*
13921 * We will search for an model group reference which
13922 * references the context model group definition.
13923 */
13924 while (gr != NULL) {
13925 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
13926 (gr->type == XML_SCHEMA_TYPE_ALL) ||
13927 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
13928 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
13929 (gr->subtypes != NULL)) {
13930 marked = 0;
13931 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
13932 (gr->ref != NULL)) {
13933 if (gr->subtypes == ctxtGrDef)
13934 return (gr);
13935 else if (gr->subtypes->flags &
13936 XML_SCHEMAS_TYPE_MARKED) {
13937 gr = gr->next;
13938 continue;
13939 } else {
13940 /*
13941 * Mark to avoid infinite recursion on
13942 * circular references not yet examined.
13943 */
13944 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
13945 marked = 1;
13946 }
13947 if (gr->subtypes->subtypes != NULL)
13948 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13949 gr->subtypes->subtypes);
13950 /*
13951 * Unmark the visited model group definition.
13952 */
13953 if (marked)
13954 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
13955 if (circ != NULL)
13956 return (circ);
13957 } else {
13958 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13959 (xmlSchemaTypePtr) gr->subtypes);
13960 if (circ != NULL)
13961 return (circ);
13962 }
13963
13964 }
13965 gr = gr->next;
13966 }
13967 return (NULL);
13968}
13969
13970/**
13971 * xmlSchemaCheckGroupDefCircular:
13972 * attrGr: the model group definition
13973 * @ctxt: the parser context
13974 * @name: the name
13975 *
13976 * Checks for circular references to model group definitions.
13977 */
13978static void
13979xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
13980 xmlSchemaParserCtxtPtr ctxt,
13981 const xmlChar * name ATTRIBUTE_UNUSED)
13982{
13983 /*
13984 * Schema Component Constraint: Model Group Correct
13985 * 2 Circular groups are disallowed. That is, within the {particles}
13986 * of a group there must not be at any depth a particle whose {term}
13987 * is the group itself.
13988 */
13989 /*
13990 * NOTE: "gr->subtypes" holds the referenced group.
13991 */
13992 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
13993 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
13994 (modelGrDef->subtypes == NULL))
13995 return;
13996 else {
13997 xmlSchemaTypePtr circ;
13998
13999 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
14000 if (circ != NULL) {
14001 /*
14002 * TODO: Report the referenced attr group as QName.
14003 */
14004 xmlSchemaPCustomErr(ctxt,
14005 XML_SCHEMAP_MG_PROPS_CORRECT_2,
14006 NULL, NULL, circ->node,
14007 "Circular reference to the model group definition '%s' "
14008 "defined", modelGrDef->name);
14009 /*
14010 * NOTE: We will cut the reference to avoid further
14011 * confusion of the processor.
14012 * TODO: SPEC: Does the spec define how to process here?
14013 */
14014 circ->subtypes = NULL;
14015 }
14016 }
14017}
14018
14019
14020/**
14021 * xmlSchemaGetCircAttrGrRef:
14022 * @ctxtGr: the searched attribute group
14023 * @attr: the current attribute list to be processed
14024 *
14025 * This one is intended to be used by
14026 * xmlSchemaCheckSRCAttributeGroupCircular only.
14027 *
14028 * Returns the circular attribute grou reference, otherwise NULL.
14029 */
14030static xmlSchemaAttributeGroupPtr
14031xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
14032 xmlSchemaAttributePtr attr)
14033{
14034 xmlSchemaAttributeGroupPtr circ = NULL, gr;
14035 int marked;
14036 /*
14037 * We will search for an attribute group reference which
14038 * references the context attribute group.
14039 */
14040 while (attr != NULL) {
14041 marked = 0;
14042 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
14043 gr = (xmlSchemaAttributeGroupPtr) attr;
14044 if (gr->refItem != NULL) {
14045 if (gr->refItem == ctxtGr)
14046 return (gr);
14047 else if (gr->refItem->flags &
14048 XML_SCHEMAS_ATTRGROUP_MARKED) {
14049 attr = attr->next;
14050 continue;
14051 } else {
14052 /*
14053 * Mark as visited to avoid infinite recursion on
14054 * circular references not yet examined.
14055 */
14056 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
14057 marked = 1;
14058 }
14059 }
14060 if (gr->attributes != NULL)
14061 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
14062 /*
14063 * Unmark the visited group's attributes.
14064 */
14065 if (marked)
14066 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
14067 if (circ != NULL)
14068 return (circ);
14069 }
14070 attr = attr->next;
14071 }
14072 return (NULL);
14073}
14074
14075/**
14076 * xmlSchemaCheckSRCAttributeGroupCircular:
14077 * attrGr: the attribute group definition
14078 * @ctxt: the parser context
14079 * @name: the name
14080 *
14081 * Checks for circular references of attribute groups.
14082 */
14083static void
14084xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
14085 xmlSchemaParserCtxtPtr ctxt,
14086 const xmlChar * name ATTRIBUTE_UNUSED)
14087{
14088 /*
14089 * Schema Representation Constraint:
14090 * Attribute Group Definition Representation OK
14091 * 3 Circular group reference is disallowed outside <redefine>.
14092 * That is, unless this element information item's parent is
14093 * <redefine>, then among the [children], if any, there must
14094 * not be an <attributeGroup> with ref [attribute] which resolves
14095 * to the component corresponding to this <attributeGroup>. Indirect
14096 * circularity is also ruled out. That is, when QName resolution
14097 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
14098 * any <attributeGroup>s with a ref [attribute] among the [children],
14099 * it must not be the case that a ·QName· is encountered at any depth
14100 * which resolves to the component corresponding to this <attributeGroup>.
14101 */
14102 /*
14103 * Only global components can be referenced.
14104 */
14105 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
14106 (attrGr->attributes == NULL))
14107 return;
14108 else {
14109 xmlSchemaAttributeGroupPtr circ;
14110
14111 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
14112 if (circ != NULL) {
14113 /*
14114 * TODO: Report the referenced attr group as QName.
14115 */
14116 xmlSchemaPCustomErr(ctxt,
14117 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
14118 NULL, NULL, circ->node,
14119 "Circular reference to the attribute group '%s' "
14120 "defined", attrGr->name);
14121 /*
14122 * NOTE: We will cut the reference to avoid further
14123 * confusion of the processor.
14124 * BADSPEC: The spec should define how to process in this case.
14125 */
14126 circ->attributes = NULL;
14127 circ->refItem = NULL;
14128 }
14129 }
14130}
14131
14132/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000014133 * xmlSchemaAttrGrpFixup:
14134 * @attrgrpDecl: the schema attribute definition
14135 * @ctxt: the schema parser context
14136 * @name: the attribute name
14137 *
14138 * Fixes finish doing the computations on the attributes definitions
14139 */
14140static void
Daniel Veillard3646d642004-06-02 19:19:14 +000014141xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014142 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000014143{
14144 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000014145 name = attrgrp->name;
14146 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014147 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000014148 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014149 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000014150
Daniel Veillardc0826a72004-08-10 14:17:33 +000014151 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
14152 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014153 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014154 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014155 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014156 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
14157 "ref", attrgrp->ref, attrgrp->refNs,
14158 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014159 return;
14160 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014161 attrgrp->refItem = ref;
14162 /*
14163 * Check for self reference!
14164 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014165 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000014166 attrgrp->attributes = ref->attributes;
14167 attrgrp->attributeWildcard = ref->attributeWildcard;
14168 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000014169}
14170
14171/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014172 * xmlSchemaAttrCheckValConstr:
14173 * @item: an schema attribute declaration/use
14174 * @ctxt: a schema parser context
14175 * @name: the name of the attribute
14176 *
14177 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000014178 *
14179 * Fixes finish doing the computations on the attributes definitions
14180 */
14181static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014182xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
14183 xmlSchemaParserCtxtPtr ctxt,
14184 const xmlChar * name ATTRIBUTE_UNUSED)
14185{
14186
14187 /*
14188 * a-props-correct
14189 * Schema Component Constraint: Attribute Declaration Properties Correct
14190 *
14191 * 2 if there is a {value constraint}, the canonical lexical
14192 * representation of its value must be ·valid· with respect
14193 * to the {type definition} as defined in String Valid (§3.14.4).
14194 */
14195
14196 if (item->defValue != NULL) {
14197 int ret;
14198 xmlNodePtr node;
14199 xmlSchemaTypePtr type;
14200
14201 if (item->subtypes == NULL) {
14202 xmlSchemaPErr(ctxt, item->node,
14203 XML_SCHEMAP_INTERNAL,
14204 "Internal error: xmlSchemaCheckAttrValConstr, "
14205 "type is missing... skipping validation of "
14206 "value constraint", NULL, NULL);
14207 return;
14208 }
14209
14210 /*
14211 * TODO: Try to avoid creating a new context.
14212 * TODO: This all is not very performant.
14213 */
14214 type = item->subtypes;
14215 /*
14216 * Ensure there's validation context.
14217 */
14218 if (ctxt->vctxt == NULL) {
14219 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
14220 xmlSchemaPErr(ctxt, item->node,
14221 XML_SCHEMAP_INTERNAL,
14222 "Internal error: xmlSchemaCheckAttrValConstr, "
14223 "creating a new validation context.\n",
14224 NULL, NULL);
14225 return;
14226 }
14227 }
14228
14229 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
14230 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
14231 else
14232 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
14233 ctxt->vctxt->node = node;
14234 ctxt->vctxt->cur = NULL;
14235 /*
14236 * NOTE: This call does not check the content nodes,
14237 * since they are not available:
14238 * facet->node is just the node holding the facet
14239 * definition, *not* the attribute holding the *value*
14240 * of the facet.
14241 */
14242 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
14243 item->defValue, 0, 1, 1, 0);
14244 if (ret == 0) {
14245 /*
14246 * Store the computed value.
14247 */
14248 item->defVal = ctxt->vctxt->value;
14249 ctxt->vctxt->value = NULL;
14250 } else if (ret > 0) {
14251 if (ctxt != NULL) {
14252 xmlSchemaPSimpleTypeErr(ctxt,
14253 XML_SCHEMAP_A_PROPS_CORRECT_2,
14254 NULL, NULL, node,
14255 type, NULL, item->defValue,
14256 NULL, NULL, NULL);
14257 }
14258 } else if (ret < 0) {
14259 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14260 NULL, NULL, node,
14261 "Internal error: xmlSchemaAttrCheckValConstr, "
14262 "failed to validate the value constraint of the "
14263 "attribute decl/use against the type '%s'",
14264 type->name);
14265 }
14266 }
14267}
14268
14269#if 0 /* Not used yet. */
14270static int
14271xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
14272 xmlSchemaElementPtr edecl)
14273{
14274 /*
14275 * TODO: 1 The values of the properties of an element declaration must be as
14276 * described in the property tableau in The Element Declaration Schema
14277 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
14278 */
14279 /*
14280 * 2 If there is a {value constraint}, the canonical lexical
14281 * representation of its value must be ·valid· with respect to the {type
14282 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14283 *
14284 * NOTE: This is done in xmlSchemaCheckElemValConstr.
14285 */
14286 /*
14287 * 3 If there is a non-·absent· {substitution group affiliation},
14288 * then {scope} must be global.
14289 *
14290 * NOTE: This is done in xmlSchemaParseElement.
14291 * TODO: Move it to this layer here.
14292 */
14293 /*
14294 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
14295 * of the element declaration must be validly derived from the {type
14296 * definition} of the {substitution group affiliation}, given the value
14297 * of the {substitution group exclusions} of the {substitution group
14298 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
14299 * (if the {type definition} is complex) or as defined in
14300 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
14301 * simple).
14302 */
14303 /*
14304 * TODO: 5 If the {type definition} or {type definition}'s {content type}
14305 * is or is derived from ID then there must not be a {value constraint}.
14306 * Note: The use of ID as a type definition for elements goes beyond
14307 * XML 1.0, and should be avoided if backwards compatibility is desired
14308 */
14309 /*
14310 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
14311 * be possible to return to an element declaration by repeatedly following
14312 * the {substitution group affiliation} property.
14313 */
14314}
14315#endif
14316
14317/**
14318 * xmlSchemaCheckElemValConstr:
14319 * @item: an schema element declaration/particle
14320 * @ctxt: a schema parser context
14321 * @name: the name of the attribute
14322 *
14323 * Validates the value constraints of an element declaration.
14324 *
14325 * Fixes finish doing the computations on the element declarations.
14326 */
14327static void
14328xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
14329 xmlSchemaParserCtxtPtr ctxt,
14330 const xmlChar * name ATTRIBUTE_UNUSED)
14331{
14332 if (decl->value != NULL) {
14333 int ret;
14334 xmlNodePtr node = NULL;
14335 xmlSchemaTypePtr type;
14336
14337 /*
14338 * 2 If there is a {value constraint}, the canonical lexical
14339 * representation of its value must be ·valid· with respect to the {type
14340 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14341 */
14342 if (decl->subtypes == NULL) {
14343 xmlSchemaPErr(ctxt, decl->node,
14344 XML_SCHEMAP_INTERNAL,
14345 "Internal error: xmlSchemaCheckElemValConstr, "
14346 "type is missing... skipping validation of "
14347 "the value constraint", NULL, NULL);
14348 return;
14349 }
14350 /*
14351 * Ensure there's a validation context.
14352 */
14353 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14354 return;
14355
14356 type = decl->subtypes;
14357
14358 if (decl->node != NULL) {
14359 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
14360 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
14361 else
14362 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
14363 }
14364 ctxt->vctxt->node = node;
14365 ctxt->vctxt->cur = NULL;
14366 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
14367 node);
14368 if (ret == 0) {
14369 /*
14370 * Consume the computed value.
14371 */
14372 decl->defVal = ctxt->vctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014373 ctxt->vctxt->value = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014374 } else if (ret < 0) {
14375 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14376 NULL, NULL, node,
14377 "Internal error: xmlSchemaElemCheckValConstr, "
14378 "failed to validate the value constraint of the "
14379 "element declaration '%s'",
14380 decl->name);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014381 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014382 }
14383}
14384
14385/**
14386 * xmlSchemaAttrFixup:
14387 * @item: an schema attribute declaration/use.
14388 * @ctxt: a schema parser context
14389 * @name: the name of the attribute
14390 *
14391 * Fixes finish doing the computations on attribute declarations/uses.
14392 */
14393static void
14394xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
14395 xmlSchemaParserCtxtPtr ctxt,
14396 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000014397{
Daniel Veillardc0826a72004-08-10 14:17:33 +000014398 /*
14399 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014400 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000014401 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014402 /*
14403 * The simple type definition corresponding to the <simpleType> element
14404 * information item in the [children], if present, otherwise the simple
14405 * type definition ·resolved· to by the ·actual value· of the type
14406 * [attribute], if present, otherwise the ·simple ur-type definition·.
14407 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014408 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014409 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014410 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
14411 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014412 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014413 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014414 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000014415
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014416 type = xmlSchemaGetType(ctxt->schema, item->typeName,
14417 item->typeNs);
14418 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014419 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014420 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014421 NULL, (xmlSchemaTypePtr) item, item->node,
14422 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014423 XML_SCHEMA_TYPE_SIMPLE, NULL);
14424 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014425 item->subtypes = type;
14426
14427 } else if (item->ref != NULL) {
14428 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000014429
Daniel Veillardc0826a72004-08-10 14:17:33 +000014430 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014431 * We have an attribute use here; assign the referenced
14432 * attribute declaration.
14433 */
14434 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014435 * TODO: Evaluate, what errors could occur if the declaration is not
14436 * found. It might be possible that the "typefixup" might crash if
14437 * no ref declaration was found.
14438 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014439 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
14440 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014441 xmlSchemaPResCompAttrErr(ctxt,
14442 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014443 NULL, (xmlSchemaTypePtr) item, item->node,
14444 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014445 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014446 return;
14447 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014448 item->refDecl = decl;
14449 xmlSchemaAttrFixup(decl, ctxt, NULL);
14450
14451 item->subtypes = decl->subtypes;
14452 /*
14453 * Attribute Use Correct
14454 * au-props-correct.2: If the {attribute declaration} has a fixed
14455 * {value constraint}, then if the attribute use itself has a
14456 * {value constraint}, it must also be fixed and its value must match
14457 * that of the {attribute declaration}'s {value constraint}.
14458 */
14459 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
14460 (item->defValue != NULL)) {
14461 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
14462 (!xmlStrEqual(item->defValue, decl->defValue))) {
14463 xmlSchemaPCustomErr(ctxt,
14464 XML_SCHEMAP_AU_PROPS_CORRECT_2,
14465 NULL, NULL, item->node,
14466 "The value constraint must be fixed "
14467 "and match the referenced attribute "
14468 "declarations's value constraint '%s'",
14469 decl->defValue);
14470 }
14471 /*
14472 * FUTURE: One should change the values of the attr. use
14473 * if ever validation should be attempted even if the
14474 * schema itself was not fully valid.
14475 */
14476 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014477 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014478 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14479 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014480}
14481
14482/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014483 * xmlSchemaResolveIDCKeyRef:
14484 * @idc: the identity-constraint definition
14485 * @ctxt: the schema parser context
14486 * @name: the attribute name
14487 *
14488 * Resolve keyRef references to key/unique IDCs.
14489 */
14490static void
14491xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
14492 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000014493 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014494{
14495 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
14496 return;
14497 if (idc->ref->name != NULL) {
14498 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
14499 ctxt->schema->idcDef,
14500 idc->ref->name,
14501 idc->ref->targetNamespace);
14502 if (idc->ref->item == NULL) {
14503 /*
14504 * TODO: It is actually not an error to fail to resolve.
14505 */
14506 xmlSchemaPResCompAttrErr(ctxt,
14507 XML_SCHEMAP_SRC_RESOLVE,
14508 NULL, (xmlSchemaTypePtr) idc, idc->node,
14509 "refer", idc->ref->name,
14510 idc->ref->targetNamespace,
14511 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
14512 return;
14513 }
14514 }
14515}
14516
14517/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014518 * xmlSchemaParse:
14519 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014520 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014521 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000014522 * XML Shema struture which can be used to validate instances.
14523 * *WARNING* this interface is highly subject to change
14524 *
14525 * Returns the internal XML Schema structure built from the resource or
14526 * NULL in case of error
14527 */
14528xmlSchemaPtr
14529xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
14530{
14531 xmlSchemaPtr ret = NULL;
14532 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014533 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014534 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014535
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014536 /*
14537 * This one is used if the schema to be parsed was specified via
14538 * the API; i.e. not automatically by the validated instance document.
14539 */
14540
Daniel Veillard4255d502002-04-16 15:50:10 +000014541 xmlSchemaInitTypes();
14542
Daniel Veillard6045c902002-10-09 21:13:59 +000014543 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000014544 return (NULL);
14545
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014546 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014547 ctxt->counter = 0;
14548 ctxt->container = NULL;
14549
14550 /*
14551 * First step is to parse the input document into an DOM/Infoset
14552 */
Daniel Veillard6045c902002-10-09 21:13:59 +000014553 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014554 doc = xmlReadFile((const char *) ctxt->URL, NULL,
14555 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014556 if (doc == NULL) {
14557 xmlSchemaPErr(ctxt, NULL,
14558 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014559 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014560 ctxt->URL, NULL);
14561 return (NULL);
14562 }
Daniel Veillard6045c902002-10-09 21:13:59 +000014563 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014564 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
14565 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014566 if (doc == NULL) {
14567 xmlSchemaPErr(ctxt, NULL,
14568 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014569 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014570 NULL, NULL);
14571 return (NULL);
14572 }
14573 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000014574 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000014575 } else if (ctxt->doc != NULL) {
14576 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014577 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000014578 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014579 xmlSchemaPErr(ctxt, NULL,
14580 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014581 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014582 NULL, NULL);
14583 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014584 }
14585
14586 /*
14587 * Then extract the root and Schema parse it
14588 */
14589 root = xmlDocGetRootElement(doc);
14590 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014591 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
14592 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014593 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000014594 if (!preserve) {
14595 xmlFreeDoc(doc);
14596 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014597 return (NULL);
14598 }
14599
14600 /*
14601 * Remove all the blank text nodes
14602 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014603 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000014604
14605 /*
14606 * Then do the parsing for good
14607 */
14608 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000014609 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000014610 if (!preserve) {
14611 xmlFreeDoc(doc);
14612 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014613 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000014614 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014615 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014616 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000014617 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014618 ctxt->ctxtType = NULL;
14619 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000014620 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000014621 * Then fixup all attributes declarations
14622 */
14623 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
14624
14625 /*
14626 * Then fixup all attributes group declarations
14627 */
14628 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
14629 ctxt);
14630
14631 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014632 * Resolve identity-constraint keyRefs.
14633 */
14634 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
14635
14636 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014637 * Check attribute groups for circular references.
14638 */
14639 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
14640 xmlSchemaCheckAttributeGroupCircular, ctxt);
14641
14642 /*
14643 * Then fixup all model group definitions.
14644 */
14645 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014646
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014647 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000014648 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000014649 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014650 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014651
14652 /*
14653 * Then fix references of element declaration; apply constraints.
14654 */
14655 xmlHashScanFull(ret->elemDecl,
14656 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014657
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014658 /*
14659 * Check model groups defnitions for circular references.
14660 */
14661 xmlHashScan(ret->groupDecl, (xmlHashScanner)
14662 xmlSchemaCheckGroupDefCircular, ctxt);
14663
Daniel Veillard4255d502002-04-16 15:50:10 +000014664 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014665 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000014666 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014667 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014668 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014669
14670 /*
14671 * Then check the defaults part of the type like facets values
14672 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014673 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000014674
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014675 /*
14676 * Validate the value constraint of attribute declarations/uses.
14677 */
14678 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
14679
14680 /*
14681 * Validate the value constraint of element declarations.
14682 */
14683 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
14684
Daniel Veillardc0826a72004-08-10 14:17:33 +000014685
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014686 if (ctxt->nberrors != 0) {
14687 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014688 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014689 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014690 return (ret);
14691}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014692
Daniel Veillard4255d502002-04-16 15:50:10 +000014693/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000014694 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000014695 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000014696 * @err: the error callback
14697 * @warn: the warning callback
14698 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000014699 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014700 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014701 */
14702void
14703xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014704 xmlSchemaValidityErrorFunc err,
14705 xmlSchemaValidityWarningFunc warn, void *ctx)
14706{
Daniel Veillard4255d502002-04-16 15:50:10 +000014707 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014708 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000014709 ctxt->error = err;
14710 ctxt->warning = warn;
14711 ctxt->userData = ctx;
14712}
14713
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014714/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000014715 * xmlSchemaGetParserErrors:
14716 * @ctxt: a XMl-Schema parser context
14717 * @err: the error callback result
14718 * @warn: the warning callback result
14719 * @ctx: contextual data for the callbacks result
14720 *
14721 * Get the callback information used to handle errors for a parser context
14722 *
14723 * Returns -1 in case of failure, 0 otherwise
14724 */
14725int
14726xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
14727 xmlSchemaValidityErrorFunc * err,
14728 xmlSchemaValidityWarningFunc * warn, void **ctx)
14729{
14730 if (ctxt == NULL)
14731 return(-1);
14732 if (err != NULL)
14733 *err = ctxt->error;
14734 if (warn != NULL)
14735 *warn = ctxt->warning;
14736 if (ctx != NULL)
14737 *ctx = ctxt->userData;
14738 return(0);
14739}
14740
14741/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014742 * xmlSchemaFacetTypeToString:
14743 * @type: the facet type
14744 *
14745 * Convert the xmlSchemaTypeType to a char string.
14746 *
14747 * Returns the char string representation of the facet type if the
14748 * type is a facet and an "Internal Error" string otherwise.
14749 */
14750static const char *
14751xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
14752{
14753 switch (type) {
14754 case XML_SCHEMA_FACET_PATTERN:
14755 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014756 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014757 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014758 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014759 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014760 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014761 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014762 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014763 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014764 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014765 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014766 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014767 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014768 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014769 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014770 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014771 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014772 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014773 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014774 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014775 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014776 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014777 return ("fractionDigits");
14778 default:
14779 break;
14780 }
14781 return ("Internal Error");
14782}
14783
Daniel Veillardc0826a72004-08-10 14:17:33 +000014784static int
14785xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
14786{
14787 xmlSchemaTypePtr anc;
14788
14789 /*
14790 * The normalization type can be changed only for types which are derived
14791 * from xsd:string.
14792 */
14793 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000014794 if (type->builtInType == XML_SCHEMAS_STRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014795 return(XML_SCHEMAS_FACET_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000014796 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014797 return(XML_SCHEMAS_FACET_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014798 else {
14799 /*
14800 * For all ·atomic· datatypes other than string (and types ·derived·
14801 * by ·restriction· from it) the value of whiteSpace is fixed to
14802 * collapse
14803 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014804 return(XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014805 }
14806 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14807 /*
14808 * For list types the facet "whiteSpace" is fixed to "collapse".
14809 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014810 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014811 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014812 return (XML_SCHEMAS_FACET_UNKNOWN);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014813 } else if (type->facetSet != NULL) {
14814 xmlSchemaTypePtr anyST;
14815 xmlSchemaFacetLinkPtr lin;
14816
14817 /*
14818 * Atomic types.
14819 */
14820 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14821 anc = type->baseType;
14822 do {
14823 /*
14824 * For all ·atomic· datatypes other than string (and types ·derived·
14825 * by ·restriction· from it) the value of whiteSpace is fixed to
14826 * collapse
14827 */
14828 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
14829 (anc->builtInType == XML_SCHEMAS_STRING)) {
14830
14831 lin = type->facetSet;
14832 do {
14833 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014834 return(lin->facet->whitespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014835 break;
14836 }
14837 lin = lin->next;
14838 } while (lin != NULL);
14839 break;
14840 }
14841 anc = anc->baseType;
14842 } while (anc != anyST);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014843 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014844 }
14845 return (-1);
14846}
14847
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014848/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000014849 * xmlSchemaValidateFacetsInternal:
14850 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000014851 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000014852 * @facets: the list of facets to check
14853 * @value: the lexical repr of the value to validate
14854 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000014855 * @fireErrors: if 0, only internal errors will be fired;
14856 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000014857 *
14858 * Check a value against all facet conditions
14859 *
14860 * Returns 0 if the element is schemas valid, a positive error code
14861 * number otherwise and -1 in case of internal or API error.
14862 */
14863static int
14864xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014865 xmlSchemaTypePtr type,
14866 const xmlChar * value,
14867 unsigned long length,
14868 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000014869{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014870 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014871 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014872 xmlSchemaTypePtr biType; /* The build-in type. */
14873 xmlSchemaTypePtr tmpType;
14874 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000014875 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014876 xmlSchemaFacetPtr facet;
14877 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014878
Daniel Veillardc0826a72004-08-10 14:17:33 +000014879#ifdef DEBUG_UNION_VALIDATION
14880 printf("Facets of type: '%s'\n", (const char *) type->name);
14881 printf(" fireErrors: %d\n", fireErrors);
14882#endif
14883
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014884 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014885 /*
14886 * NOTE: Do not jump away, if the facetSet of the given type is
14887 * empty: until now, "pattern" facets of the *base types* need to
14888 * be checked as well.
14889 */
14890 biType = type->baseType;
14891 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
14892 biType = biType->baseType;
14893 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014894 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014895 "Internal error: xmlSchemaValidateFacetsInternal, "
14896 "the base type axis of the given type '%s' does not resolve to "
14897 "a built-in type.\n",
14898 type->name, NULL);
14899 return (-1);
14900 }
14901
14902 if (type->facetSet != NULL) {
14903 facetLink = type->facetSet;
14904 while (facetLink != NULL) {
14905 facet = facetLink->facet;
14906 /*
14907 * Skip the pattern "whiteSpace": it is used to
14908 * format the character content beforehand.
14909 */
14910 switch (facet->type) {
14911 case XML_SCHEMA_FACET_WHITESPACE:
14912 case XML_SCHEMA_FACET_PATTERN:
14913 case XML_SCHEMA_FACET_ENUMERATION:
14914 break;
14915 case XML_SCHEMA_FACET_LENGTH:
14916 case XML_SCHEMA_FACET_MINLENGTH:
14917 case XML_SCHEMA_FACET_MAXLENGTH:
14918 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14919 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
14920 value, length, 0);
14921 len = length;
14922 } else
14923 ret = xmlSchemaValidateLengthFacet(biType, facet,
14924 value, ctxt->value, &len);
14925 break;
14926 default:
14927 ret = xmlSchemaValidateFacet(biType, facet, value,
14928 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014929 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014930 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014931 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014932 "Internal error: xmlSchemaValidateFacetsInternal, "
14933 "validating facet of type '%s'.\n",
14934 type->name, NULL);
14935 break;
14936 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014937 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014938 type, facet, NULL, NULL, NULL, NULL);
14939 }
14940
14941 facetLink = facetLink->next;
14942 }
14943 if (ret >= 0) {
14944 /*
14945 * Process enumerations.
14946 */
14947 retFacet = 0;
14948 facetLink = type->facetSet;
14949 while (facetLink != NULL) {
14950 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
14951 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
14952 value, ctxt->value);
14953 if (retFacet <= 0)
14954 break;
14955 }
14956 facetLink = facetLink->next;
14957 }
14958 if (retFacet > 0) {
14959 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
14960 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014961 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014962 value, 0, type, NULL, NULL, NULL, NULL, NULL);
14963 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014964 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014965 "Internal error: xmlSchemaValidateFacetsInternal, "
14966 "validating facet of type '%s'.\n",
14967 BAD_CAST "enumeration", NULL);
14968 ret = -1;
14969 }
14970 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014971 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014972 if (ret >= 0) {
14973 /*
14974 * Process patters. Pattern facets are ORed at type level
14975 * and ANDed if derived. Walk the base type axis.
14976 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014977 tmpType = type;
14978 facet = NULL;
14979 do {
14980 retFacet = 0;
14981 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014982 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014983 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
14984 continue;
14985 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
14986 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014987 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014988 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014989 else if (retFacet < 0) {
14990 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
14991 "Internal error: xmlSchemaValidateFacetsInternal, "
14992 "validating 'pattern' facet '%s' of type '%s'.\n",
14993 facetLink->facet->value, tmpType->name);
14994 ret = -1;
14995 break;
14996 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000014997 /* Save the last non-validating facet. */
14998 facet = facetLink->facet;
14999 }
15000 if (retFacet != 0)
15001 break;
15002 tmpType = tmpType->baseType;
15003 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015004 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015005 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
15006 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015007 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015008 NULL, NULL, NULL, NULL);
15009 }
15010 }
15011 }
15012
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015013 return (ret);
15014}
15015
Daniel Veillard4255d502002-04-16 15:50:10 +000015016/************************************************************************
15017 * *
15018 * Simple type validation *
15019 * *
15020 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000015021
Daniel Veillard4255d502002-04-16 15:50:10 +000015022
15023/************************************************************************
15024 * *
15025 * DOM Validation code *
15026 * *
15027 ************************************************************************/
15028
Daniel Veillard4255d502002-04-16 15:50:10 +000015029static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015030 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000015031 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015032static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015033 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000015034 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015035 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000015036
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015037static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015038static int xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015039
15040#ifdef ELEM_INFO_ENABLED
15041/**
15042 * xmlSchemaGetFreshElemInfo:
15043 * @vctxt: the schema validation context
15044 *
15045 * Creates/reuses and initializes the element info item for
15046 * the currect tree depth.
15047 *
15048 * Returns the element info item or NULL on API or internal errors.
15049 */
15050static xmlSchemaElemInfoPtr
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015051xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt,
15052 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015053{
15054 xmlSchemaElemInfoPtr info = NULL;
15055
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015056 if (depth > vctxt->sizeElemInfos) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015057 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015058 "Internal error: xmlSchemaGetFreshElemInfo, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015059 "an inconsistent depth encountered.\n",
15060 NULL, NULL);
15061 return (NULL);
15062 }
15063 if (vctxt->elemInfos == NULL) {
15064 vctxt->elemInfos = (xmlSchemaElemInfoPtr *)
15065 xmlMalloc(10 * sizeof(xmlSchemaElemInfoPtr));
15066 if (vctxt->elemInfos == NULL) {
15067 xmlSchemaVErrMemory(vctxt,
15068 "allocating the element info array", NULL);
15069 return (NULL);
15070 }
15071 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaElemInfoPtr));
15072 vctxt->sizeElemInfos = 10;
15073 } else if (vctxt->sizeElemInfos == vctxt->depth) {
15074 int i = vctxt->sizeElemInfos;
15075
15076 vctxt->sizeElemInfos *= 2;
15077 vctxt->elemInfos = (xmlSchemaElemInfoPtr *)
15078 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
15079 sizeof(xmlSchemaElemInfoPtr));
15080 if (vctxt->elemInfos == NULL) {
15081 xmlSchemaVErrMemory(vctxt,
15082 "re-allocating the element info array", NULL);
15083 return (NULL);
15084 }
15085 /*
15086 * We need the new memory to be NULLed.
15087 * TODO: Use memset instead?
15088 */
15089 for (; i < vctxt->sizeElemInfos; i++)
15090 vctxt->elemInfos[i] = NULL;
15091 } else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015092 info = vctxt->elemInfos[depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015093
15094 if (info == NULL) {
15095 info = (xmlSchemaElemInfoPtr)
15096 xmlMalloc(sizeof(xmlSchemaElemInfo));
15097 if (info == NULL) {
15098 xmlSchemaVErrMemory(vctxt,
15099 "allocating an element info", NULL);
15100 return (NULL);
15101 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015102 vctxt->elemInfos[depth] = info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015103 }
15104 memset(info, 0, sizeof(xmlSchemaElemInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015105 info->depth = depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015106
15107 return (info);
15108}
15109#endif /* ELEM_INFO_ENABLED */
15110
Daniel Veillard3646d642004-06-02 19:19:14 +000015111
15112/**
15113 * xmlSchemaFreeAttrStates:
15114 * @state: a list of attribute states
15115 *
15116 * Free the given list of attribute states
15117 *
15118 */
15119static void
15120xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
15121{
15122 xmlSchemaAttrStatePtr tmp;
15123 while (state != NULL) {
15124 tmp = state;
15125 state = state->next;
15126 xmlFree(tmp);
15127 }
15128}
15129
Daniel Veillard4255d502002-04-16 15:50:10 +000015130/**
15131 * xmlSchemaRegisterAttributes:
15132 * @ctxt: a schema validation context
15133 * @attrs: a list of attributes
15134 *
15135 * Register the list of attributes as the set to be validated on that element
15136 *
15137 * Returns -1 in case of error, 0 otherwise
15138 */
15139static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015140xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
15141{
Daniel Veillard3646d642004-06-02 19:19:14 +000015142 xmlSchemaAttrStatePtr tmp;
15143
15144 ctxt->attr = NULL;
15145 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015146 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015147 if ((attrs->ns != NULL) &&
15148 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
15149 attrs = attrs->next;
15150 continue;
15151 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015152 tmp = (xmlSchemaAttrStatePtr)
15153 xmlMalloc(sizeof(xmlSchemaAttrState));
15154 if (tmp == NULL) {
15155 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
15156 return (-1);
15157 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015158 tmp->attr = attrs;
15159 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
15160 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015161 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015162 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015163 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000015164 else
15165 ctxt->attrTop->next = tmp;
15166 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015167 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015168 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015169 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000015170}
15171
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015172#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000015173/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015174 * xmlSchemaValidateCheckNodeList
15175 * @nodelist: the list of nodes
15176 *
15177 * Check the node list is only made of text nodes and entities pointing
15178 * to text nodes
15179 *
15180 * Returns 1 if true, 0 if false and -1 in case of error
15181 */
15182static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015183xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
15184{
Daniel Veillard4255d502002-04-16 15:50:10 +000015185 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015186 if (nodelist->type == XML_ENTITY_REF_NODE) {
15187 TODO /* implement recursion in the entity content */
15188 }
15189 if ((nodelist->type != XML_TEXT_NODE) &&
15190 (nodelist->type != XML_COMMENT_NODE) &&
15191 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000015192 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015193 return (0);
15194 }
15195 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015196 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015197 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015198}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015199#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015200
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015201static void
15202xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
15203{
15204 int i, nbItems;
15205 xmlSchemaTypePtr item, *items;
15206
15207
15208 /*
15209 * During the Assemble of the schema ctxt->curItems has
15210 * been filled with the relevant new items. Fix those up.
15211 */
15212 nbItems = ctxt->assemble->nbItems;
15213 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
15214
15215 for (i = 0; i < nbItems; i++) {
15216 item = items[i];
15217 switch (item->type) {
15218 case XML_SCHEMA_TYPE_ATTRIBUTE:
15219 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
15220 break;
15221 case XML_SCHEMA_TYPE_ELEMENT:
15222 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
15223 NULL, NULL, NULL);
15224 break;
15225 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15226 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
15227 ctxt, NULL);
15228 break;
15229 case XML_SCHEMA_TYPE_GROUP:
15230 xmlSchemaGroupDefFixup(item, ctxt, NULL);
15231 default:
15232 break;
15233 }
15234 }
15235 /*
15236 * Circularity checks.
15237 */
15238 for (i = 0; i < nbItems; i++) {
15239 item = items[i];
15240 switch (item->type) {
15241 case XML_SCHEMA_TYPE_GROUP:
15242 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
15243 break;
15244 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15245 xmlSchemaCheckAttributeGroupCircular(
15246 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
15247 break;
15248 default:
15249 break;
15250 }
15251 }
15252 /*
15253 * Fixup for all other item.
15254 * TODO: Hmm, not sure if starting from complex/simple types,
15255 * all subsequent items will be reached.
15256 */
15257 for (i = 0; i < nbItems; i++) {
15258 item = items[i];
15259 switch (item->type) {
15260 case XML_SCHEMA_TYPE_SIMPLE:
15261 case XML_SCHEMA_TYPE_COMPLEX:
15262 xmlSchemaTypeFixup(item, ctxt, NULL);
15263 break;
15264 default:
15265 break;
15266 }
15267 }
15268 /*
15269 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015270 * hold by simple type components only (and
15271 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015272 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015273 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015274 for (i = 0; i < nbItems; i++) {
15275 item = items[i];
15276 switch (item->type) {
15277 case XML_SCHEMA_TYPE_SIMPLE:
15278 case XML_SCHEMA_TYPE_COMPLEX:
15279 xmlSchemaCheckDefaults(item, ctxt, NULL);
15280 break;
15281 default:
15282 break;
15283 }
15284 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015285 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015286 /*
15287 * Build the content model for complex types.
15288 */
15289 for (i = 0; i < nbItems; i++) {
15290 item = items[i];
15291 switch (item->type) {
15292 case XML_SCHEMA_TYPE_COMPLEX:
15293 xmlSchemaBuildContentModel(item, ctxt, NULL);
15294 break;
15295 default:
15296 break;
15297 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015298 }
15299 /*
15300 * Validate value contraint values.
15301 */
15302 for (i = 0; i < nbItems; i++) {
15303 item = items[i];
15304 switch (item->type) {
15305 case XML_SCHEMA_TYPE_ATTRIBUTE:
15306 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
15307 break;
15308 case XML_SCHEMA_TYPE_ELEMENT:
15309 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
15310 break;
15311 default:
15312 break;
15313 }
15314 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015315}
15316
15317/**
15318 * xmlSchemaAssembleByLocation:
15319 * @pctxt: a schema parser context
15320 * @vctxt: a schema validation context
15321 * @schema: the existing schema
15322 * @node: the node that fired the assembling
15323 * @nsName: the namespace name of the new schema
15324 * @location: the location of the schema
15325 *
15326 * Expands an existing schema by an additional schema.
15327 *
15328 * Returns 0 if the new schema is correct, a positive error code
15329 * number otherwise and -1 in case of an internal or API error.
15330 */
15331static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015332xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
15333 xmlSchemaPtr schema,
15334 xmlNodePtr node,
15335 const xmlChar *nsName,
15336 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015337{
15338 const xmlChar *targetNs, *oldtns;
15339 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015340 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015341 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015342 xmlSchemaParserCtxtPtr pctxt;
15343
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015344 /*
15345 * This should be used:
15346 * 1. on <import>(s)
15347 * 2. if requested by the validated instance
15348 * 3. if requested via the API
15349 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015350 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015351 return (-1);
15352 /*
15353 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015354 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015355 if ((vctxt->pctxt == NULL) &&
15356 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
15357 xmlSchemaVErr(vctxt, node,
15358 XML_SCHEMAV_INTERNAL,
15359 "Internal error: xmlSchemaAssembleByLocation, "
15360 "failed to create a temp. parser context.\n",
15361 NULL, NULL);
15362 return (-1);
15363 }
15364 pctxt = vctxt->pctxt;
15365 /*
15366 * Set the counter to produce unique names for anonymous items.
15367 */
15368 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015369 /*
15370 * Acquire the schema document.
15371 */
15372 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
15373 nsName, location, &doc, &targetNs, 0);
15374 if (ret != 0) {
15375 if (doc != NULL)
15376 xmlFreeDoc(doc);
15377 } else if (doc != NULL) {
15378 docElem = xmlDocGetRootElement(doc);
15379 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015380 * Create new assemble info.
15381 */
15382 if (pctxt->assemble == NULL) {
15383 pctxt->assemble = xmlSchemaNewAssemble();
15384 if (pctxt->assemble == NULL) {
15385 xmlSchemaVErrMemory(vctxt,
15386 "Memory error: xmlSchemaAssembleByLocation, "
15387 "allocating assemble info", NULL);
15388 xmlFreeDoc(doc);
15389 return (-1);
15390 }
15391 }
15392 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015393 * Save and reset the context & schema.
15394 */
15395 oldflags = schema->flags;
15396 oldtns = schema->targetNamespace;
15397 olddoc = schema->doc;
15398
15399 xmlSchemaClearSchemaDefaults(schema);
15400 schema->targetNamespace = targetNs;
15401 /* schema->nbCurItems = 0; */
15402 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015403 pctxt->ctxtType = NULL;
15404 pctxt->parentItem = NULL;
15405
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015406 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
15407 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015408 xmlSchemaPostSchemaAssembleFixup(pctxt);
15409 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015410 * Set the counter of items.
15411 */
15412 schema->counter = pctxt->counter;
15413 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015414 * Free the list of assembled components.
15415 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015416 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015417 /*
15418 * Restore the context & schema.
15419 */
15420 schema->flags = oldflags;
15421 schema->targetNamespace = oldtns;
15422 schema->doc = olddoc;
15423 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015424 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015425 return (ret);
15426}
15427
15428/**
15429 * xmlSchemaAssembleByXSIAttr:
15430 * @vctxt: a schema validation context
15431 * @xsiAttr: an xsi attribute
15432 * @noNamespace: whether a schema with no target namespace is exptected
15433 *
15434 * Expands an existing schema by an additional schema using
15435 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
15436 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
15437 * must be set to 1.
15438 *
15439 * Returns 0 if the new schema is correct, a positive error code
15440 * number otherwise and -1 in case of an internal or API error.
15441 */
15442static int
15443xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
15444 xmlAttrPtr xsiAttr,
15445 int noNamespace)
15446{
15447 xmlChar *value;
15448 const xmlChar *cur, *end;
15449 const xmlChar *nsname = NULL, *location;
15450 int count = 0;
15451 int ret = 0;
15452
15453 if (xsiAttr == NULL) {
15454 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
15455 NULL, NULL,
15456 "Internal error: xmlSchemaAssembleByXSIAttr, "
15457 "bad arguments", NULL);
15458 return (-1);
15459 }
15460 /*
15461 * Parse the value; we will assume an even number of values
15462 * to be given (this is how Xerces and XSV work).
15463 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015464 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015465 cur = value;
15466 do {
15467 if (noNamespace != 1) {
15468 /*
15469 * Get the namespace name.
15470 */
15471 while (IS_BLANK_CH(*cur))
15472 cur++;
15473 end = cur;
15474 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15475 end++;
15476 if (end == cur)
15477 break;
15478 count++;
15479 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
15480 cur = end;
15481 }
15482 /*
15483 * Get the URI.
15484 */
15485 while (IS_BLANK_CH(*cur))
15486 cur++;
15487 end = cur;
15488 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15489 end++;
15490 if (end == cur)
15491 break;
15492 count++;
15493 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015494 cur = end;
15495 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015496 xsiAttr->parent, nsname, location);
15497 if (ret == -1) {
15498 xmlSchemaVCustomErr(vctxt,
15499 XML_SCHEMAV_INTERNAL,
15500 (xmlNodePtr) xsiAttr, NULL,
15501 "Internal error: xmlSchemaAssembleByXSIAttr, "
15502 "assembling schemata", NULL);
15503 if (value != NULL)
15504 xmlFree(value);
15505 return (-1);
15506 }
15507 } while (*cur != 0);
15508 if (value != NULL)
15509 xmlFree(value);
15510 return (ret);
15511}
15512
15513/**
15514 * xmlSchemaAssembleByXSIElem:
15515 * @vctxt: a schema validation context
15516 * @elem: an element node possibly holding xsi attributes
15517 * @noNamespace: whether a schema with no target namespace is exptected
15518 *
15519 * Assembles an existing schema by an additional schema using
15520 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
15521 * of the given @elem.
15522 *
15523 * Returns 0 if the new schema is correct, a positive error code
15524 * number otherwise and -1 in case of an internal or API error.
15525 */
15526static int
15527xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
15528 xmlNodePtr elem)
15529{
15530 int ret = 0, retNs = 0;
15531 xmlAttrPtr attr;
15532
15533 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
15534 if (attr != NULL) {
15535 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
15536 if (retNs == -1)
15537 return (-1);
15538 }
15539 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
15540 if (attr != NULL) {
15541 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
15542 if (ret == -1)
15543 return (-1);
15544 }
15545 if (retNs != 0)
15546 return (retNs);
15547 else
15548 return (ret);
15549}
15550
Daniel Veillard4255d502002-04-16 15:50:10 +000015551/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015552 * xmlSchemaValidateCallback:
15553 * @ctxt: a schema validation context
15554 * @name: the name of the element detected (might be NULL)
15555 * @type: the type
15556 *
15557 * A transition has been made in the automata associated to an element
15558 * content model
15559 */
15560static void
15561xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015562 const xmlChar * name ATTRIBUTE_UNUSED,
15563 xmlSchemaTypePtr type, xmlNodePtr node)
15564{
Daniel Veillard4255d502002-04-16 15:50:10 +000015565 xmlSchemaTypePtr oldtype = ctxt->type;
15566 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015567
Daniel Veillard4255d502002-04-16 15:50:10 +000015568#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000015569 xmlGenericError(xmlGenericErrorContext,
15570 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015571 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000015572#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015573 /*
15574 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
15575 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015576 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015577 ctxt->node = node;
15578 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015579
15580#ifdef ELEM_INFO_ENABLED
15581 xmlSchemaBeginElement(ctxt);
15582#endif
15583
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015584 /*
15585 * Assemble new schemata using xsi.
15586 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015587 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015588 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015589
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015590 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15591 if (ret == -1) {
15592 xmlSchemaVCustomErr(ctxt,
15593 XML_SCHEMAV_INTERNAL,
15594 ctxt->node, NULL,
15595 "Internal error: xmlSchemaValidateElement, "
15596 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015597 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015598 }
15599 /*
15600 * NOTE: We won't react on schema parser errors here.
15601 * TODO: But a warning would be nice.
15602 */
15603 }
15604 switch (type->type) {
15605 case XML_SCHEMA_TYPE_ELEMENT: {
15606 /*
15607 * NOTE: The build of the content model
15608 * (xmlSchemaBuildAContentModel) ensures that the element
15609 * declaration (and not a reference to it) will be given.
15610 */
15611 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
15612 /*
15613 * This is paranoid coding ;-)... it should not
15614 * happen here any more.
15615 */
15616 xmlSchemaVCustomErr(ctxt,
15617 XML_SCHEMAV_INTERNAL,
15618 node, NULL,
15619 "Internal error: xmlSchemaValidateCallback, "
15620 "element declaration 'reference' encountered, "
15621 "but an element declaration was expected",
15622 NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015623 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015624 }
15625 xmlSchemaValidateElementByDeclaration(ctxt,
15626 (xmlSchemaElementPtr) type);
15627 break;
15628 }
15629 case XML_SCHEMA_TYPE_ANY:
15630 xmlSchemaValidateElementByWildcard(ctxt, type);
15631 break;
15632 default:
15633 break;
15634 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015635leave:
15636
15637#ifdef ELEM_INFO_ENABLED
15638 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015639#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015640 ctxt->type = oldtype;
15641 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015642}
Daniel Veillard4255d502002-04-16 15:50:10 +000015643
Daniel Veillard01fa6152004-06-29 17:04:39 +000015644/**
15645 * xmlSchemaValidateSimpleTypeValue:
15646 * @ctxt: a schema validation context
15647 * @value: the value to be validated
15648 * @fireErrors: shall errors be reported?
15649 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015650 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015651 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000015652 *
15653 * Validates a value by the given type (user derived or built-in).
15654 *
15655 * Returns 0 if the value is valid, a positive error code
15656 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015657 */
15658static int
15659xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015660 xmlSchemaTypePtr type,
15661 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015662 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015663 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015664 int normalize,
15665 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015666{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015667 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015668 int ret = 0;
15669 xmlChar *normValue = NULL;
15670 int wtsp;
15671
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015672 node = ctxt->node;
15673 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015674 wtsp = ctxt->valueWS;
15675 /*
15676 * Normalize the value.
15677 */
15678 if (normalize &&
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015679 (ctxt->valueWS != XML_SCHEMAS_FACET_COLLAPSE)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015680 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
15681
15682 if ((norm != -1) && (norm > ctxt->valueWS)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015683 if (norm == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015684 normValue = xmlSchemaCollapseString(value);
15685 else
15686 normValue = xmlSchemaWhiteSpaceReplace(value);
15687 ctxt->valueWS = norm;
15688 if (normValue != NULL)
15689 value = (const xmlChar *) normValue;
15690 }
15691 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015692 /*
15693 * The nodes of a content must be checked only once,
15694 * this is not working since list types will fire this
15695 * multiple times.
15696 */
15697 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
15698 xmlNodePtr cur = ctxt->cur;
15699
15700 do {
15701 switch (cur->type) {
15702 case XML_TEXT_NODE:
15703 case XML_CDATA_SECTION_NODE:
15704 case XML_PI_NODE:
15705 case XML_COMMENT_NODE:
15706 case XML_XINCLUDE_START:
15707 case XML_XINCLUDE_END:
15708 break;
15709 case XML_ENTITY_REF_NODE:
15710 case XML_ENTITY_NODE:
15711 /* TODO: Scour the entities for illegal nodes. */
15712 TODO break;
15713 case XML_ELEMENT_NODE: {
15714 /* NOTE: Changed to an internal error, since the
15715 * existence of an element node will be already checked in
15716 * xmlSchemaValidateElementBySimpleType and in
15717 * xmlSchemaValidateElementByComplexType.
15718 */
15719 xmlSchemaVCustomErr(ctxt,
15720 XML_SCHEMAV_INTERNAL,
15721 /* XML_SCHEMAS_ERR_INVALIDELEM, */
15722 node, type,
15723 "Element '%s' found in simple type content",
15724 cur->name);
15725 return (XML_SCHEMAV_INTERNAL);
15726 }
15727 case XML_ATTRIBUTE_NODE:
15728 case XML_DOCUMENT_NODE:
15729 case XML_DOCUMENT_TYPE_NODE:
15730 case XML_DOCUMENT_FRAG_NODE:
15731 case XML_NOTATION_NODE:
15732 case XML_HTML_DOCUMENT_NODE:
15733 case XML_DTD_NODE:
15734 case XML_ELEMENT_DECL:
15735 case XML_ATTRIBUTE_DECL:
15736 case XML_ENTITY_DECL:
15737 case XML_NAMESPACE_DECL:
15738#ifdef LIBXML_DOCB_ENABLED
15739 case XML_DOCB_DOCUMENT_NODE:
15740#endif
15741 xmlSchemaVCustomErr(ctxt,
15742 XML_SCHEMAV_INTERNAL,
15743 /* XML_SCHEMAS_ERR_INVALIDELEM, */
15744 node, NULL,
15745 "Node of unexpected type found in simple type content",
15746 NULL);
15747 return (XML_SCHEMAV_INTERNAL);
15748 }
15749 cur = cur->next;
15750 } while (cur != NULL);
15751 }
15752
William M. Brack2f2a6632004-08-20 23:09:47 +000015753 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
15754 xmlSchemaTypePtr base, anyType;
15755
15756 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
15757
15758 base = type->baseType;
15759 while ((base != NULL) &&
15760 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
15761 (base->type != XML_SCHEMA_TYPE_BASIC) &&
15762 (base != anyType)) {
15763 base = base->baseType;
15764 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015765 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015766 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015767 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015768 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15769 "validating complex type '%s'\n",
15770 type->name, NULL);
15771 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
15772 /*
15773 * Check facets.
15774 */
15775 /*
15776 * This is somehow not nice, since if an error occurs
15777 * the reported type will be the complex type; the spec
15778 * wants a simple type to be created on the complex type
15779 * if it has a simple content. For now we have to live with
15780 * it.
15781 */
15782 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15783 value, 0, fireErrors);
15784 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015785 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015786 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15787 "validating facets of complex type '%s'\n",
15788 type->name, NULL);
15789 } else if (ret > 0) {
15790 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000015791 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015792 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000015793 }
15794 }
15795 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015796
15797 if (ctxt->value != NULL) {
15798 xmlSchemaFreeValue(ctxt->value);
15799 ctxt->value = NULL;
15800 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015801 /*
15802 * STREAM-READ-CHILDREN.
15803 */
15804 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015805 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015806 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
15807 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
15808 else
15809 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015810 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015811 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015812 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015813 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015814 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015815 "validating built-in type '%s'\n", type->name, NULL);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015816 } else if ((ctxt->value == NULL) &&
15817 (type->builtInType == XML_SCHEMAS_STRING) &&
15818 (ctxt->nodeInfo != NULL) &&
15819 (ctxt->nodeInfo->flags & XML_SCHEMA_ELEM_INFO_VALUE_NEEDED)) {
15820#ifdef IDC_VALUE_SUPPORT
15821 xmlChar *valdup;
15822 /*
15823 * Create a precomputed string value for "string" as well if
15824 * requested.
15825 */
15826 valdup = xmlStrdup(value);
15827 ctxt->value = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
15828 BAD_CAST valdup);
15829 if ((valdup != NULL) && (ctxt->value == NULL))
15830 xmlFree(valdup);
15831#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015832 }
15833 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
15834 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
15835 * a literal in the ·lexical space· of {base type definition}
15836 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015837 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015838 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015839 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015840 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015841 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015842 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015843 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015844 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015845 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015846 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015847 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015848 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015849 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015850 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015851 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15852 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015853 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015854 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015855 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015856 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015857 type->name, NULL);
15858 } else if (ret > 0) {
15859 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015860 /*
15861 Disabled, since the facet validation already reports errors.
15862 if (fireErrors)
15863 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
15864 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015865 }
15866 }
15867 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15868
15869 xmlSchemaTypePtr tmpType;
15870 const xmlChar *cur, *end;
15871 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015872 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015873
15874 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
15875 * of white space separated tokens, each of which ·match·es a literal
15876 * in the ·lexical space· of {item type definition}
15877 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000015878
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000015879 if (value == NULL)
15880 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000015881 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015882 cur = value;
15883 do {
15884 while (IS_BLANK_CH(*cur))
15885 cur++;
15886 end = cur;
15887 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15888 end++;
15889 if (end == cur)
15890 break;
15891 tmp = xmlStrndup(cur, end - cur);
15892 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015893 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015894 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015895 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015896 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015897 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15898 "validating an item of list simple type '%s'\n",
15899 type->name, NULL);
15900 break;
15901 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015902 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015903 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015904 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015905 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015906 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015907 cur = end;
15908 } while (*cur != 0);
15909 /*
15910 * Check facets.
15911 */
15912 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015913 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015914 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015915 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015916 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015917 } else if ((ret == 0) && (applyFacets)) {
15918 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15919 value, len, fireErrors);
15920 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015921 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015922 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15923 "validating facets of list simple type '%s'\n",
15924 type->name, NULL);
15925 } else if (ret > 0) {
15926 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015927 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015928 Disabled, since the facet validation already reports errors.
15929 if (fireErrors)
15930 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015931 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015932 }
15933
Daniel Veillard01fa6152004-06-29 17:04:39 +000015934 }
15935 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
15936 xmlSchemaTypeLinkPtr memberLink;
15937
15938 /*
15939 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
15940 * not apply directly; however, the normalization behavior of ·union·
15941 * types is controlled by the value of whiteSpace on that one of the
15942 * ·memberTypes· against which the ·union· is successfully validated.
15943 *
15944 * This means that the value is normalized by the first validating
15945 * member type, then the facets of the union type are applied. This
15946 * needs changing of the value!
15947 */
15948
15949 /*
15950 * 1.2.3 if {variety} is ·union· then the string must ·match· a
15951 * literal in the ·lexical space· of at least one member of
15952 * {member type definitions}
15953 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015954#ifdef DEBUG_UNION_VALIDATION
15955 printf("Union ST : '%s'\n", (const char *) type->name);
15956 printf(" fireErrors : %d\n", fireErrors);
15957 printf(" applyFacets: %d\n", applyFacets);
15958#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015959 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
15960 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015961 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015962 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015963 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015964 type->name, NULL);
15965 ret = -1;
15966 }
15967 if (ret == 0) {
15968 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015969 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
15970 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015971 if ((ret <= 0) || (ret == 0))
15972 break;
15973 memberLink = memberLink->next;
15974 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015975 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015976 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015977 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015978 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015979 type->name, NULL);
15980 } else if (ret > 0) {
15981 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015982 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015983 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015984 }
15985 }
15986 /*
15987 * Apply facets (pattern, enumeration).
15988 */
15989 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
15990 int mws;
15991 /*
15992 * The normalization behavior of ·union· types is controlled by
15993 * the value of whiteSpace on that one of the ·memberTypes·
15994 * against which the ·union· is successfully validated.
15995 */
15996 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015997 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015998 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15999 "the value was already normalized for the union simple "
16000 "type '%s'.\n", type->name, NULL);
16001 }
16002 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
16003 if (mws > ctxt->valueWS) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016004 if (mws == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000016005 normValue = xmlSchemaCollapseString(value);
16006 else
16007 normValue = xmlSchemaWhiteSpaceReplace(value);
16008 if (normValue != NULL)
16009 value = (const xmlChar *) normValue;
16010 }
16011
16012 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16013 value, 0, fireErrors);
16014 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016015 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016016 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16017 "validating facets of union simple type '%s'\n",
16018 type->name, NULL);
16019 } else if (ret > 0) {
16020 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
16021 /*
16022 if (fireErrors)
16023 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16024 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016025 }
16026 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016027 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016028 ctxt->valueWS = wtsp;
16029 if (normValue != NULL)
16030 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016031 return (ret);
16032}
16033
16034/**
16035 * xmlSchemaValidateSimpleTypeElement:
16036 * @ctxt: a schema validation context
16037 * @node: the element node to be validated.
16038 *
16039 * Validate the element against a simple type.
16040 *
16041 * Returns 0 if the element is valid, a positive error code
16042 * number otherwise and -1 in case of an internal or API error.
16043 */
16044static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016045xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016046 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016047 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016048 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016049{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016050 xmlSchemaTypePtr oldtype;
16051 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016052 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016053 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016054 int ret = 0, retval = 0;
16055
Daniel Veillard01fa6152004-06-29 17:04:39 +000016056 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016057 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16058 "Internal error: xmlSchemaValidateElementBySimpleType, "
16059 "bad arguments", NULL);
16060 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016061 }
16062
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016063 oldtype = ctxt->type;
16064 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016065 /*
16066 * cvc-type: 3.1.2 The element information item must have no element
16067 * information item [children].
16068 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016069 /*
16070 * STREAM: Child nodes are processed.
16071 */
16072 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016073 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016074 /*
16075 * TODO: Entities, will they produce elements as well?
16076 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016077 if (cur->type == XML_ELEMENT_NODE) {
16078 xmlSchemaVCustomErr(ctxt,
16079 XML_SCHEMAV_CVC_TYPE_3_1_2,
16080 node, type,
16081 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016082 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016083 }
16084 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016085 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016086
Daniel Veillard01fa6152004-06-29 17:04:39 +000016087 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016088 * cvc-type 3.1.1:
16089 *
16090 * The attributes of must be empty, excepting those whose namespace name
16091 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
16092 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016093 */
16094 /*
16095 * STREAM: Attribute nodes are processed.
16096 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016097 attr = node->properties;
16098 while (attr != NULL) {
16099 if ((attr->ns == NULL) ||
16100 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
16101 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
16102 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
16103 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
16104 (!xmlStrEqual
16105 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016106 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016107 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
16108 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016109 }
16110 attr = attr->next;
16111 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016112 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016113 * This will skip validation if the type is 'anySimpleType' and
16114 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016115 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016116 if ((! isNil) &&
16117 (valSimpleContent == 1) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016118 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
16119 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016120 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016121
16122 value = xmlNodeGetContent(node);
16123 /*
16124 * NOTE: This call will not check the content nodes, since
16125 * this should be checked here already.
16126 */
16127 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
16128 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016129 if (value != NULL)
16130 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016131 if (retval != 0)
16132 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000016133 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016134 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016135 return (ret);
16136}
Daniel Veillard4255d502002-04-16 15:50:10 +000016137
16138/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016139 * xmlSchemaValQNameAcquire:
16140 * @value: the lexical represantation of the QName value
16141 * @node: the node to search for the corresponding namespace declaration
16142 * @nsName: the resulting namespace name if found
16143 *
16144 * Checks that a value conforms to the lexical space of the type QName;
16145 * if valid, the corresponding namespace name is searched and retured
16146 * as a copy in @nsName. The local name is returned in @localName as
16147 * a copy.
16148 *
16149 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
16150 * namespace declaration was found in scope; -1 in case of an internal or
16151 * API error.
16152 */
16153static int
16154xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
16155 xmlChar **nsName, xmlChar **localName)
16156{
16157 int ret;
16158 xmlChar *local = NULL;
16159
16160 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
16161 return (-1);
16162 *nsName = NULL;
16163 *localName = NULL;
16164 ret = xmlValidateQName(value, 1);
16165 if (ret == 0) {
16166 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016167 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016168
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016169 /*
16170 * NOTE: xmlSplitQName2 will return a duplicated
16171 * string.
16172 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016173 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016174 if (local == NULL)
16175 local = xmlStrdup(value);
16176 ns = xmlSearchNs(node->doc, node, prefix);
16177 /*
16178 * A namespace need not to be found if the prefix is NULL.
16179 */
16180 if (ns != NULL) {
16181 /*
16182 * TODO: Is it necessary to duplicate the URI here?
16183 */
16184 *nsName = xmlStrdup(ns->href);
16185 } else if (prefix != NULL) {
16186 xmlFree(prefix);
16187 if (local != NULL)
16188 xmlFree(local);
16189 return (2);
16190 }
16191 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016192 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016193 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016194 } else
16195 return (1);
16196 return (ret);
16197}
16198
16199/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016200 * xmlSchemaHasElemContent:
16201 * @node: the node
16202 *
16203 * Scours the content of the given node for element
16204 * nodes.
16205 *
16206 * Returns 1 if an element node is found,
16207 * 0 otherwise.
16208 */
16209static int
16210xmlSchemaHasElemContent(xmlNodePtr node)
16211{
16212 if (node == NULL)
16213 return (0);
16214 node = node->children;
16215 while (node != NULL) {
16216 if (node->type == XML_ELEMENT_NODE)
16217 return (1);
16218 node = node->next;
16219 }
16220 return (0);
16221}
16222/**
16223 * xmlSchemaHasElemOrCharContent:
16224 * @node: the node
16225 *
16226 * Scours the content of the given node for element
16227 * and character nodes.
16228 *
16229 * Returns 1 if an element or character node is found,
16230 * 0 otherwise.
16231 */
16232static int
16233xmlSchemaHasElemOrCharContent(xmlNodePtr node)
16234{
16235 if (node == NULL)
16236 return (0);
16237 node = node->children;
16238 while (node != NULL) {
16239 switch (node->type) {
16240 case XML_ELEMENT_NODE:
16241 /*
16242 * TODO: Ask Daniel if these are all character nodes.
16243 */
16244 case XML_TEXT_NODE:
16245 case XML_CDATA_SECTION_NODE:
16246 /*
16247 * TODO: How XML_ENTITY_NODEs evaluated?
16248 */
16249 case XML_ENTITY_REF_NODE:
16250 case XML_ENTITY_NODE:
16251 return (1);
16252 break;
16253 default:
16254 break;
16255 }
16256 node = node->next;
16257 }
16258 return (0);
16259}
16260
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016261/************************************************************************
16262 * *
16263 * Identity-constraints (IDC) *
16264 * *
16265 ************************************************************************/
16266
16267#ifdef IDC_ENABLED
16268
16269/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016270 * xmlSchemaAugmentIDC:
16271 * @idcDef: the IDC definition
16272 *
16273 * Creates an augmented IDC definition item.
16274 *
16275 * Returns the item, or NULL on internal errors.
16276 */
16277static void
16278xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
16279 xmlSchemaValidCtxtPtr vctxt)
16280{
16281 xmlSchemaIDCAugPtr aidc;
16282
16283 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
16284 if (aidc == NULL) {
16285 xmlSchemaVErrMemory(vctxt,
16286 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
16287 NULL);
16288 return;
16289 }
16290 aidc->bubbleDepth = -1;
16291 aidc->def = idcDef;
16292 aidc->next = NULL;
16293 if (vctxt->aidcs == NULL)
16294 vctxt->aidcs = aidc;
16295 else {
16296 aidc->next = vctxt->aidcs;
16297 vctxt->aidcs = aidc;
16298 }
16299}
16300
16301/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016302 * xmlSchemaIDCNewBinding:
16303 * @idcDef: the IDC definition of this binding
16304 *
16305 * Creates a new IDC binding.
16306 *
16307 * Returns the new binding in case of succeeded, NULL on internal errors.
16308 */
16309static xmlSchemaPSVIIDCBindingPtr
16310xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
16311{
16312 xmlSchemaPSVIIDCBindingPtr ret;
16313
16314 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
16315 sizeof(xmlSchemaPSVIIDCBinding));
16316 if (ret == NULL) {
16317 xmlSchemaVErrMemory(NULL,
16318 "allocating a PSVI IDC binding item", NULL);
16319 return (NULL);
16320 }
16321 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
16322 ret->definition = idcDef;
16323 return (ret);
16324}
16325
16326/**
16327 * xmlSchemaIDCStoreNodeTableItem:
16328 * @vctxt: the WXS validation context
16329 * @item: the IDC node table item
16330 *
16331 * The validation context is used to store an IDC node table items.
16332 * They are stored to avoid copying them if IDC node-tables are merged
16333 * with corresponding parent IDC node-tables (bubbling).
16334 *
16335 * Returns 0 if succeeded, -1 on internal errors.
16336 */
16337static int
16338xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
16339 xmlSchemaPSVIIDCNodePtr item)
16340{
16341 /*
16342 * Add to gobal list.
16343 */
16344 if (vctxt->idcNodes == NULL) {
16345 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16346 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
16347 if (vctxt->idcNodes == NULL) {
16348 xmlSchemaVErrMemory(vctxt,
16349 "allocating the IDC node table item list", NULL);
16350 return (-1);
16351 }
16352 vctxt->sizeIdcNodes = 20;
16353 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
16354 vctxt->sizeIdcNodes *= 2;
16355 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16356 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
16357 sizeof(xmlSchemaPSVIIDCNodePtr));
16358 if (vctxt->idcNodes == NULL) {
16359 xmlSchemaVErrMemory(vctxt,
16360 "re-allocating the IDC node table item list", NULL);
16361 return (-1);
16362 }
16363 }
16364 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
16365
16366 return (0);
16367}
16368
16369/**
16370 * xmlSchemaIDCStoreKey:
16371 * @vctxt: the WXS validation context
16372 * @item: the IDC key
16373 *
16374 * The validation context is used to store an IDC key.
16375 *
16376 * Returns 0 if succeeded, -1 on internal errors.
16377 */
16378static int
16379xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
16380 xmlSchemaPSVIIDCKeyPtr key)
16381{
16382 /*
16383 * Add to gobal list.
16384 */
16385 if (vctxt->idcKeys == NULL) {
16386 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16387 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
16388 if (vctxt->idcKeys == NULL) {
16389 xmlSchemaVErrMemory(vctxt,
16390 "allocating the IDC key storage list", NULL);
16391 return (-1);
16392 }
16393 vctxt->sizeIdcKeys = 40;
16394 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
16395 vctxt->sizeIdcKeys *= 2;
16396 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16397 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
16398 sizeof(xmlSchemaPSVIIDCKeyPtr));
16399 if (vctxt->idcKeys == NULL) {
16400 xmlSchemaVErrMemory(vctxt,
16401 "re-allocating the IDC key storage list", NULL);
16402 return (-1);
16403 }
16404 }
16405 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
16406
16407 return (0);
16408}
16409
16410/**
16411 * xmlSchemaIDCAppendNodeTableItem:
16412 * @bind: the IDC binding
16413 * @ntItem: the node-table item
16414 *
16415 * Appends the IDC node-table item to the binding.
16416 *
16417 * Returns 0 on success and -1 on internal errors.
16418 */
16419static int
16420xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
16421 xmlSchemaPSVIIDCNodePtr ntItem)
16422{
16423 if (bind->nodeTable == NULL) {
16424 bind->sizeNodes = 10;
16425 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16426 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
16427 if (bind->nodeTable == NULL) {
16428 xmlSchemaVErrMemory(NULL,
16429 "allocating an array of IDC node-table items", NULL);
16430 return(-1);
16431 }
16432 } else if (bind->sizeNodes <= bind->nbNodes) {
16433 bind->sizeNodes *= 2;
16434 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16435 xmlRealloc(bind->nodeTable, bind->sizeNodes *
16436 sizeof(xmlSchemaPSVIIDCNodePtr));
16437 if (bind->nodeTable == NULL) {
16438 xmlSchemaVErrMemory(NULL,
16439 "re-allocating an array of IDC node-table items", NULL);
16440 return(-1);
16441 }
16442 }
16443 bind->nodeTable[bind->nbNodes++] = ntItem;
16444 return(0);
16445}
16446
16447/**
16448 * xmlSchemaIDCAquireBinding:
16449 * @vctxt: the WXS validation context
16450 * @matcher: the IDC matcher
16451 *
16452 * Looks up an PSVI IDC binding, for the IDC definition and
16453 * of the given matcher. If none found, a new one is created
16454 * and added to the IDC table.
16455 *
16456 * Returns an IDC binding or NULL on internal errors.
16457 */
16458static xmlSchemaPSVIIDCBindingPtr
16459xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
16460 xmlSchemaIDCMatcherPtr matcher)
16461{
16462 xmlSchemaElemInfoPtr info;
16463
16464 info = vctxt->elemInfos[matcher->depth];
16465
16466 if (info->idcTable == NULL) {
16467 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
16468 if (info->idcTable == NULL)
16469 return (NULL);
16470 return(info->idcTable);
16471 } else {
16472 xmlSchemaPSVIIDCBindingPtr bind = NULL;
16473
16474 bind = info->idcTable;
16475 do {
16476 if (bind->definition == matcher->aidc->def)
16477 return(bind);
16478 if (bind->next == NULL) {
16479 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
16480 if (bind->next == NULL)
16481 return (NULL);
16482 return(bind->next);
16483 }
16484 bind = bind->next;
16485 } while (bind != NULL);
16486 }
16487 return (NULL);
16488}
16489
16490/**
16491 * xmlSchemaIDCFreeKey:
16492 * @key: the IDC key
16493 *
16494 * Frees an IDC key together with its compiled value.
16495 */
16496static void
16497xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
16498{
16499 if (key->compValue != NULL)
16500 xmlSchemaFreeValue(key->compValue);
16501 xmlFree(key);
16502}
16503
16504/**
16505 * xmlSchemaIDCFreeBinding:
16506 *
16507 * Frees an IDC binding. Note that the node table-items
16508 * are not freed.
16509 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016510static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016511xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
16512{
16513 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016514 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
16515 int i;
16516 /*
16517 * Node-table items for keyrefs are not stored globally
16518 * to the validation context, since they are not bubbled.
16519 * We need to free them here.
16520 */
16521 for (i = 0; i < bind->nbNodes; i++) {
16522 xmlFree(bind->nodeTable[i]->keys);
16523 xmlFree(bind->nodeTable[i]);
16524 }
16525 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016526 xmlFree(bind->nodeTable);
16527 }
16528 xmlFree(bind);
16529}
16530
16531/**
16532 * xmlSchemaIDCFreeIDCTable:
16533 * @bind: the first IDC binding in the list
16534 *
16535 * Frees an IDC table, i.e. all the IDC bindings in the list.
16536 */
16537static void
16538xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
16539{
16540 xmlSchemaPSVIIDCBindingPtr prev;
16541
16542 while (bind != NULL) {
16543 prev = bind;
16544 bind = bind->next;
16545 xmlSchemaIDCFreeBinding(prev);
16546 }
16547}
16548
16549/**
16550 * xmlSchemaIDCFreeMatcherList:
16551 * @matcher: the first IDC matcher in the list
16552 *
16553 * Frees a list of IDC matchers.
16554 */
16555static void
16556xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
16557{
16558 xmlSchemaIDCMatcherPtr next;
16559
16560 while (matcher != NULL) {
16561 next = matcher->next;
16562 if (matcher->keySeqs != NULL) {
16563 int i;
16564 for (i = 0; i < matcher->sizeKeySeqs; i++)
16565 if (matcher->keySeqs[i] != NULL)
16566 xmlFree(matcher->keySeqs[i]);
16567 xmlFree(matcher->keySeqs);
16568 }
16569 xmlFree(matcher);
16570 matcher = next;
16571 }
16572}
16573
16574/**
16575 * xmlSchemaAreValuesEqual:
16576 * @ta: the first type
16577 * @a: the first value
16578 * @tb: the second type
16579 * @b: the second value
16580 *
16581 * Compares two values.
16582 *
16583 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
16584 */
16585static int
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016586xmlSchemaAreValuesEqual(xmlSchemaValidCtxtPtr vctxt,
16587 xmlSchemaTypePtr ta,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016588 xmlSchemaValPtr a,
16589 xmlSchemaTypePtr tb,
16590 xmlSchemaValPtr b)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016591{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016592 /* Same user derived/built-in derived/built-in primitive types. */
16593 if (ta == tb)
16594 goto compareValue;
16595
16596 /*
16597 * Comparison with anySimpleTypes is not supported by this implemention.
16598 */
16599 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
16600 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
16601 return(0);
16602
16603 /*
16604 * 4.2.1 equal (data-types)
16605 *
16606 * the ·value space·s of all ·primitive· datatypes are disjoint
16607 * (they do not share any values)
16608 */
16609 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
16610 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
16611 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
16612 return(0);
16613
16614 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16615 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
16616 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16617 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
16618 TODO
16619 return(0);
16620 }
16621 /*
16622 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
16623 * T then the ·value space· of T' is a subset of the ·value space· of T.
16624 */
16625 /*
16626 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
16627 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
16628 */
16629
16630 {
16631 xmlSchemaTypePtr pta = ta, ptb = tb;
16632
16633 /* Note that we will compare the primitives here. */
16634 while ((pta->builtInType == 0) ||
16635 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16636 pta = pta->baseType;
16637 while ((ptb->builtInType == 0) ||
16638 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16639 ptb = ptb->baseType;
16640 if (pta == ptb)
16641 goto compareValue;
16642 return(0);
16643 }
16644compareValue:
16645 {
16646#ifdef IDC_VALUE_SUPPORT
16647 int ret;
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016648 int aws, bws;
16649
16650 aws = xmlSchemaGetWhiteSpaceFacetValue(ta);
16651 bws = xmlSchemaGetWhiteSpaceFacetValue(tb);
16652
16653 ret = xmlSchemaCompareValuesWhtsp(
16654 a, (xmlSchemaWhitespaceValueType) aws,
16655 b, (xmlSchemaWhitespaceValueType) bws);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016656 if (ret == 0)
16657 return(1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016658 else if (ret == -2) {
16659 xmlSchemaVErr(vctxt, vctxt->node,
16660 XML_SCHEMAV_INTERNAL,
16661 "Internal error: xmlSchemaAreValuesEqual, "
16662 "failed to compare the values.\n",
16663 NULL, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016664 return(-1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016665 } else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016666 return(0);
16667#else
16668 return (1);
16669#endif
16670 }
16671}
16672
16673/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016674 * xmlSchemaIDCAddStateObject:
16675 * @vctxt: the WXS validation context
16676 * @matcher: the IDC matcher
16677 * @sel: the XPath information
16678 * @parent: the parent "selector" state object if any
16679 * @type: "selector" or "field"
16680 *
16681 * Creates/reuses and activates state objects for the given
16682 * XPath information; if the XPath expression consists of unions,
16683 * multiple state objects are created for every unioned expression.
16684 *
16685 * Returns 0 on success and -1 on internal errors.
16686 */
16687static int
16688xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
16689 xmlSchemaIDCMatcherPtr matcher,
16690 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016691 int type)
16692{
16693 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016694
16695 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016696 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016697 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016698 if (vctxt->xpathStatePool != NULL) {
16699 sto = vctxt->xpathStatePool;
16700 vctxt->xpathStatePool = sto->next;
16701 sto->next = NULL;
16702 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016703 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016704 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016705 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016706 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
16707 if (sto == NULL) {
16708 xmlSchemaVErrMemory(NULL,
16709 "allocating an IDC state object", NULL);
16710 return (-1);
16711 }
16712 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
16713 }
16714 /*
16715 * Add to global list.
16716 */
16717 if (vctxt->xpathStates != NULL)
16718 sto->next = vctxt->xpathStates;
16719 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016720
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016721 /*
16722 * Free the old xpath validation context.
16723 */
16724 if (sto->xpathCtxt != NULL)
16725 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
16726
16727 /*
16728 * Create a new XPath (pattern) validation context.
16729 */
16730 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
16731 (xmlPatternPtr) sel->xpathComp);
16732 if (sto->xpathCtxt == NULL) {
16733 xmlSchemaVErr(vctxt, vctxt->node,
16734 XML_SCHEMAV_INTERNAL,
16735 "Internal error: xmlSchemaIDCAddStateObject, "
16736 "failed to create the XPath validation context.\n",
16737 NULL, NULL);
16738 return (-1);
16739 }
16740 sto->type = type;
16741 sto->depth = vctxt->depth;
16742 sto->matcher = matcher;
16743 sto->sel = sel;
16744 sto->nbHistory = 0;
16745
16746#if DEBUG_IDC
16747 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
16748 sto->sel->xpath);
16749#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016750 return (0);
16751}
16752
16753/**
16754 * xmlSchemaXPathEvaluate:
16755 * @vctxt: the WXS validation context
16756 * @nodeType: the nodeType of the current node
16757 *
16758 * Evaluates all active XPath state objects.
16759 *
16760 * Returns the number of IC "field" state objects which resolved to
16761 * this node, 0 if none resolved and -1 on internal errors.
16762 */
16763static int
16764xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016765 xmlElementType nodeType)
16766{
16767 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016768 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016769
16770 if (vctxt->xpathStates == NULL)
16771 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016772
16773 if (nodeType == XML_ATTRIBUTE_NODE)
16774 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016775#if DEBUG_IDC
16776 {
16777 xmlChar *str = NULL;
16778 xmlGenericError(xmlGenericErrorContext,
16779 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016780 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
16781 vctxt->nodeInfo->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016782 FREE_AND_NULL(str)
16783 }
16784#endif
16785 /*
16786 * Process all active XPath state objects.
16787 */
16788 first = vctxt->xpathStates;
16789 sto = first;
16790 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016791#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016792 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016793 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
16794 sto->matcher->aidc->def->name, sto->sel->xpath);
16795 else
16796 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
16797 sto->matcher->aidc->def->name, sto->sel->xpath);
16798#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016799
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016800#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016801 if (nodeType == XML_ELEMENT_NODE)
16802 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
16803 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
16804 else
16805 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
16806 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
16807
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016808#else
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016809 res = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016810#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016811 if (res == -1) {
16812 xmlSchemaVErr(vctxt, vctxt->node,
16813 XML_SCHEMAV_INTERNAL,
16814 "Internal error: xmlSchemaXPathEvaluate, "
16815 "failed to evaluate a node.\n",
16816 NULL, NULL);
16817 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016818 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016819 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016820 goto next_sto;
16821 /*
16822 * Full match.
16823 */
16824#if DEBUG_IDC
16825 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016826 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016827#endif
16828 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016829 * Register a match in the state object history.
16830 */
16831 if (sto->history == NULL) {
16832 sto->history = (int *) xmlMalloc(5 * sizeof(int));
16833 if (sto->history == NULL) {
16834 xmlSchemaVErrMemory(NULL,
16835 "allocating the state object history", NULL);
16836 return(-1);
16837 }
16838 sto->sizeHistory = 10;
16839 } else if (sto->sizeHistory <= sto->nbHistory) {
16840 sto->sizeHistory *= 2;
16841 sto->history = (int *) xmlRealloc(sto->history,
16842 sto->sizeHistory * sizeof(int));
16843 if (sto->history == NULL) {
16844 xmlSchemaVErrMemory(NULL,
16845 "re-allocating the state object history", NULL);
16846 return(-1);
16847 }
16848 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016849 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016850
16851#ifdef DEBUG_IDC
16852 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
16853 vctxt->depth);
16854#endif
16855
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016856 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
16857 xmlSchemaIDCSelectPtr sel;
16858 /*
16859 * Activate state objects for the IDC fields of
16860 * the IDC selector.
16861 */
16862#if DEBUG_IDC
16863 xmlGenericError(xmlGenericErrorContext, "IDC: "
16864 "activating field states\n");
16865#endif
16866 sel = sto->matcher->aidc->def->fields;
16867 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016868 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
16869 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
16870 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016871 sel = sel->next;
16872 }
16873 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
16874 /*
16875 * An IDC key node was found.
16876 */
16877#if DEBUG_IDC
16878 xmlGenericError(xmlGenericErrorContext,
16879 "IDC: key found\n");
16880#endif
16881 /*
16882 * Notify that the character value of this node is
16883 * needed.
16884 */
16885 if (resolved == 0)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016886 vctxt->nodeInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016887 resolved++;
16888 }
16889next_sto:
16890 if (sto->next == NULL) {
16891 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016892 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016893 */
16894 head = first;
16895 sto = vctxt->xpathStates;
16896 } else
16897 sto = sto->next;
16898 }
16899 return (resolved);
16900}
16901
16902/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016903 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016904 * @vctxt: the WXS validation context
16905 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016906 * @compValue: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016907 *
16908 * Processes and pops the history items of the IDC state objects.
16909 * IDC key-sequences are validated/created on IDC bindings.
16910 *
16911 * Returns 0 on success and -1 on internal errors.
16912 */
16913static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016914xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016915 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016916{
16917 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016918 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016919 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016920 xmlSchemaTypePtr type = vctxt->nodeInfo->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016921
16922 if (vctxt->xpathStates == NULL)
16923 return (0);
16924 sto = vctxt->xpathStates;
16925
16926#if DEBUG_IDC
16927 {
16928 xmlChar *str = NULL;
16929 xmlGenericError(xmlGenericErrorContext,
16930 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016931 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
16932 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016933 FREE_AND_NULL(str)
16934 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016935#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016936 /*
16937 * Evaluate the state objects.
16938 */
16939 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016940#ifdef IDC_XPATH_SUPPORT
16941 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
16942 #if DEBUG_IDC
16943 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
16944 sto->sel->xpath);
16945 #endif
16946#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016947 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016948 goto deregister_check;
16949
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016950 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016951
16952 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016953 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016954 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016955 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016956 sto = sto->next;
16957 continue;
16958 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016959
16960 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
16961 if (! IS_SIMPLE_TYPE(type)) {
16962 /*
16963 * Not qualified if the field resolves to a node of non
16964 * simple type.
16965 */
16966 xmlSchemaVCustomErr(vctxt,
16967 XML_SCHEMAV_CVC_IDC,
16968 vctxt->node,
16969 (xmlSchemaTypePtr) sto->matcher->aidc->def,
16970 "The field '%s' does evaluate to a node of "
16971 "non-simple type", sto->sel->xpath);
16972
16973 sto->nbHistory--;
16974 goto deregister_check;
16975 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016976 if ((key == NULL) && (vctxt->nodeInfo->value == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016977 /*
16978 * Failed to provide the normalized value; maby
16979 * the value was invalid.
16980 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016981 xmlSchemaVCustomErr(vctxt,
16982 XML_SCHEMAV_CVC_IDC,
16983 vctxt->nodeInfo->node,
16984 (xmlSchemaTypePtr) sto->matcher->aidc->def,
16985 "Warning: No precomputed value available, the value "
16986 "was either invalid or something strange happend", NULL);
16987 /*
16988 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016989 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016990 "Internal error: xmlSchemaXPathProcessHistory, "
16991 "computed value not available.\n",
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016992 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016993 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016994 sto->nbHistory--;
16995 goto deregister_check;
16996 } else {
16997 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
16998 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016999 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017000
17001 /*
17002 * The key will be anchored on the matcher's list of
17003 * key-sequences. The position in this list is determined
17004 * by the target node's depth relative to the matcher's
17005 * depth of creation (i.e. the depth of the scope element).
17006 */
17007 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017008 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017009
17010 /*
17011 * Create/grow the array of key-sequences.
17012 */
17013 if (matcher->keySeqs == NULL) {
17014 if (pos > 9)
17015 matcher->sizeKeySeqs = pos * 2;
17016 else
17017 matcher->sizeKeySeqs = 10;
17018 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17019 xmlMalloc(matcher->sizeKeySeqs *
17020 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17021 if (matcher->keySeqs == NULL) {
17022 xmlSchemaVErrMemory(NULL,
17023 "allocating an array of key-sequences",
17024 NULL);
17025 return(-1);
17026 }
17027 memset(matcher->keySeqs, 0,
17028 matcher->sizeKeySeqs *
17029 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17030 } else if (pos >= matcher->sizeKeySeqs) {
17031 int i = matcher->sizeKeySeqs;
17032
17033 matcher->sizeKeySeqs *= 2;
17034 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17035 xmlRealloc(matcher->keySeqs,
17036 matcher->sizeKeySeqs *
17037 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017038 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017039 xmlSchemaVErrMemory(NULL,
17040 "reallocating an array of key-sequences",
17041 NULL);
17042 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017043 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017044 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017045 * The array needs to be NULLed.
17046 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017047 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017048 for (; i < matcher->sizeKeySeqs; i++)
17049 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017050 }
17051
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017052 /*
17053 * Get/create the key-sequence.
17054 */
17055 keySeq = matcher->keySeqs[pos];
17056 if (keySeq == NULL) {
17057 goto create_sequence;
17058 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017059 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017060 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017061 * cvc-identity-constraint:
17062 * 3 For each node in the ·target node set· all
17063 * of the {fields}, with that node as the context
17064 * node, evaluate to either an empty node-set or
17065 * a node-set with exactly one member, which must
17066 * have a simple type.
17067 *
17068 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017069 */
17070 xmlSchemaVCustomErr(vctxt,
17071 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017072 vctxt->node, (xmlSchemaTypePtr) matcher->aidc->def,
17073 "The field '%s' evaluates to a node-set "
17074 "with more than one member", sto->sel->xpath);
17075 sto->nbHistory--;
17076 goto deregister_check;
17077 } else {
17078 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017079 }
17080 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017081
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017082create_sequence:
17083 /*
17084 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017085 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017086 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
17087 matcher->aidc->def->nbFields *
17088 sizeof(xmlSchemaPSVIIDCKeyPtr));
17089 if (keySeq == NULL) {
17090 xmlSchemaVErrMemory(NULL,
17091 "allocating an IDC key-sequence", NULL);
17092 return(-1);
17093 }
17094 memset(keySeq, 0, matcher->aidc->def->nbFields *
17095 sizeof(xmlSchemaPSVIIDCKeyPtr));
17096 matcher->keySeqs[pos] = keySeq;
17097create_key:
17098 /*
17099 * Created a key once per node only.
17100 */
17101 if (key == NULL) {
17102 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
17103 sizeof(xmlSchemaPSVIIDCKey));
17104 if (key == NULL) {
17105 xmlSchemaVErrMemory(NULL,
17106 "allocating a IDC key", NULL);
17107 xmlFree(keySeq);
17108 matcher->keySeqs[pos] = NULL;
17109 return(-1);
17110 }
17111 /*
17112 * Consume the compiled value.
17113 */
17114 key->type = type;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017115 key->compValue = vctxt->nodeInfo->value;
17116 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017117 /*
17118 * Store the key in a global list.
17119 */
17120 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
17121 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017122 return (-1);
17123 }
17124 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017125 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017126 }
17127 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017128
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017129 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
17130 xmlSchemaPSVIIDCBindingPtr bind;
17131 xmlSchemaPSVIIDCNodePtr ntItem;
17132 xmlSchemaIDCMatcherPtr matcher;
17133 xmlSchemaIDCPtr idc;
17134 int pos, i, j, nbKeys;
17135 /*
17136 * Here we have the following scenario:
17137 * An IDC 'selector' state object resolved to a target node,
17138 * during the time this target node was in the
17139 * ancestor-or-self axis, the 'field' state object(s) looked
17140 * out for matching nodes to create a key-sequence for this
17141 * target node. Now we are back to this target node and need
17142 * to put the key-sequence, together with the target node
17143 * itself, into the node-table of the corresponding IDC
17144 * binding.
17145 */
17146 matcher = sto->matcher;
17147 idc = matcher->aidc->def;
17148 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017149 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017150 /*
17151 * Check if the matcher has any key-sequences at all, plus
17152 * if it has a key-sequence for the current target node.
17153 */
17154 if ((matcher->keySeqs == NULL) ||
17155 (matcher->sizeKeySeqs <= pos)) {
17156 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17157 goto selector_key_error;
17158 else
17159 goto selector_leave;
17160 }
17161
17162 keySeq = &(matcher->keySeqs[pos]);
17163 if (*keySeq == NULL) {
17164 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17165 goto selector_key_error;
17166 else
17167 goto selector_leave;
17168 }
17169
17170 for (i = 0; i < nbKeys; i++) {
17171 if ((*keySeq)[i] == NULL) {
17172 /*
17173 * Not qualified, if not all fields did resolve.
17174 */
17175 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
17176 /*
17177 * All fields of a "key" IDC must resolve.
17178 */
17179 goto selector_key_error;
17180 }
17181 goto selector_leave;
17182 }
17183 }
17184 /*
17185 * All fields did resolve.
17186 */
17187
17188 /*
17189 * 4.1 If the {identity-constraint category} is unique(/key),
17190 * then no two members of the ·qualified node set· have
17191 * ·key-sequences· whose members are pairwise equal, as
17192 * defined by Equal in [XML Schemas: Datatypes].
17193 *
17194 * Get the IDC binding from the matcher and check for
17195 * duplicate key-sequences.
17196 */
17197 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
17198 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
17199 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017200 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017201
17202 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017203 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017204 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017205 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017206 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017207 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017208 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017209 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017210 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017211 bkey = bkeySeq[j];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017212 res = xmlSchemaAreValuesEqual(vctxt, ckey->type,
17213 ckey->compValue, bkey->type, bkey->compValue);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017214 if (res == -1) {
17215 return (-1);
17216 } else if (res == 0)
17217 break;
17218 }
17219 if (res == 1) {
17220 /*
17221 * Duplicate found.
17222 */
17223 break;
17224 }
17225 i++;
17226 } while (i < bind->nbNodes);
17227 if (i != bind->nbNodes) {
17228 /*
17229 * TODO: Try to report the key-sequence.
17230 */
17231 xmlSchemaVCustomErr(vctxt,
17232 XML_SCHEMAV_CVC_IDC,
17233 vctxt->node,
17234 (xmlSchemaTypePtr) idc,
17235 "Duplicate key-sequence found", NULL);
17236
17237 goto selector_leave;
17238 }
17239 }
17240 /*
17241 * Add a node-table item to the IDC binding.
17242 */
17243 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
17244 sizeof(xmlSchemaPSVIIDCNode));
17245 if (ntItem == NULL) {
17246 xmlSchemaVErrMemory(NULL,
17247 "allocating an IDC node-table item", NULL);
17248 xmlFree(*keySeq);
17249 *keySeq = NULL;
17250 return(-1);
17251 }
17252 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
17253
17254 /*
17255 * Store the node-table item on global list.
17256 */
17257 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
17258 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
17259 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017260 xmlFree(*keySeq);
17261 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017262 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017263 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017264 }
17265 /*
17266 * Init the node-table item. Consume the key-sequence.
17267 */
17268 ntItem->node = vctxt->node;
17269 ntItem->keys = *keySeq;
17270 *keySeq = NULL;
17271 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
17272 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17273 /*
17274 * Free the item, since keyref items won't be
17275 * put on a global list.
17276 */
17277 xmlFree(ntItem->keys);
17278 xmlFree(ntItem);
17279 }
17280 return (-1);
17281 }
17282
17283 goto selector_leave;
17284selector_key_error:
17285 /*
17286 * 4.2.1 (KEY) The ·target node set· and the
17287 * ·qualified node set· are equal, that is, every
17288 * member of the ·target node set· is also a member
17289 * of the ·qualified node set· and vice versa.
17290 */
17291 xmlSchemaVCustomErr(vctxt,
17292 XML_SCHEMAV_CVC_IDC,
17293 vctxt->node,
17294 (xmlSchemaTypePtr) idc,
17295 "All 'key' fields must evaluate to a node",
17296 NULL);
17297selector_leave:
17298 /*
17299 * Free the key-sequence if not added to the IDC table.
17300 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017301 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017302 xmlFree(*keySeq);
17303 *keySeq = NULL;
17304 }
17305 } /* if selector */
17306
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017307 sto->nbHistory--;
17308
17309deregister_check:
17310 /*
17311 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017312 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017313 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017314#if DEBUG_IDC
17315 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
17316 sto->sel->xpath);
17317#endif
17318 if (vctxt->xpathStates != sto) {
17319 xmlSchemaVErr(vctxt, vctxt->node,
17320 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017321 "Internal error: xmlSchemaXPathProcessHistory, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017322 "The state object to be removed is not the first "
17323 "in the list.\n",
17324 NULL, NULL);
17325 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017326 nextsto = sto->next;
17327 /*
17328 * Unlink from the list of active XPath state objects.
17329 */
17330 vctxt->xpathStates = sto->next;
17331 sto->next = vctxt->xpathStatePool;
17332 /*
17333 * Link it to the pool of reusable state objects.
17334 */
17335 vctxt->xpathStatePool = sto;
17336 sto = nextsto;
17337 } else
17338 sto = sto->next;
17339 } /* while (sto != NULL) */
17340 return (0);
17341}
17342
17343/**
17344 * xmlSchemaIDCRegisterMatchers:
17345 * @vctxt: the WXS validation context
17346 * @elemDecl: the element declaration
17347 *
17348 * Creates helper objects to evaluate IDC selectors/fields
17349 * successively.
17350 *
17351 * Returns 0 if OK and -1 on internal errors.
17352 */
17353static int
17354xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
17355 xmlSchemaElementPtr elemDecl)
17356{
17357 xmlSchemaIDCMatcherPtr matcher, last = NULL;
17358 xmlSchemaIDCPtr idc, refIdc;
17359 xmlSchemaIDCAugPtr aidc;
17360
17361 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
17362 if (idc == NULL)
17363 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017364
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017365#if DEBUG_IDC
17366 {
17367 xmlChar *str = NULL;
17368 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017369 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017370 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17371 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017372 FREE_AND_NULL(str)
17373 }
17374#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017375 if (vctxt->nodeInfo->idcMatchers != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017376 xmlSchemaVErr(vctxt, vctxt->node,
17377 XML_SCHEMAV_INTERNAL,
17378 "Internal error: xmlSchemaIDCRegisterMatchers: "
17379 "The chain of IDC matchers is expected to be empty.\n",
17380 NULL, NULL);
17381 return (-1);
17382 }
17383 do {
17384 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17385 /*
17386 * Since IDCs bubbles are expensive we need to know the
17387 * depth at which the bubbles should stop; this will be
17388 * the depth of the top-most keyref IDC. If no keyref
17389 * references a key/unique IDC, the bubbleDepth will
17390 * be -1, indicating that no bubbles are needed.
17391 */
17392 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
17393 if (refIdc != NULL) {
17394 /*
17395 * Lookup the augmented IDC.
17396 */
17397 aidc = vctxt->aidcs;
17398 while (aidc != NULL) {
17399 if (aidc->def == refIdc)
17400 break;
17401 aidc = aidc->next;
17402 }
17403 if (aidc == NULL) {
17404 xmlSchemaVErr(vctxt, vctxt->node,
17405 XML_SCHEMAV_INTERNAL,
17406 "Internal error: xmlSchemaIDCRegisterMatchers: "
17407 "Could not find an augmented IDC item for an IDC "
17408 "definition.\n",
17409 NULL, NULL);
17410 return (-1);
17411 }
17412 if ((aidc->bubbleDepth == -1) ||
17413 (vctxt->depth < aidc->bubbleDepth))
17414 aidc->bubbleDepth = vctxt->depth;
17415 }
17416 }
17417 /*
17418 * Lookup the augmented IDC item for the IDC definition.
17419 */
17420 aidc = vctxt->aidcs;
17421 while (aidc != NULL) {
17422 if (aidc->def == idc)
17423 break;
17424 aidc = aidc->next;
17425 }
17426 if (aidc == NULL) {
17427 xmlSchemaVErr(vctxt, vctxt->node,
17428 XML_SCHEMAV_INTERNAL,
17429 "Internal error: xmlSchemaIDCRegisterMatchers: "
17430 "Could not find an augmented IDC item for an IDC definition.\n",
17431 NULL, NULL);
17432 return (-1);
17433 }
17434 /*
17435 * Create an IDC matcher for every IDC definition.
17436 */
17437 matcher = (xmlSchemaIDCMatcherPtr)
17438 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
17439 if (matcher == NULL) {
17440 xmlSchemaVErrMemory(vctxt,
17441 "allocating an IDC matcher", NULL);
17442 return (-1);
17443 }
17444 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
17445 if (last == NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017446 vctxt->nodeInfo->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017447 else
17448 last->next = matcher;
17449 last = matcher;
17450
17451 matcher->type = IDC_MATCHER;
17452 matcher->depth = vctxt->depth;
17453 matcher->aidc = aidc;
17454#if DEBUG_IDC
17455 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
17456#endif
17457 /*
17458 * Init the automaton state object.
17459 */
17460 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017461 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017462 return (-1);
17463
17464 idc = idc->next;
17465 } while (idc != NULL);
17466 return (0);
17467}
17468
17469/**
17470 * xmlSchemaBubbleIDCNodeTables:
17471 * @depth: the current tree depth
17472 *
17473 * Merges IDC bindings of an element at @depth into the corresponding IDC
17474 * bindings of its parent element. If a duplicate note-table entry is found,
17475 * both, the parent node-table entry and child entry are discarded from the
17476 * node-table of the parent.
17477 *
17478 * Returns 0 if OK and -1 on internal errors.
17479 */
17480static int
17481xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
17482{
17483 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017484 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
17485 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017486 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
17487 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017488 int i, j, k, ret = 0, oldNum, newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017489 int duplTop;
17490
17491 /*
17492 * The node table has the following sections:
17493 *
17494 * O --> old node-table entries (first)
17495 * O
17496 * + --> new node-table entries
17497 * +
17498 * % --> new duplicate node-table entries
17499 * %
17500 * # --> old duplicate node-table entries
17501 * # (last)
17502 *
17503 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017504 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017505 if (bind == NULL) {
17506 /* Fine, no table, no bubbles. */
17507 return (0);
17508 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017509
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017510 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
17511 /*
17512 * Walk all bindings; create new or add to existing bindings.
17513 * Remove duplicate key-sequences.
17514 */
17515start_binding:
17516 while (bind != NULL) {
17517 /*
17518 * Skip keyref IDCs.
17519 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017520 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17521 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017522 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017523 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017524 /*
17525 * Check if the key/unique IDC table needs to be bubbled.
17526 */
17527 aidc = vctxt->aidcs;
17528 do {
17529 if (aidc->def == bind->definition) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017530 if (aidc->bubbleDepth >= vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017531 bind = bind->next;
17532 goto start_binding;
17533 }
17534 break;
17535 }
17536 aidc = aidc->next;
17537 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017538
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017539 if (parTable != NULL)
17540 parBind = *parTable;
17541 while (parBind != NULL) {
17542 /*
17543 * Search a matching parent binding for the
17544 * IDC definition.
17545 */
17546 if (parBind->definition == bind->definition) {
17547
17548 /*
17549 * Compare every node-table entry of the child node,
17550 * i.e. the key-sequence within, ...
17551 */
17552 oldNum = parBind->nbNodes; /* Skip newly added items. */
17553 duplTop = oldNum + parBind->nbDupls;
17554
17555 for (i = 0; i < bind->nbNodes; i++) {
17556 node = bind->nodeTable[i];
17557 if (node == NULL)
17558 continue;
17559 /*
17560 * ...with every key-sequence of the parent node, already
17561 * evaluated to be a duplicate key-sequence.
17562 */
17563 if (parBind->nbDupls != 0) {
17564 j = bind->nbNodes + newDupls;
17565 while (j < duplTop) {
17566 parNode = parBind->nodeTable[j];
17567 for (k = 0; k < bind->definition->nbFields; k++) {
17568 key = node->keys[k];
17569 parKey = parNode->keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017570 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017571 key->compValue,
17572 parKey->type, parKey->compValue);
17573 if (ret == -1) {
17574 /* TODO: Internal error */
17575 return(-1);
17576 } else if (ret == 0)
17577 break;
17578
17579 }
17580 if (ret == 1)
17581 /* Duplicate found. */
17582 break;
17583 j++;
17584 }
17585 if (j != duplTop) {
17586 /* Duplicate found. */
17587 continue;
17588 }
17589 }
17590 /*
17591 * ... and with every key-sequence of the parent node.
17592 */
17593 j = 0;
17594 while (j < oldNum) {
17595 parNode = parBind->nodeTable[j];
17596 /*
17597 * Compare key by key.
17598 */
17599 for (k = 0; k < parBind->definition->nbFields; k++) {
17600 key = node->keys[k];
17601 parKey = parNode->keys[k];
17602
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017603 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017604 key->compValue,
17605 parKey->type, parKey->compValue);
17606 if (ret == -1) {
17607 /* TODO: Internal error */
17608 } else if (ret == 0)
17609 break;
17610
17611 }
17612 if (ret == 1)
17613 /*
17614 * The key-sequences are equal.
17615 */
17616 break;
17617 j++;
17618 }
17619 if (j != oldNum) {
17620 /*
17621 * Handle duplicates.
17622 */
17623 newDupls++;
17624 oldNum--;
17625 parBind->nbNodes--;
17626 /*
17627 * Move last old item to pos of duplicate.
17628 */
17629 parBind->nodeTable[j] =
17630 parBind->nodeTable[oldNum];
17631
17632 if (parBind->nbNodes != oldNum) {
17633 /*
17634 * If new items exist, move last new item to
17635 * last of old items.
17636 */
17637 parBind->nodeTable[oldNum] =
17638 parBind->nodeTable[parBind->nbNodes];
17639 }
17640 /*
17641 * Move duplicate to last pos of new/old items.
17642 */
17643 parBind->nodeTable[parBind->nbNodes] = parNode;
17644
17645 } else {
17646 /*
17647 * Add the node-table entry (node and key-sequence) of
17648 * the child node to the node table of the parent node.
17649 */
17650 if (parBind->nodeTable == NULL) {
17651 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17652 xmlMalloc(1 * sizeof(xmlSchemaPSVIIDCNodePtr));
17653 if (parBind->nodeTable == NULL) {
17654 xmlSchemaVErrMemory(NULL,
17655 "allocating IDC list of node-table items", NULL);
17656 return(-1);
17657 }
17658 parBind->sizeNodes = 1;
17659 } else if (duplTop >= parBind->sizeNodes) {
17660 parBind->sizeNodes++;
17661 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17662 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
17663 sizeof(xmlSchemaPSVIIDCNodePtr));
17664 if (parBind->nodeTable == NULL) {
17665 xmlSchemaVErrMemory(NULL,
17666 "re-allocating IDC list of node-table items", NULL);
17667 return(-1);
17668 }
17669 }
17670
17671 /*
17672 * Move first old duplicate to last position
17673 * of old duplicates +1.
17674 */
17675 if (parBind->nbDupls != 0) {
17676 parBind->nodeTable[duplTop] =
17677 parBind->nodeTable[parBind->nbNodes + newDupls];
17678 }
17679 /*
17680 * Move first new duplicate to last position of
17681 * new duplicates +1.
17682 */
17683 if (newDupls != 0) {
17684 parBind->nodeTable[parBind->nbNodes + newDupls] =
17685 parBind->nodeTable[parBind->nbNodes];
17686 }
17687 /*
17688 * Append the new node-table entry to the 'new node-table
17689 * entries' section.
17690 */
17691 parBind->nodeTable[parBind->nbNodes] = node;
17692 parBind->nbNodes++;
17693 duplTop++;
17694 }
17695 }
17696 parBind->nbDupls += newDupls;
17697 break;
17698 }
17699 if (parBind->next == NULL)
17700 lastParBind = parBind;
17701 parBind = parBind->next;
17702 }
17703 if (parBind == NULL) {
17704 /*
17705 * No binding for the IDC was found: create a new one and
17706 * copy all node-tables.
17707 */
17708 parBind = xmlSchemaIDCNewBinding(bind->definition);
17709 if (parBind == NULL)
17710 return(-1);
17711
17712 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17713 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
17714 if (parBind->nodeTable == NULL) {
17715 xmlSchemaVErrMemory(NULL,
17716 "allocating an array of IDC node-table items", NULL);
17717 xmlSchemaIDCFreeBinding(parBind);
17718 return(-1);
17719 }
17720 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017721 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017722 memcpy(parBind->nodeTable, bind->nodeTable,
17723 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017724 if (*parTable == NULL)
17725 *parTable = parBind;
17726 else
17727 lastParBind->next = parBind;
17728 }
17729 bind = bind->next;
17730 }
17731 return (0);
17732}
17733
17734/**
17735 * xmlSchemaCheckCVCIDCKeyRef:
17736 * @vctxt: the WXS validation context
17737 * @elemDecl: the element declaration
17738 *
17739 * Check the cvc-idc-keyref constraints.
17740 */
17741static int
17742xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
17743{
17744 xmlSchemaPSVIIDCBindingPtr refbind, bind;
17745
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017746 refbind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017747 /*
17748 * Find a keyref.
17749 */
17750 while (refbind != NULL) {
17751 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17752 int i, j, k, res;
17753 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
17754 xmlSchemaPSVIIDCKeyPtr refKey, key;
17755
17756 /*
17757 * Find the referred key/unique.
17758 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017759 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017760 do {
17761 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
17762 bind->definition)
17763 break;
17764 bind = bind->next;
17765 } while (bind != NULL);
17766
17767 /*
17768 * Search for a matching key-sequences.
17769 */
17770 for (i = 0; i < refbind->nbNodes; i++) {
17771 res = 0;
17772 if (bind != NULL) {
17773 refKeys = refbind->nodeTable[i]->keys;
17774 for (j = 0; j < bind->nbNodes; j++) {
17775 keys = bind->nodeTable[j]->keys;
17776 for (k = 0; k < bind->definition->nbFields; k++) {
17777 refKey = refKeys[k];
17778 key = keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017779 res = xmlSchemaAreValuesEqual(vctxt,
17780 key->type, key->compValue,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017781 refKey->type, refKey->compValue);
17782 if (res == 0)
17783 break;
17784 else if (res == -1) {
17785 return (-1);
17786 }
17787 }
17788 if (res == 1) {
17789 /*
17790 * Match found.
17791 */
17792 break;
17793 }
17794 }
17795 }
17796 if (res == 0) {
17797 /* TODO: Report the key-sequence. */
17798 xmlSchemaVCustomErr(vctxt,
17799 XML_SCHEMAV_CVC_IDC,
17800 refbind->nodeTable[i]->node,
17801 (xmlSchemaTypePtr) refbind->definition,
17802 "No matching key-sequence found", NULL);
17803 }
17804 }
17805 }
17806 refbind = refbind->next;
17807 }
17808 return (0);
17809}
17810#endif /* IDC_ENABLED */
17811
17812#ifdef ELEM_INFO_ENABLED
17813/**
17814 * xmlSchemaBeginElement:
17815 * @vctxt: the WXS validation context
17816 *
17817 * Just a temporary workaround to simulate streaming validation
17818 * a bit.
17819 */
17820static void
17821xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
17822{
17823 vctxt->depth++;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017824 vctxt->nodeInfo = xmlSchemaGetFreshElemInfo(vctxt, vctxt->depth);
17825 vctxt->nodeInfo->node = vctxt->node;
17826 vctxt->nodeInfo->localName = vctxt->node->name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017827 if (vctxt->node->ns != NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017828 vctxt->nodeInfo->namespaceName = vctxt->node->ns->href;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017829 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017830 vctxt->nodeInfo->namespaceName = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017831}
17832
17833/**
17834 * xmlSchemaEndElement:
17835 * @vctxt: the WXS validation context
17836 *
17837 * Just a temporary workaround to simulate streaming validation
17838 * a bit.
17839 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017840static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017841xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
17842{
17843 if (vctxt->depth < 0) {
17844 /* TODO: raise error? */
17845 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017846 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017847 }
17848#ifdef IDC_ENABLED
17849 /*
17850 * Evaluate the history of changes of active state objects.
17851 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017852 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
17853 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017854
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017855 if (vctxt->nodeInfo->value != NULL) {
17856 xmlSchemaFreeValue(vctxt->nodeInfo->value);
17857 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017858 }
17859 /*
17860 * TODO: 6 The element information item must be ·valid· with respect to each of
17861 * the {identity-constraint definitions} as per Identity-constraint
17862 * Satisfied (§3.11.4).
17863 */
17864 /*
17865 * Validate IDC keyrefs.
17866 */
17867 xmlSchemaCheckCVCIDCKeyRef(vctxt);
17868#endif
17869
17870 /*
17871 * Merge/free the IDC table.
17872 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017873 if (vctxt->nodeInfo->idcTable != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017874#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017875#ifdef DEBUG_IDC
17876 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017877 vctxt->nodeInfo->namespaceName,
17878 vctxt->nodeInfo->localName,
17879 vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017880#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017881 if (vctxt->depth > 0) {
17882 /*
17883 * Merge the IDC node table with the table of the parent node.
17884 */
17885 xmlSchemaBubbleIDCNodeTables(vctxt);
17886 }
17887 /*
17888 * TODO: Don't free the PSVI IDC tables if they are
17889 * requested for the PSVI.
17890 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017891 xmlSchemaIDCFreeIDCTable(vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017892#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017893 vctxt->nodeInfo->idcTable = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017894 }
17895
17896 /*
17897 * Cleanup IDC matchers.
17898 */
17899#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017900 if (vctxt->nodeInfo->idcMatchers != NULL) {
17901 xmlSchemaIDCFreeMatcherList(vctxt->nodeInfo->idcMatchers);
17902 vctxt->nodeInfo->idcMatchers = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017903 }
17904#endif
17905
17906 /*
17907 * Skip further processing if we are on the validation root.
17908 */
17909 if (vctxt->depth == 0) {
17910 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017911 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017912 }
17913
17914 /*
17915 * Reset the bubbleDepth if needed.
17916 */
17917#ifdef IDC_ENABLED
17918 if (vctxt->aidcs != NULL) {
17919 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
17920 do {
17921 if (aidc->bubbleDepth == vctxt->depth) {
17922 /*
17923 * A bubbleDepth of a key/unique IDC matches the current
17924 * depth, this means that we are leaving the scope of the
17925 * top-most keyref IDC.
17926 */
17927 aidc->bubbleDepth = -1;
17928 }
17929 aidc = aidc->next;
17930 } while (aidc != NULL);
17931 }
17932#endif
17933 vctxt->depth--;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017934 /*
17935 * Clear the current elemInfo.
17936 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017937 if (vctxt->nodeInfo->value != NULL) {
17938 xmlSchemaFreeValue(vctxt->nodeInfo->value);
17939 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017940 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017941 vctxt->nodeInfo = vctxt->elemInfos[vctxt->depth];
17942 vctxt->node = vctxt->nodeInfo->node;
17943
17944 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017945}
17946
17947#endif /* ELEM_INFO_ENABLED */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017948
17949/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017950 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000017951 * @ctxt: a schema validation context
17952 * @node: the top node.
17953 *
17954 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017955 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000017956 *
17957 * Returns 0 if the element is schemas valid, a positive error code
17958 * number otherwise and -1 in case of internal or API error.
17959 */
17960static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017961xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
17962 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017963{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017964 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017965 int ret = 0;
17966 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017967 xmlAttrPtr attr;
17968 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017969 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000017970
17971 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017972 * This one is called by xmlSchemaValidateElementByWildcardInternal,
17973 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017974 * Note that @elemDecl will be the declaration and never the
17975 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017976 */
Daniel Veillard3646d642004-06-02 19:19:14 +000017977
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017978 if (ctxt == NULL) {
17979 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
17980 "Internal error: xmlSchemaValidateElementByDeclaration, "
17981 "bad arguments.\n",
17982 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017983 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000017984 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017985
17986 elem = ctxt->node;
17987
17988 /*
17989 * cvc-elt (3.3.4) : 1
17990 */
17991 if (elemDecl == NULL) {
17992 xmlSchemaVCustomErr(ctxt,
17993 XML_SCHEMAV_CVC_ELT_1,
17994 elem, NULL,
17995 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017996 /*
17997 * Evaluate IDCs even if an error occured.
17998 */
17999#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018000 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018001 return (-1);
18002#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018003 return (ctxt->err);
18004 }
18005 /*
18006 * cvc-elt (3.3.4) : 2
18007 */
18008 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
18009 xmlSchemaVCustomErr(ctxt,
18010 XML_SCHEMAV_CVC_ELT_2,
18011 elem, NULL,
18012 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018013 /*
18014 * Evaluate IDCs even if an error occured.
18015 */
18016#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018017 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018018 return (-1);
18019#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018020 return (ctxt->err);
18021 }
18022
18023 /*
18024 * cvc-elt (3.3.4) : 3
18025 * Handle 'xsi:nil'.
18026 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018027
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018028 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018029 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018030 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18031 ctxt->node = (xmlNodePtr) attr;
18032 ctxt->cur = attr->children;
18033 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
18034 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
18035 BAD_CAST attrValue, 1, 1, 1, 1);
18036 ctxt->node = elem;
18037 ctxt->type = (xmlSchemaTypePtr) elemDecl;
18038 if (ret < 0) {
18039 xmlSchemaVCustomErr(ctxt,
18040 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018041 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018042 "Internal error: xmlSchemaValidateElementByDeclaration, "
18043 "validating the attribute 'xsi:nil'", NULL);
18044 if (attrValue != NULL)
18045 xmlFree(attrValue);
18046 return (-1);
18047 }
18048 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018049 /*
18050 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018051 */
18052 xmlSchemaVCustomErr(ctxt,
18053 XML_SCHEMAV_CVC_ELT_3_1,
18054 elem, NULL,
18055 "The element is not 'nillable'", NULL);
18056 } else {
18057 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018058 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018059 ret = 0;
18060 /*
18061 * cvc-elt (3.3.4) : 3.2.1
18062 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018063 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
18064 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018065 xmlSchemaVCustomErr(ctxt,
18066 XML_SCHEMAV_CVC_ELT_3_2_1,
18067 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018068 elem, (xmlSchemaTypePtr) elemDecl,
18069 "The 'nilled' element must have no character or "
18070 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018071 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
18072 }
18073 /*
18074 * cvc-elt (3.3.4) : 3.2.2
18075 */
18076 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
18077 (elemDecl->value != NULL)) {
18078 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
18079 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018080 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018081 "There is a fixed value constraint defined for "
18082 "the 'nilled' element", NULL);
18083 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
18084 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018085 if (ret == 0)
18086 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018087 }
18088 }
18089 if (attrValue != NULL)
18090 xmlFree(attrValue);
18091 }
18092
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018093
18094 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018095 /*
18096 * cvc-elt (3.3.4) : 4
18097 * Handle 'xsi:type'.
18098 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018099
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018100 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
18101 if (attr != NULL) {
18102 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018103
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018104 /*
18105 * TODO: We should report a *warning* that the type was overriden
18106 * by the instance.
18107 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018108
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018109 /*
18110 * cvc-elt (3.3.4) : 4.1
18111 */
18112 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18113 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
18114 &nsName, &local);
18115 if (ret < 0) {
18116 xmlSchemaVCustomErr(ctxt,
18117 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018118 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018119 "Internal error: xmlSchemaValidateElementByDeclaration, "
18120 "validating the attribute 'xsi:type'", NULL);;
18121 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018122 FREE_AND_NULL(nsName)
18123 FREE_AND_NULL(local)
18124 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018125 } else if (ret == 1) {
18126 xmlSchemaVSimpleTypeErr(ctxt,
18127 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18128 (xmlNodePtr) attr, attrValue,
18129 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
18130 } else if (ret == 2) {
18131 xmlSchemaVCustomErr(ctxt,
18132 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18133 (xmlNodePtr) attr,
18134 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18135 "The QName value '%s' has no "
18136 "corresponding namespace declaration in scope",
18137 attrValue);
18138 } else {
18139 /*
18140 * cvc-elt (3.3.4) : 4.2
18141 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018142 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
18143 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018144 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018145
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018146 xmlSchemaVCustomErr(ctxt,
18147 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018148 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018149 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18150 "The value %s does not resolve to a type "
18151 "definition",
18152 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
18153 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018154 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018155 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018156 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018157 */
18158 }
18159 }
18160 FREE_AND_NULL(attrValue)
18161 FREE_AND_NULL(nsName)
18162 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018163 }
18164 /* TODO: Change the handling of missing types according to
18165 * the spec.
18166 */
18167 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018168 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018169 XML_SCHEMAV_CVC_TYPE_1,
18170 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018171 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018172 /*
18173 * Evaluate IDCs even if an error occured.
18174 */
18175#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018176 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018177 return (-1);
18178#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018179 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018180 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018181
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018182 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018183 * Remember the actual-type definition.
18184 */
18185#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018186 ctxt->nodeInfo->typeDef = actualType;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018187#endif
18188
18189 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018190 * TODO: Since this should be already checked by the content model automaton,
18191 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
18192 * has been changed to XML_SCHEMAV_INTERNAL.
18193 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018194 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000018195 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018196 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018197 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018198 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018199 "Element %s: missing child %s\n",
18200 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018201 }
18202 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018203 }
18204 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018205 /*
18206 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018207 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018208 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000018209 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018210 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018211 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018212 "Element %s: missing child %s found %s\n",
18213 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018214 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018215 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018216 */
18217 if (elemHasContent == -1)
18218 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018219
18220 /*
18221 * IDC: Register identity-constraint XPath matchers.
18222 */
18223#ifdef IDC_ENABLED
18224 if (elemDecl->idcs != NULL)
18225 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
18226 /*
18227 * Evaluate IDCs.
18228 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018229 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018230 return (-1);
18231#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018232 /*
18233 * cvc-elt (3.3.4) : 5
18234 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018235 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018236 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018237 * cvc-elt (3.3.4) : 5.1
18238 * If the declaration has a {value constraint},
18239 * the item has neither element nor character [children] and
18240 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018241 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018242 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
18243 /*
18244 * cvc-elt (3.3.4) : 5.1.1
18245 * If the ·actual type definition· is a ·local type definition·
18246 * then the canonical lexical representation of the {value constraint}
18247 * value must be a valid default for the ·actual type definition· as
18248 * defined in Element Default Valid (Immediate) (§3.3.6).
18249 */
18250 /*
18251 * NOTE: 'local' above means types aquired by xsi:type.
18252 */
18253 ret = 0;
18254 if (actualType != elemDecl->subtypes) {
18255 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
18256 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018257 elemDecl->value, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018258 if (ret < 0) {
18259 xmlSchemaVCustomErr(ctxt,
18260 XML_SCHEMAV_INTERNAL,
18261 elem, actualType,
18262 "Internal error: xmlSchemaValidateElementByDeclaration, "
18263 "validating a default value", NULL);
18264 return (-1);
18265 }
18266 }
18267 /*
18268 * cvc-elt (3.3.4) : 5.1.2
18269 * The element information item with the canonical lexical
18270 * representation of the {value constraint} value used as its
18271 * ·normalized value· must be ·valid· with respect to the
18272 * ·actual type definition· as defined by Element Locally Valid (Type)
18273 * (§3.3.4).
18274 */
18275 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018276 * Disable validation of the simple content, if it was already
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018277 * done above.
18278 */
18279 if (ret == 0) {
18280 if (actualType != elemDecl->subtypes)
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018281 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018282 else
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018283 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018284 ctxt->node = elem;
18285 if (ret < 0) {
18286 xmlSchemaVCustomErr(ctxt,
18287 XML_SCHEMAV_INTERNAL,
18288 elem, actualType,
18289 "Internal error: xmlSchemaValidateElementByDeclaration, "
18290 "validating against the type", NULL);
18291 return (-1);
18292 }
18293 /*
18294 * PSVI: Create a text node on the instance element.
18295 */
18296 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
18297 xmlNodePtr textChild;
18298
18299 textChild = xmlNewText(elemDecl->value);
18300 if (textChild == NULL) {
18301 xmlSchemaVCustomErr(ctxt,
18302 XML_SCHEMAV_INTERNAL,
18303 elem, actualType,
18304 "Internal error: xmlSchemaValidateElementByDeclaration, "
18305 "could not create a default text node for the instance",
18306 NULL);
18307 } else
18308 xmlAddChild(elem, textChild);
18309 }
18310 }
18311
18312 } else {
18313 /*
18314 * 5.2.1 The element information item must be ·valid· with respect
18315 * to the ·actual type definition· as defined by Element Locally
18316 * Valid (Type) (§3.3.4).
18317 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018318 ret = xmlSchemaValidateElementByType(ctxt, actualType, nilled, 1);
18319 /*
18320 * Consume the computed value for IDCs, ect. Note that default
18321 * values are not supported yet.
18322 */
18323#ifdef ELEM_INFO_ENABLED
18324 if (ctxt->value != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018325 ctxt->nodeInfo->value = ctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018326 ctxt->value = NULL;
18327 }
18328#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018329 ctxt->node = elem;
18330 if (ret < 0) {
18331 xmlSchemaVCustomErr(ctxt,
18332 XML_SCHEMAV_INTERNAL,
18333 elem, actualType,
18334 "Internal error: xmlSchemaValidateElementByDeclaration, "
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018335 "calling validation by type", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018336 return (-1);
18337 }
18338 /*
18339 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
18340 * not applied, all of the following must be true:
18341 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018342 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
18343 /*
18344 * 5.2.2.1 The element information item must have no element
18345 * information item [children].
18346 *
18347 * TODO REDUNDANT: If the actual type exists, the above call to
18348 * xmlSchemaValidateElementByType will already check for element
18349 * nodes.
18350 */
18351 if (xmlSchemaHasElemContent(elem)) {
18352 xmlSchemaVCustomErr(ctxt,
18353 XML_SCHEMAV_CVC_ELT_5_2_2_1,
18354 elem, (xmlSchemaTypePtr) elemDecl,
18355 "Elements in the content are not allowed if it is "
18356 "constrained by a fixed value", NULL);
18357 } else {
18358 /*
18359 * 5.2.2.2 The appropriate case among the following must
18360 * be true:
18361 */
18362
18363 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
18364 xmlChar *value;
18365 /*
18366 * 5.2.2.2.1 If the {content type} of the ·actual type
18367 * definition· is mixed, then the *initial value* of the
18368 * item must match the canonical lexical representation
18369 * of the {value constraint} value.
18370 *
18371 * ... the *initial value* of an element information
18372 * item is the string composed of, in order, the
18373 * [character code] of each character information item in
18374 * the [children] of that element information item.
18375 */
18376 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18377 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18378 /*
18379 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018380 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018381 */
18382 xmlSchemaVCustomErr(ctxt,
18383 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
18384 elem, (xmlSchemaTypePtr) elemDecl,
18385 "The value does not match the cononical "
18386 "lexical representation of the fixed constraint",
18387 NULL);
18388 }
18389 if (value != NULL)
18390 xmlFree(value);
18391 } else if ((actualType->contentType ==
18392 XML_SCHEMA_CONTENT_SIMPLE) ||
18393 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
18394 xmlChar *value;
18395
18396 /*
18397 * 5.2.2.2.2 If the {content type} of the ·actual type
18398 * definition· is a simple type definition, then the
18399 * *actual value* of the item must match the canonical
18400 * lexical representation of the {value constraint} value.
18401 */
18402 /*
18403 * TODO: *actual value* is the normalized value, impl. this.
18404 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018405 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018406 *
18407 */
18408 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18409 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18410 xmlSchemaVCustomErr(ctxt,
18411 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
18412 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018413 "The normalized value does not match the canonical "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018414 "lexical representation of the fixed constraint",
18415 NULL);
18416 }
18417 if (value != NULL)
18418 xmlFree(value);
18419
18420 }
18421 /*
18422 * TODO: What if the content type is not 'mixed' or simple?
18423 */
18424
18425 }
18426
18427 }
18428 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018429 /*
18430 * TODO: 7 If the element information item is the ·validation root·, it must be
18431 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
18432 */
18433
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018434 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018435}
18436
Daniel Veillard4255d502002-04-16 15:50:10 +000018437/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018438 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018439 * @ctxt: a schema validation context
18440 * @node: the top node.
18441 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018442 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
18443 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018444 *
18445 * Returns 0 if the element is valid, a positive error code
18446 * number otherwise and -1 in case of an internal error.
18447 */
18448static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018449xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
18450 xmlSchemaWildcardPtr wild,
18451 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018452{
18453 const xmlChar *uri;
18454 int ret = 0;
18455 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018456
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018457 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018458 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
18459 if (ret == -1) {
18460 xmlSchemaVCustomErr(ctxt,
18461 XML_SCHEMAV_INTERNAL,
18462 ctxt->node, NULL,
18463 "Internal error: xmlSchemaValidateElement, "
18464 "assembling schema by xsi", NULL);
18465 return (-1);
18466 }
18467 /*
18468 * NOTE: We won't react on schema parser errors here.
18469 * TODO: But a warning would be nice.
18470 */
18471 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018472 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
18473 xmlSchemaElementPtr decl = NULL;
18474
18475 if (node->ns != NULL)
18476 decl = xmlHashLookup3(ctxt->schema->elemDecl,
18477 node->name, node->ns->href, NULL);
18478 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018479 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
18480 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018481 if (decl != NULL) {
18482 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018483 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018484 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018485 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018486 "Internal error: xmlSchemaValidateAnyInternal, "
18487 "validating an element in the context of a wildcard.",
18488 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000018489 }
18490 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018491 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
18492 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018493 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018494 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018495 /*
18496 * Evaluate IDCs even if a validation error occured.
18497 */
18498#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018499 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018500 return(-1);
18501#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018502 return (ctxt->err);
18503 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018504 /*
18505 * Evaluate IDCs; we need to know if an IDC field resolves to
18506 * such a node. This node has no type definition and will
18507 * definitely result in an IDC validation error if an IDC field
18508 * resolves.
18509 */
18510#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018511 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018512 return(-1);
18513#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018514 }
18515 if (node->children != NULL) {
18516 child = node->children;
18517 do {
18518 if (child->type == XML_ELEMENT_NODE) {
18519 if (child->ns != NULL)
18520 uri = child->ns->href;
18521 else
18522 uri = NULL;
18523 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018524 /* TODO: error code. */
18525 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018526 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018527 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000018528 return (ctxt->err);
18529 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018530#ifdef ELEM_INFO_ENABLED
18531 ctxt->node = child;
18532 xmlSchemaBeginElement(ctxt);
18533#endif
18534 /*
18535 * Recurse over the children.
18536 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018537 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
18538 wild, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018539 if (ret == -1)
18540 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018541#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018542 if (xmlSchemaEndElement(ctxt) == -1)
18543 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018544#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018545 if (ret != 0)
18546 return (ret);
18547 }
18548 child = child->next;
18549 } while (child != NULL);
18550 }
18551 return (0);
18552}
18553
18554/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018555 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018556 * @ctxt: a schema validation context
18557 *
18558 * Returns 0 if the element is valid, a positive error code
18559 * number otherwise and -1 in case of an internal or API error.
18560 */
18561static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018562xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
18563 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018564{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018565 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
18566 (ctxt->node == NULL)) {
18567 xmlSchemaVCustomErr(ctxt,
18568 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
18569 "Internal error: xmlSchemaValidateElementByWildcard, "
18570 "bad arguments", NULL);
18571 return (-1);
18572 }
18573 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
18574 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000018575}
18576
18577/**
William M. Brack2f2a6632004-08-20 23:09:47 +000018578 * xmlSchemaValidateAnyTypeContent:
18579 * @ctxt: a schema validation context
18580 * @node: the current element
18581 *
18582 * This one validates the content of an element of the type
18583 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
18584 * thus elements in the subtree will be validated, if a corresponding
18585 * declaration in the schema exists.
18586 *
18587 * Returns 0 if the element and its subtree is valid, a positive error code
18588 * otherwise and -1 in case of an internal or API error.
18589 */
18590static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018591xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
18592 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000018593{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018594 xmlSchemaTypePtr oldtype;
18595 xmlNodePtr top, cur;
18596 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000018597 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018598
18599 if ((type == NULL) || (ctxt->node == NULL))
18600 return (-1);
18601
18602 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018603 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018604
18605 oldtype = ctxt->type;
18606 top = ctxt->node;
18607 /*
18608 * STREAM: Child nodes are processed.
18609 */
18610 cur = ctxt->node->children;
18611 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018612 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018613 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018614 /*
18615 * The process contents of the wildcard is "lax", thus
18616 * we need to validate the element if a declaration
18617 * exists.
18618 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018619 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018620 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018621 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018622 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018623 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018624 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018625 ctxt->node = cur;
18626 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
18627 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000018628 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018629 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000018630 "Internal error: xmlSchemaValidateAnyTypeContent, "
18631 "validating an element in the context of a wildcard.",
18632 NULL, NULL);
18633 return (ret);
18634 } else if (ret > 0)
18635 return (ret);
18636 skipContent = 1;
18637 }
18638 }
18639 /*
18640 * Browse the full subtree, deep first.
18641 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018642 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018643 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018644 cur = cur->children;
18645 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018646 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018647 cur = cur->next;
18648 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018649 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018650 while (cur != top) {
18651 if (cur->parent != NULL)
18652 cur = cur->parent;
18653 if ((cur != top) && (cur->next != NULL)) {
18654 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000018655 break;
18656 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018657 if (cur->parent == NULL) {
18658 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018659 break;
18660 }
18661 }
18662 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018663 if (cur == top)
18664 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018665 } else
18666 break;
18667 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018668 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000018669 return (0);
18670}
18671
18672/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018673 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000018674 * @ctxt: a schema validation context
18675 * @node: the top node.
18676 *
18677 * Validate the content of an element expected to be a complex type type
18678 * xmlschema-1.html#cvc-complex-type
18679 * Validation Rule: Element Locally Valid (Complex Type)
18680 *
18681 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000018682 * number otherwise and -1 in case of internal or API error.
18683 * Note on reported errors: Although it might be nice to report
18684 * the name of the simple/complex type, used to validate the content
18685 * of a node, it is quite unnecessary: for global defined types
18686 * the local name of the element is equal to the NCName of the type,
18687 * for local defined types it makes no sense to output the internal
18688 * computed name of the type. TODO: Instead, one should attach the
18689 * struct of the type involved to the error handler - this allows
18690 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000018691 */
18692static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018693xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018694 xmlSchemaTypePtr type,
18695 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018696{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018697 xmlSchemaTypePtr oldtype;
18698 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018699 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000018700 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018701 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000018702
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018703 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
18704 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018705
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018706 oldtype = ctxt->type;
18707 ctxt->type = type;
18708 elem = ctxt->node;
18709
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018710 /*
18711 * Verify the attributes
18712 */
18713 /*
18714 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018715 */
18716 /* NOTE: removed, since a check for abstract is
18717 * done in the cvc-type constraint.
18718 *
18719 *
18720 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
18721 * xmlSchemaVComplexTypeErr(ctxt,
18722 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
18723 * elem, type,
18724 * "The type definition is abstract");
18725 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
18726 *}
18727 */
18728
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018729 attrs = ctxt->attr;
18730 attrTop = ctxt->attrTop;
18731 /*
18732 * STREAM: Attribute nodes are processed.
18733 */
18734 xmlSchemaRegisterAttributes(ctxt, elem->properties);
18735 xmlSchemaValidateAttributes(ctxt, elem, type);
18736 if (ctxt->attr != NULL)
18737 xmlSchemaFreeAttributeStates(ctxt->attr);
18738 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018739 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018740
18741 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018742 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018743 * model was defined. Somehow ->contModel is always not NULL
18744 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018745 * TODO: Check if the obove still occurs.
18746 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018747 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018748 case XML_SCHEMA_CONTENT_EMPTY: {
18749 /*
18750 * 1 If the {content type} is empty, then the element information
18751 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000018752 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018753 /*
18754 * TODO: Is the entity stuff correct?
18755 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018756 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018757 xmlSchemaVComplexTypeErr(ctxt,
18758 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018759 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018760 "Character or element content is not allowed, "
18761 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018762 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018763 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018764 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018765 case XML_SCHEMA_CONTENT_MIXED:
18766 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018767 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018768 /*
18769 * The type has 'anyType' as its base and no content model
18770 * is defined -> use 'anyType' as the type to validate
18771 * against.
18772 */
18773 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
18774 /* TODO: Handle -1. */
18775 break;
18776 }
18777 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018778 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018779 {
18780 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018781 xmlChar *values[10];
18782 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018783
18784 /*
18785 * Content model check initialization.
18786 */
18787 if (type->contModel != NULL) {
18788 oldregexp = ctxt->regexp;
18789 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
18790 (xmlRegExecCallbacks)
18791 xmlSchemaValidateCallback, ctxt);
18792#ifdef DEBUG_AUTOMATA
18793 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
18794#endif
18795 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018796 /*
18797 * STREAM: Children are processed.
18798 */
18799 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018800 while (child != NULL) {
18801 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018802 if (child->ns != NULL)
18803 nsUri = child->ns->href;
18804 else
18805 nsUri = NULL;
18806 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018807 child->name, nsUri, child);
18808 if (ctxt->err == XML_SCHEMAV_INTERNAL)
18809 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018810 /*
18811 * URGENT TODO: Could we anchor an error report
18812 * here to notify of invalid elements?
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018813 * TODO: Perhaps it would be better to report
18814 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018815 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018816#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000018817 if (ret < 0)
18818 xmlGenericError(xmlGenericErrorContext,
18819 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000018820 else
18821 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018822 " --> %s\n", child->name);
18823#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018824 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018825 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
18826 &values[0], &terminal);
18827 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018828 XML_SCHEMAV_ELEMENT_CONTENT,
18829 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018830 "This element is not expected",
18831 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018832 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018833 /*
18834 * Note that this will skip further validation of the
18835 * content.
18836 */
18837 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018838 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018839 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
18840 /*
18841 * TODO: Ask Daniel if this are all character nodes.
18842 */
18843 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
18844 (child->type == XML_ENTITY_NODE) ||
18845 (child->type == XML_ENTITY_REF_NODE) ||
18846 (child->type == XML_CDATA_SECTION_NODE))) {
18847 /*
18848 * 2.3 If the {content type} is element-only, then the
18849 * element information item has no character information
18850 * item [children] other than those whose [character
18851 * code] is defined as a white space in [XML 1.0 (Second
18852 * Edition)].
18853 */
William M. Brack2f2a6632004-08-20 23:09:47 +000018854 xmlSchemaVComplexTypeErr(ctxt,
18855 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018856 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018857 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018858 "because the content type is element-only");
18859 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018860 break;
18861 }
18862 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018863 }
18864 /*
18865 * Content model check finalization.
18866 */
18867 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018868 if (ret == 0) {
18869 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
18870 &values[0], &terminal);
18871 if (nbval + nbneg != 0) {
18872 /*
18873 * If a next value still exists, I does not have to
18874 * mean that there's an element missing, since it
18875 * might be an optional element. So double check it.
18876 */
18877 ret = xmlRegExecPushString(ctxt->regexp,
18878 NULL, NULL);
18879 if (ret <= 0) {
18880 ret = 1;
18881 xmlSchemaVComplexTypeElemErr(ctxt,
18882 XML_SCHEMAV_ELEMENT_CONTENT,
18883 elem, type, "Missing child element(s)",
18884 nbval, nbneg, values);
18885 } else
18886 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018887#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018888 xmlGenericError(xmlGenericErrorContext,
18889 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018890#endif
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018891 }
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018892#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018893 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018894 xmlGenericError(xmlGenericErrorContext,
18895 "Element %s content check succeeded\n",
18896 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018897#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018898 }
18899 xmlRegFreeExecCtxt(ctxt->regexp);
18900 ctxt->regexp = oldregexp;
18901 }
18902 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018903 break;
18904 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018905 case XML_SCHEMA_CONTENT_BASIC:
18906 /*
18907 * If the simple content was already validated
18908 * (e.g. a default value), the content need not
18909 * to be validated again.
18910 */
18911 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018912 xmlChar *value = NULL;
18913 /*
18914 * We hit a complexType with a simpleContent resolving
18915 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000018916 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018917 /*
18918 * 2.2 If the {content type} is a simple type definition,
18919 * then the element information item has no element
18920 * information item [children], and the ·normalized value·
18921 * of the element information item is ·valid· with respect
18922 * to that simple type definition as defined by String
18923 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018924 */
18925 /*
18926 * STREAM: Children are processed.
18927 */
18928 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018929 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018930 /*
18931 * TODO: Could the entity stuff produce elements
18932 * as well?
18933 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018934 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018935 xmlSchemaVComplexTypeErr(ctxt,
18936 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018937 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018938 "Element content is not allowed, because "
18939 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018940 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
18941 break;
18942 }
18943 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018944 }
18945 ctxt->node = elem;
18946 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018947 if (ret == 0) {
18948 /*
18949 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000018950 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018951 /*
18952 * STREAM: Children are processed.
18953 */
18954 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000018955 value = NULL;
18956 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018957 value = xmlNodeGetContent(elem);
18958 /*
18959 * URGENT TODO: Should facets for the simple type validation be
18960 * disabled, if the derivation of facets for complex types
18961 * is implemented?
18962 */
18963 /*
18964 * NOTE: This call won't check the correct types of the
18965 * content nodes, since this should be done here.
18966 */
18967 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000018968 if (ret > 0) {
18969 /*
18970 * NOTE: Although an error will be reported by
18971 * xmlSchemaValidateSimpleTypeValue, the spec wants
18972 * a specific complex type error to be reported
18973 * additionally.
18974 */
18975 xmlSchemaVComplexTypeErr(ctxt,
18976 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018977 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018978 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018979 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
18980 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018981 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018982 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018983 "Element '%s': Error while validating character "
18984 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018985 elem->name, type->name);
18986 if (value != NULL)
18987 xmlFree(value);
18988 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018989 return (-1);
18990 }
William M. Brack2f2a6632004-08-20 23:09:47 +000018991 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018992 if (ret == 0) {
18993 /*
18994 * Apply facets of the complexType. Be sure to pass the
18995 * built-in type to xmlSchemaValidateFacetsInternal.
18996 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018997 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000018998 * are used, or if the facets, defined by this complex type,
18999 * are to be used only. This here applies both facet sets.
19000 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000019001
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019002 ret = xmlSchemaValidateFacetsInternal(ctxt,
19003 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019004 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019005 xmlSchemaVComplexTypeErr(ctxt,
19006 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019007 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019008 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019009 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19010 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019011 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019012 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019013 "Element '%s': Error while validating character "
19014 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000019015 "apply facets.\n",
19016 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019017 if (value != NULL)
19018 xmlFree(value);
19019 ctxt->type = oldtype;
19020 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019021 }
19022 }
19023 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019024 xmlFree(value);
19025
Daniel Veillard01fa6152004-06-29 17:04:39 +000019026 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019027 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019028 default:
19029 TODO xmlGenericError(xmlGenericErrorContext,
19030 "unimplemented content type %d\n",
19031 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000019032 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019033 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019034 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019035}
19036
19037/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019038 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000019039 * @ctxt: a schema validation context
19040 * @elem: an element
19041 * @type: the list of type declarations
19042 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019043 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000019044 *
19045 * Returns 0 if the element is schemas valid, a positive error code
19046 * number otherwise and -1 in case of internal or API error.
19047 */
19048static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019049xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019050 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019051 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019052 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019053{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019054 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000019055
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019056
19057 if ((ctxt == NULL) || (type == NULL)) {
19058 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
19059 "Internal error: xmlSchemaValidateElementByType, "
19060 "bad arguments", NULL);
19061 return (-1);
19062 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019063 /*
19064 * This one is called by "xmlSchemaValidateElementByDeclaration".
19065 * It will forward to the proper validation
19066 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019067 */
19068 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019069 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019070 XML_SCHEMAV_CVC_TYPE_1,
19071 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019072 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019073 return (XML_SCHEMAV_CVC_TYPE_1);
19074 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019075
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019076 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019077 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019078 XML_SCHEMAV_CVC_TYPE_2,
19079 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019080 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019081 return (XML_SCHEMAV_CVC_TYPE_2);
19082 }
19083
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019084 switch (type->type) {
19085 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019086 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
19087 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019088 break;
19089 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019090 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019091 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019092 break;
19093 case XML_SCHEMA_TYPE_BASIC:
19094 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
19095 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
19096 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019097 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019098 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019099 break;
19100 default:
19101 ret = -1;
19102 break;
19103 }
19104 if (ret == -1)
19105 return (-1);
19106 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019107 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019108}
19109
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019110static int
19111xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019112 xmlSchemaAttrStatePtr state)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019113{
19114 xmlChar *value;
19115 const xmlChar *defValue;
19116 xmlSchemaValPtr defVal;
19117 int fixed;
19118 int ret;
19119
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019120 if (ctxt->attrInfo->typeDef == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019121 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
19122 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
19123 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019124 ctxt->node = ctxt->attrInfo->node;
19125 ctxt->cur = ctxt->node->children;
19126 value = xmlNodeListGetString(ctxt->node->doc, ctxt->cur, 1);
19127
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019128 /*
19129 * NOTE: This call also checks the content nodes for correct type.
19130 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019131 ret = xmlSchemaValidateSimpleTypeValue(ctxt, ctxt->attrInfo->typeDef,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019132 value, 1, 1, 1, 1);
19133
19134 /*
19135 * Handle 'fixed' attributes.
19136 */
19137 if (ret > 0) {
19138 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
19139 /*
19140 * NOTE: Fixed value constraints will be not
19141 * applied if the value was invalid, because:
19142 * 1. The validation process does not return a precomputed
19143 * value.
19144 * 2. An invalid value implies a violation of a fixed
19145 * value constraint.
19146 */
19147 } else if (ret == 0) {
19148 state->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019149 if (xmlSchemaGetEffectiveValueConstraint(
19150 (xmlSchemaAttributePtr) ctxt->attrInfo->decl,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019151 &fixed, &defValue, &defVal) && (fixed == 1)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019152
19153 int ws = xmlSchemaGetWhiteSpaceFacetValue(
19154 ctxt->attrInfo->typeDef);
19155
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019156 /*
19157 * cvc-au : Attribute Locally Valid (Use)
19158 * For an attribute information item to be·valid·
19159 * with respect to an attribute use its ·normalized
19160 * value· must match the canonical lexical representation
19161 * of the attribute use's {value constraint} value, if it
19162 * is present and fixed.
19163 */
19164 /*
19165 * NOTE: the validation context holds in ctxt->value the
19166 * precomputed value of the attribute; well for some types,
19167 * fallback to string comparison if no computed value
19168 * exists.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019169 * TODO: Use the *normalized* value and the *canonical* fixed
19170 * value.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019171 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019172 if (ctxt->value != NULL) {
19173 if (defVal == NULL) {
19174 xmlSchemaTypePtr prim;
19175 /*
19176 * Oops, the value was not computed.
19177 */
19178 prim = xmlSchemaGetPrimitiveType(ctxt->attrInfo->typeDef);
19179 if (prim->builtInType == XML_SCHEMAS_STRING) {
19180 xmlSchemaTypePtr builtIn;
19181
19182 builtIn = xmlSchemaGetBuiltInTypeAncestor(
19183 ctxt->attrInfo->typeDef);
19184 defVal = xmlSchemaNewStringValue(
19185 builtIn->builtInType, value);
19186 ((xmlSchemaAttributePtr) ctxt->attrInfo->decl)->defVal =
19187 defVal;
19188 value = NULL;
19189 } else {
19190 xmlSchemaVErr(ctxt, ctxt->attrInfo->node,
19191 XML_SCHEMAV_INTERNAL,
19192 "Internal error: xmlSchemaCheckAttrLocallyValid, "
19193 "could not aquire a precomputed vale",
19194 NULL, NULL);
19195 }
19196 }
19197 if (defVal != NULL) {
19198 if (xmlSchemaCompareValuesWhtsp(ctxt->value,
19199 (xmlSchemaWhitespaceValueType) ws,
19200 defVal, (xmlSchemaWhitespaceValueType) ws) != 0)
19201 state->state =
19202 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
19203 }
19204 } else if (! xmlStrEqual(defValue, BAD_CAST value)) {
19205 /*
19206 * TODO: Remove this and ensure computed values to be
19207 * existent.
19208 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019209 state->state =
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019210 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019211 }
19212 }
19213 }
19214 if (value != NULL) {
19215 xmlFree(value);
19216 }
19217 return (ret);
19218}
19219
Daniel Veillard4255d502002-04-16 15:50:10 +000019220/**
19221 * xmlSchemaValidateAttributes:
19222 * @ctxt: a schema validation context
19223 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000019224 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000019225 *
19226 * Validate the attributes of an element.
19227 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000019228 * 1. Existent, invalid attributes are reported in the form
19229 * "prefix:localName".
19230 * Reason: readability - it is easier to find the actual XML
19231 * representation of the attributes QName.
19232 * 2. Missing attributes are reported in the form
19233 * {"URI", "localName"}.
19234 * This is necessary, since the the prefix need not to be declared
19235 * at all, and thus is not computable.
19236 *
Daniel Veillard4255d502002-04-16 15:50:10 +000019237 * Returns 0 if the element is schemas valid, a positive error code
19238 * number otherwise and -1 in case of internal or API error.
19239 */
19240static int
Daniel Veillard3646d642004-06-02 19:19:14 +000019241xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019242{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019243 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000019244 int ret;
19245 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019246 const xmlChar *defValue;
19247 xmlSchemaValPtr defVal;
19248 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019249 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000019250 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019251 int found;
William M. Brack803812b2004-06-03 02:11:24 +000019252 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019253 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019254 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000019255#ifdef DEBUG_ATTR_VALIDATION
19256 int redundant = 0;
19257#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000019258
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019259
Daniel Veillardc0826a72004-08-10 14:17:33 +000019260 /*
19261 * Allow all attributes if the type is anyType.
19262 */
19263 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
19264 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019265
19266 oldnode = ctxt->node;
19267 if (type != NULL)
19268 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000019269 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019270 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000019271 attrDecl = attrUse->attr;
19272#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019273 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000019274 printf("attr use - use: %d\n", attrDecl->occurs);
19275#endif
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019276 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019277
19278 if (curState->decl == attrUse->attr) {
19279#ifdef DEBUG_ATTR_VALIDATION
19280 redundant = 1;
19281#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019282 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019283 attr = curState->attr;
19284#ifdef DEBUG_ATTR_VALIDATION
19285 printf("attr - name: %s\n", attr->name);
19286 if (attr->ns != NULL)
19287 printf("attr - ns: %s\n", attr->ns->href);
19288 else
19289 printf("attr - ns: none\n");
19290#endif
19291 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019292 if (attr == NULL)
19293 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019294 if (attrDecl->ref != NULL) {
19295 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019296 continue;
19297 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019298 if ((attrDecl->refNs == NULL) ||
19299 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019300 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019301 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019302 continue;
19303 }
19304 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019305 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019306 continue;
19307 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019308 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019309 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019310 if (attr->ns == NULL) {
19311 /*
William M. Bracke7091952004-05-11 15:09:58 +000019312 * accept an unqualified attribute only if the target
19313 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019314 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019315 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000019316 /*
19317 * This check was removed, since the target namespace
19318 * was evaluated during parsing and already took
19319 * "attributeFormDefault" into account.
19320 */
19321 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019322 continue;
19323 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019324 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019325 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019326 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019327 attr->ns->href))
19328 continue;
19329 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019330 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019331#ifdef DEBUG_ATTR_VALIDATION
19332 printf("found\n");
19333#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019334 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000019335 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019336 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
19337 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019338 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019339 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019340 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019341 if (!found) {
19342 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
19343 xmlSchemaAttrStatePtr tmp;
19344
Daniel Veillard3646d642004-06-02 19:19:14 +000019345#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019346 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019347#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019348 /*
19349 * Add a new dummy attribute state.
19350 */
19351 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
19352 if (tmp == NULL) {
19353 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
19354 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019355 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019356 }
19357 tmp->attr = NULL;
19358 tmp->state = XML_SCHEMAS_ATTR_MISSING;
19359 tmp->decl = attrDecl;
19360 tmp->next = NULL;
19361
19362 if (reqAttrStates == NULL) {
19363 reqAttrStates = tmp;
19364 reqAttrStatesTop = tmp;
19365 } else {
19366 reqAttrStatesTop->next = tmp;
19367 reqAttrStatesTop = tmp;
19368 }
19369 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
19370 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
19371 &fixed, &defValue, &defVal))) {
19372 xmlSchemaAttrStatePtr tmp;
19373 /*
19374 * Handle non existent default/fixed attributes.
19375 */
19376 tmp = (xmlSchemaAttrStatePtr)
19377 xmlMalloc(sizeof(xmlSchemaAttrState));
19378 if (tmp == NULL) {
19379 xmlSchemaVErrMemory(ctxt,
19380 "registering schema specified attributes", NULL);
19381 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019382 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019383 }
19384 tmp->attr = NULL;
19385 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
19386 tmp->decl = attrDecl;
19387 tmp->value = defValue;
19388 tmp->next = NULL;
19389
19390 if (defAttrStates == NULL) {
19391 defAttrStates = tmp;
19392 defAttrStates = tmp;
19393 } else {
19394 defAttrStates->next = tmp;
19395 defAttrStatesTop = tmp;
19396 }
19397 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019398 }
19399 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000019400 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019401 /*
19402 * Add required attributes to the attribute states of the context.
19403 */
19404 if (reqAttrStates != NULL) {
19405 if (ctxt->attr == NULL) {
19406 ctxt->attr = reqAttrStates;
19407 } else {
19408 ctxt->attrTop->next = reqAttrStates;
19409 }
19410 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019411 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019412 /*
19413 * Process wildcards.
19414 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019415
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019416 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019417#ifdef DEBUG_ATTR_VALIDATION
19418 xmlSchemaWildcardNsPtr ns;
19419 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019420 if (type->attributeWildcard->processContents ==
19421 XML_SCHEMAS_ANY_LAX)
19422 printf("processContents: lax\n");
19423 else if (type->attributeWildcard->processContents ==
19424 XML_SCHEMAS_ANY_STRICT)
19425 printf("processContents: strict\n");
19426 else
19427 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019428 if (type->attributeWildcard->any)
19429 printf("type: any\n");
19430 else if (type->attributeWildcard->negNsSet != NULL) {
19431 printf("type: negated\n");
19432 if (type->attributeWildcard->negNsSet->value == NULL)
19433 printf("ns: (absent)\n");
19434 else
19435 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
19436 } else if (type->attributeWildcard->nsSet != NULL) {
19437 printf("type: set\n");
19438 ns = type->attributeWildcard->nsSet;
19439 while (ns != NULL) {
19440 if (ns->value == NULL)
19441 printf("ns: (absent)\n");
19442 else
19443 printf("ns: %s\n", ns->value);
19444 ns = ns->next;
19445 }
19446 } else
19447 printf("empty\n");
19448
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019449
19450#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000019451 curState = ctxt->attr;
19452 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019453 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
19454 if (curState->attr->ns != NULL)
19455 nsURI = curState->attr->ns->href;
19456 else
19457 nsURI = NULL;
19458 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
19459 nsURI)) {
19460 /*
19461 * Handle processContents.
19462 */
19463 if ((type->attributeWildcard->processContents ==
19464 XML_SCHEMAS_ANY_LAX) ||
19465 (type->attributeWildcard->processContents ==
19466 XML_SCHEMAS_ANY_STRICT)) {
19467
19468 attr = curState->attr;
19469 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019470 attr->name, nsURI);
19471 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019472 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019473 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019474 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
19475 /* TODO
19476 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
19477 */
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019478 } else if (type->attributeWildcard->processContents ==
19479 XML_SCHEMAS_ANY_LAX) {
19480 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019481 } else
19482 curState->state = XML_SCHEMAS_ATTR_WILD_NO_DECL;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019483 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000019484 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019485 }
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019486 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019487 curState = curState->next;
19488 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019489 }
19490
Daniel Veillardc0826a72004-08-10 14:17:33 +000019491 if (ctxt->attr != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019492 int valueNeeded;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019493
19494 /*
19495 * Validate the value of the attribute.
19496 */
19497 if (ctxt->value != NULL) {
19498 xmlSchemaFreeValue(ctxt->value);
19499 ctxt->value = NULL;
19500 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019501 curState = ctxt->attr;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019502 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019503 valueNeeded = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019504 switch (curState->state) {
19505 case XML_SCHEMAS_ATTR_VALIDATE_VALUE:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019506
19507 /*
19508 * Create an attribute info if needed.
19509 */
19510 if (ctxt->attrInfo == NULL) {
19511 ctxt->attrInfo = (xmlSchemaElemInfoPtr)
19512 xmlMalloc(sizeof(xmlSchemaElemInfo));
19513 if (ctxt->attrInfo == NULL) {
19514 xmlSchemaVErrMemory(ctxt,
19515 "allocating an attribute info", NULL);
19516 goto fatal_exit;
19517 }
19518 }
19519 /*
19520 * Init the attribute info.
19521 */
19522 ctxt->attrInfo->flags = 0;
19523 ctxt->attrInfo->node = (xmlNodePtr) curState->attr;
19524 ctxt->attrInfo->decl = (xmlSchemaTypePtr) curState->decl;
19525 ctxt->attrInfo->value = NULL;
19526 if (curState->decl != NULL)
19527 ctxt->attrInfo->typeDef = curState->decl->subtypes;
19528 else
19529 ctxt->attrInfo->typeDef = NULL;
19530 if (curState->attr->ns != NULL)
19531 ctxt->attrInfo->namespaceName =
19532 curState->attr->ns->href;
19533 else
19534 ctxt->attrInfo->namespaceName = NULL;
19535 ctxt->attrInfo->localName = curState->attr->name;
19536
19537 ctxt->nodeInfo = ctxt->attrInfo;
19538
19539#ifdef IDC_ENABLED
19540 /*
19541 * Evaluate IDCs.
19542 */
19543 if (ctxt->xpathStates != NULL) {
19544 ret = xmlSchemaXPathEvaluate(ctxt,
19545 XML_ATTRIBUTE_NODE);
19546 if (ret == -1)
19547 goto fatal_exit;
19548 }
19549
19550#endif
19551 ret = xmlSchemaCheckAttrLocallyValid(ctxt, curState);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019552 if (ret == -1)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019553 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019554 if ((ret != 0) && (ctxt->value != NULL)) {
19555 xmlSchemaFreeValue(ctxt->value);
19556 ctxt->value = NULL;
19557 }
19558 /* No break on purpose. */
19559 case XML_SCHEMAS_ATTR_CHECKED:
19560#ifdef IDC_ENABLED
19561 if (ctxt->xpathStates != NULL) {
19562 /*
19563 * Evaluate IDCs.
19564 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019565 if (ctxt->value != NULL) {
19566 ctxt->attrInfo->value = ctxt->value;
19567 ctxt->value = NULL;
19568 }
19569 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
19570 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019571 }
19572 break;
19573#endif
19574 default:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019575 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019576 }
19577 curState = curState->next;
19578 }
19579
19580 /*
19581 * Report missing and illegal attributes.
19582 */
19583 curState = ctxt->attr;
19584 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019585 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
19586 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019587 if (curState->decl != NULL) {
19588 if (curState->decl->ref != NULL)
19589 attrDecl = curState->decl->refDecl;
19590 else
19591 attrDecl = curState->decl;
19592 } else
19593 attrDecl = NULL;
19594 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
19595 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
19596 } else if (curState->state ==
19597 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
19598 xmlSchemaVCustomErr(ctxt,
19599 XML_SCHEMAV_CVC_ATTRIBUTE_2,
19600 (xmlNodePtr) attr,
19601 (xmlSchemaTypePtr) attrDecl,
19602 "The type definition is absent",
19603 NULL);
19604 } else if (curState->state ==
19605 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
19606 xmlSchemaVCustomErr(ctxt,
19607 XML_SCHEMAV_CVC_AU,
19608 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
19609 "The value does not match the fixed value "
19610 "constraint", NULL);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019611 } else if (curState->state == XML_SCHEMAS_ATTR_WILD_NO_DECL) {
19612 xmlSchemaVWildcardErr(ctxt,
19613 XML_SCHEMAV_CVC_WILDCARD,
19614 (xmlNodePtr) attr,
19615 type->attributeWildcard,
19616 "No global attribute declaration found, but "
19617 "stipulated by the strict processContents of "
19618 "the wildcard");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019619 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019620 /* TODO: "prohibited" won't ever be touched here!.
19621 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
19622 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019623 /*
19624 * TODO: One might report different error messages
19625 * for the following errors.
19626 */
19627 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019628 xmlSchemaVIllegalAttrErr(ctxt,
19629 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
19630 } else {
19631 xmlSchemaVIllegalAttrErr(ctxt,
19632 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
19633 }
19634 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019635 }
19636 curState = curState->next;
19637 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019638 }
19639
19640 /*
19641 * Add missing default/fixed attributes.
19642 */
19643 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
19644 curState = defAttrStates;
19645 while (curState != NULL) {
19646 attrDecl = curState->decl;
19647 if (attrDecl->ref != NULL)
19648 attrDecl = attrDecl->refDecl;
19649 /*
19650 * PSVI: Add a new attribute node to the current element.
19651 */
19652 if (attrDecl->targetNamespace == NULL) {
19653 xmlNewProp(elem, attrDecl->name, curState->value);
19654 } else {
19655 xmlNsPtr ns;
19656
19657 ns = xmlSearchNsByHref(elem->doc, elem,
19658 attrDecl->targetNamespace);
19659 if (ns == NULL) {
19660 xmlChar prefix[12];
19661 int counter = 1;
19662
19663 attr = curState->attr;
19664 /*
19665 * Create a namespace declaration on the validation
19666 * root node if no namespace declaration is in scope.
19667 */
19668 snprintf((char *) prefix, sizeof(prefix), "p");
19669 /*
19670 * This is somehow not performant, since the ancestor
19671 * axis beyond @elem will be searched as well.
19672 */
19673 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
19674 while (ns != NULL) {
19675 if (counter > 1000) {
19676 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
19677 XML_SCHEMAV_INTERNAL,
19678 "Internal error: xmlSchemaValidateAttributes, "
19679 "could not compute a ns prefix for "
19680 "default/fixed attribute '%s'.\n",
19681 attrDecl->name, NULL);
19682
19683 break;
19684 }
19685 snprintf((char *) prefix,
19686 sizeof(prefix), "p%d", counter++);
19687 ns = xmlSearchNs(elem->doc, elem,
19688 BAD_CAST prefix);
19689 }
19690 if (ns == NULL) {
19691 ns = xmlNewNs(ctxt->validationRoot,
19692 attrDecl->targetNamespace, BAD_CAST prefix);
19693 xmlNewNsProp(elem, ns, attrDecl->name,
19694 curState->value);
19695 }
19696 } else {
19697 xmlNewNsProp(elem, ns, attrDecl->name,
19698 curState->value);
19699 }
19700 }
19701 curState = curState->next;
19702 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019703 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019704 ret = ctxt->err;
19705 goto exit;
19706
19707fatal_exit:
19708 ret = -1;
19709
19710exit:
19711
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019712 if (defAttrStates != NULL)
19713 xmlSchemaFreeAttributeStates(defAttrStates);
19714
Daniel Veillard3646d642004-06-02 19:19:14 +000019715#ifdef DEBUG_ATTR_VALIDATION
19716 if (redundant)
19717 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019718 "xmlSchemaValidateAttributes: redundant call by "
19719 "type: %s\n", type->name);
Daniel Veillard3646d642004-06-02 19:19:14 +000019720#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019721 ctxt->nodeInfo = ctxt->elemInfos[ctxt->depth];
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019722 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019723 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019724}
19725
19726/**
19727 * xmlSchemaValidateElement:
19728 * @ctxt: a schema validation context
19729 * @elem: an element
19730 *
19731 * Validate an element in a tree
19732 *
19733 * Returns 0 if the element is schemas valid, a positive error code
19734 * number otherwise and -1 in case of internal or API error.
19735 */
19736static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019737xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019738{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019739 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019740 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000019741
Daniel Veillardc0826a72004-08-10 14:17:33 +000019742 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019743 * This one is called by xmlSchemaValidateDocument and
19744 * xmlSchemaValidateOneElement.
19745 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019746 if (ctxt->schema == NULL) {
19747 /*
19748 * No schema was specified at time of creation of the validation
19749 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
19750 * of the instance to build a schema.
19751 */
19752 if (ctxt->pctxt == NULL)
19753 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
19754 if (ctxt->pctxt == NULL)
19755 return (-1);
19756 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
19757 if (ctxt->schema == NULL)
19758 return (-1);
19759 /* TODO: assign user data. */
19760 ctxt->pctxt->error = ctxt->error;
19761 ctxt->pctxt->warning = ctxt->warning;
19762 ctxt->xsiAssemble = 1;
19763 } else
19764 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019765 /*
19766 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000019767 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019768 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019769 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
19770 if (ret == -1) {
19771 xmlSchemaVCustomErr(ctxt,
19772 XML_SCHEMAV_INTERNAL,
19773 ctxt->node, NULL,
19774 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019775 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019776 }
19777 /*
19778 * NOTE: We won't react on schema parser errors here.
19779 * TODO: But a warning would be nice.
19780 */
19781 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019782 if (ret != -1) {
19783 if (ctxt->node->ns != NULL)
19784 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
19785 ctxt->node->ns->href);
19786 else
19787 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
19788
19789 if (elemDecl == NULL) {
19790 xmlSchemaVCustomErr(ctxt,
19791 XML_SCHEMAV_CVC_ELT_1,
19792 ctxt->node, NULL,
19793 "No matching global declaration available", NULL);
19794 ret = XML_SCHEMAV_CVC_ELT_1;
19795 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019796#ifdef IDC_ENABLED
19797 /*
19798 * Augment the IDC definitions.
19799 */
19800 if (ctxt->schema->idcDef != NULL) {
19801 xmlHashScan(ctxt->schema->idcDef,
19802 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
19803 }
19804#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019805#ifdef ELEM_INFO_ENABLED
19806 ctxt->depth = -1;
19807 xmlSchemaBeginElement(ctxt);
19808#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019809 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019810#ifdef ELEM_INFO_ENABLED
19811 xmlSchemaEndElement(ctxt);
19812#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019813 if (ret < 0) {
19814 xmlSchemaVCustomErr(ctxt,
19815 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
19816 "Internal error: xmlSchemaValidateElement, "
19817 "calling validation by declaration", NULL);
19818 }
19819 }
19820 }
19821 /* ctxt->xsiAssemble = 0; */
19822 if (ctxt->xsiAssemble) {
19823 if (ctxt->schema != NULL) {
19824 xmlSchemaFree(ctxt->schema);
19825 ctxt->schema = NULL;
19826 }
Daniel Veillard4255d502002-04-16 15:50:10 +000019827 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019828 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019829}
19830
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019831
Daniel Veillard4255d502002-04-16 15:50:10 +000019832/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019833 * xmlSchemaValidateOneElement:
19834 * @ctxt: a schema validation context
19835 * @elem: an element node
19836 *
19837 * Validate a branch of a tree, starting with the given @elem.
19838 *
19839 * Returns 0 if the element and its subtree is valid, a positive error
19840 * code number otherwise and -1 in case of an internal or API error.
19841 */
19842int
19843xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
19844{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019845 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019846 return (-1);
19847
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019848 if (ctxt->schema == NULL) {
19849 xmlSchemaVErr(ctxt, NULL,
19850 XML_SCHEMAV_INTERNAL,
19851 "API error: xmlSchemaValidateOneElement, "
19852 "no schema specified.\n", NULL, NULL);
19853 return (-1);
19854 }
19855
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019856 ctxt->doc = elem->doc;
19857 ctxt->err = 0;
19858 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019859 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019860 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019861 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019862}
19863
19864/**
Daniel Veillard4255d502002-04-16 15:50:10 +000019865 * xmlSchemaValidateDocument:
19866 * @ctxt: a schema validation context
19867 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019868 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000019869 *
19870 * Validate a document tree in memory.
19871 *
19872 * Returns 0 if the document is schemas valid, a positive error code
19873 * number otherwise and -1 in case of internal or API error.
19874 */
19875static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019876xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
19877{
Daniel Veillard4255d502002-04-16 15:50:10 +000019878 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019879
Daniel Veillard4255d502002-04-16 15:50:10 +000019880 root = xmlDocGetRootElement(doc);
19881 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019882 xmlSchemaVCustomErr(ctxt,
19883 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
19884 (xmlNodePtr) doc, NULL,
19885 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019886 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019887 }
Daniel Veillard4255d502002-04-16 15:50:10 +000019888 /*
19889 * Okay, start the recursive validation
19890 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019891 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019892 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019893 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000019894
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019895 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019896}
19897
19898/************************************************************************
19899 * *
19900 * SAX Validation code *
19901 * *
19902 ************************************************************************/
19903
19904/************************************************************************
19905 * *
19906 * Validation interfaces *
19907 * *
19908 ************************************************************************/
19909
19910/**
19911 * xmlSchemaNewValidCtxt:
19912 * @schema: a precompiled XML Schemas
19913 *
19914 * Create an XML Schemas validation context based on the given schema
19915 *
19916 * Returns the validation context or NULL in case of error
19917 */
19918xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019919xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
19920{
Daniel Veillard4255d502002-04-16 15:50:10 +000019921 xmlSchemaValidCtxtPtr ret;
19922
19923 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
19924 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019925 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000019926 return (NULL);
19927 }
19928 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000019929 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000019930 ret->attrTop = NULL;
19931 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000019932 return (ret);
19933}
19934
19935/**
19936 * xmlSchemaFreeValidCtxt:
19937 * @ctxt: the schema validation context
19938 *
19939 * Free the resources associated to the schema validation context
19940 */
19941void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019942xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
19943{
Daniel Veillard4255d502002-04-16 15:50:10 +000019944 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019945 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000019946 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000019947 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000019948 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019949 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019950 if (ctxt->pctxt != NULL) {
19951 xmlSchemaFreeParserCtxt(ctxt->pctxt);
19952 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019953
19954#ifdef IDC_ENABLED
19955 if (ctxt->idcNodes != NULL) {
19956 int i;
19957 xmlSchemaPSVIIDCNodePtr item;
19958
19959 for (i = 0; i < ctxt->nbIdcNodes; i++) {
19960 item = ctxt->idcNodes[i];
19961 xmlFree(item->keys);
19962 xmlFree(item);
19963 }
19964 xmlFree(ctxt->idcNodes);
19965 }
19966
19967 if (ctxt->idcKeys != NULL) {
19968 int i;
19969 for (i = 0; i < ctxt->nbIdcKeys; i++)
19970 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
19971 xmlFree(ctxt->idcKeys);
19972 }
19973
19974 if (ctxt->xpathStates != NULL)
19975 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
19976 if (ctxt->xpathStatePool != NULL)
19977 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
19978
19979 /*
19980 * Augmented IDC information.
19981 */
19982 if (ctxt->aidcs != NULL) {
19983 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
19984 do {
19985 next = cur->next;
19986 xmlFree(cur);
19987 cur = next;
19988 } while (cur != NULL);
19989 }
19990#endif /* IDC_ENABLED */
19991#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019992 if (ctxt->attrInfo != NULL) {
19993 if (ctxt->attrInfo->value != NULL)
19994 xmlSchemaFreeValue(ctxt->attrInfo->value);
19995 xmlFree(ctxt->attrInfo);
19996 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019997 if (ctxt->elemInfos != NULL) {
19998 int i;
19999 xmlSchemaElemInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020000
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020001 for (i = 0; i < ctxt->sizeElemInfos; i++) {
20002 info = ctxt->elemInfos[i];
20003 if (info == NULL)
20004 continue;
20005 if (info->value != NULL)
20006 xmlSchemaFreeValue(info->value);
20007#ifdef IDC_ENABLED
20008 if (info->idcMatchers != NULL)
20009 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
20010#endif
20011 /*
20012 * TODO: Free the IDC table if still existent.
20013 */
20014
20015 /*
20016 xmlFree(info->localName);
20017 if (info->namespaceName != NULL)
20018 xmlFree(info->namespaceName);
20019 */
20020 xmlFree(info);
20021 }
20022 xmlFree(ctxt->elemInfos);
20023 }
20024#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000020025 xmlFree(ctxt);
20026}
20027
20028/**
20029 * xmlSchemaSetValidErrors:
20030 * @ctxt: a schema validation context
20031 * @err: the error function
20032 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000020033 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000020034 *
William M. Brack2f2a6632004-08-20 23:09:47 +000020035 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000020036 */
20037void
20038xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020039 xmlSchemaValidityErrorFunc err,
20040 xmlSchemaValidityWarningFunc warn, void *ctx)
20041{
Daniel Veillard4255d502002-04-16 15:50:10 +000020042 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020043 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000020044 ctxt->error = err;
20045 ctxt->warning = warn;
20046 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020047 if (ctxt->pctxt != NULL)
20048 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000020049}
20050
20051/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000020052 * xmlSchemaGetValidErrors:
20053 * @ctxt: a XML-Schema validation context
20054 * @err: the error function result
20055 * @warn: the warning function result
20056 * @ctx: the functions context result
20057 *
20058 * Get the error and warning callback informations
20059 *
20060 * Returns -1 in case of error and 0 otherwise
20061 */
20062int
20063xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
20064 xmlSchemaValidityErrorFunc * err,
20065 xmlSchemaValidityWarningFunc * warn, void **ctx)
20066{
20067 if (ctxt == NULL)
20068 return (-1);
20069 if (err != NULL)
20070 *err = ctxt->error;
20071 if (warn != NULL)
20072 *warn = ctxt->warning;
20073 if (ctx != NULL)
20074 *ctx = ctxt->userData;
20075 return (0);
20076}
20077
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020078
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020079/**
Daniel Veillard6927b102004-10-27 17:29:04 +000020080 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020081 * @ctxt: a schema validation context
20082 * @options: a combination of xmlSchemaValidOption
20083 *
20084 * Sets the options to be used during the validation.
20085 *
20086 * Returns 0 in case of success, -1 in case of an
20087 * API error.
20088 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020089int
20090xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
20091 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020092
20093{
20094 int i;
20095
20096 if (ctxt == NULL)
20097 return (-1);
20098 /*
20099 * WARNING: Change the start value if adding to the
20100 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020101 * TODO: Is there an other, more easy to maintain,
20102 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020103 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020104 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020105 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020106 xmlSchemaVErr(ctxt, NULL,
20107 XML_SCHEMAV_INTERNAL,
20108 "Internal error: xmlSchemaSetValidOptions, "
20109 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020110 return (-1);
20111 }
20112 }
20113 ctxt->options = options;
20114 return (0);
20115}
20116
20117/**
Daniel Veillard6927b102004-10-27 17:29:04 +000020118 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020119 * @ctxt: a schema validation context
20120 *
William M. Brack21e4ef22005-01-02 09:53:13 +000020121 * Get the validation context options.
20122 *
20123 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020124 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020125int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020126xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
20127
20128{
20129 if (ctxt == NULL)
20130 return (-1);
20131 else
20132 return (ctxt->options);
20133}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020134
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020135
Daniel Veillard259f0df2004-08-18 09:13:18 +000020136/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020137 * xmlSchemaValidateDoc:
20138 * @ctxt: a schema validation context
20139 * @doc: a parsed document tree
20140 *
20141 * Validate a document tree in memory.
20142 *
20143 * Returns 0 if the document is schemas valid, a positive error code
20144 * number otherwise and -1 in case of internal or API error.
20145 */
20146int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020147xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
20148{
Daniel Veillard4255d502002-04-16 15:50:10 +000020149 int ret;
20150
20151 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020152 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020153
20154 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000020155 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020156 ctxt->nberrors = 0;
20157
20158 /*
20159 if (ctxt->schema == NULL) {
20160 xmlSchemaVErr(ctxt, NULL,
20161 XML_SCHEMAV_INTERNAL,
20162 "API error: xmlSchemaValidateDoc, "
20163 "no schema specified and assembling of schemata "
20164 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
20165 "is not enabled.\n", NULL, NULL);
20166 return (-1);
20167 }
20168 */
Daniel Veillard4255d502002-04-16 15:50:10 +000020169 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020170 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020171}
20172
20173/**
20174 * xmlSchemaValidateStream:
20175 * @ctxt: a schema validation context
20176 * @input: the input to use for reading the data
20177 * @enc: an optional encoding information
20178 * @sax: a SAX handler for the resulting events
20179 * @user_data: the context to provide to the SAX handler.
20180 *
20181 * Validate a document tree in memory.
20182 *
20183 * Returns 0 if the document is schemas valid, a positive error code
20184 * number otherwise and -1 in case of internal or API error.
20185 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020186int
Daniel Veillard4255d502002-04-16 15:50:10 +000020187xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020188 xmlParserInputBufferPtr input, xmlCharEncoding enc,
20189 xmlSAXHandlerPtr sax, void *user_data)
20190{
Daniel Veillard4255d502002-04-16 15:50:10 +000020191 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020192 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020193 ctxt->input = input;
20194 ctxt->enc = enc;
20195 ctxt->sax = sax;
20196 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020197 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020198}
20199
20200#endif /* LIBXML_SCHEMAS_ENABLED */