blob: 8b92c63350155b69213fa47bcd3d394cffeec19f [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. Buchcik285ebab2005-03-04 18:04:59 +000057#define IDC_ENABLED 1
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000058
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000059#define IDC_VALUE_SUPPORT 1
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000060
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000061#define IDC_XPATH_SUPPORT 1
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000062
63/* #define DEBUG_IDC 1 */
64
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000065/* #define DEBUG_INCLUDES 1 */
66
Daniel Veillardc0826a72004-08-10 14:17:33 +000067
Daniel Veillard4255d502002-04-16 15:50:10 +000068#define UNBOUNDED (1 << 30)
69#define TODO \
70 xmlGenericError(xmlGenericErrorContext, \
71 "Unimplemented block at %s:%d\n", \
72 __FILE__, __LINE__);
73
William M. Brack2f2a6632004-08-20 23:09:47 +000074#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000075
Daniel Veillard4255d502002-04-16 15:50:10 +000076/*
77 * The XML Schemas namespaces
78 */
79static const xmlChar *xmlSchemaNs = (const xmlChar *)
80 "http://www.w3.org/2001/XMLSchema";
81
82static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
83 "http://www.w3.org/2001/XMLSchema-instance";
84
Daniel Veillardc0826a72004-08-10 14:17:33 +000085static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
86 "Element decl.";
87static const xmlChar *xmlSchemaElemDesElemRef = (const xmlChar *)
88 "Element ref.";
89static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
90 "Attribute decl.";
91static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
92 "Attribute ref.";
93static const xmlChar *xmlSchemaElemDesST = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000094 "simple type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000095static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000096 "complex type";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000097static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
98 "Model group";
99static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
100 "Model group ref.";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000101
Daniel Veillard4255d502002-04-16 15:50:10 +0000102#define IS_SCHEMA(node, type) \
103 ((node != NULL) && (node->ns != NULL) && \
104 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
105 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
106
Daniel Veillardc0826a72004-08-10 14:17:33 +0000107#define FREE_AND_NULL(str) \
108 if (str != NULL) { \
109 xmlFree(str); \
110 str = NULL; \
111 }
112
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000113#define IS_ANYTYPE(item) \
114 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
115 (item->builtInType == XML_SCHEMAS_ANYTYPE))
116
117#define IS_COMPLEX_TYPE(item) \
118 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
119 (item->builtInType == XML_SCHEMAS_ANYTYPE))
120
121#define IS_SIMPLE_TYPE(item) \
122 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
123 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
124 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
125
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +0000126/*
Daniel Veillardc0826a72004-08-10 14:17:33 +0000127#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
128#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
129#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +0000130*/
Daniel Veillardc0826a72004-08-10 14:17:33 +0000131
Daniel Veillard4255d502002-04-16 15:50:10 +0000132#define XML_SCHEMAS_PARSE_ERROR 1
133
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000134#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
135
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000136
137/*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000138* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
139* locate schemata to be imported
140* using the namespace name; otherwise
141* the location URI will be used */
142
143/*
144* xmlSchemaParserOption:
145*
146* This is the set of XML Schema parser options.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000147*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000148typedef enum {
149 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000150 * locate schemata to be imported
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000151 * using the namespace name; otherwise
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000152 * the location URI will be used *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000153} xmlSchemaParserOption;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000154*/
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000155
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000156typedef struct _xmlSchemaAssemble xmlSchemaAssemble;
157typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
158struct _xmlSchemaAssemble {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000159 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000160 int nbItems; /* used for dynamic addition of schemata */
161 int sizeItems; /* used for dynamic addition of schemata */
162};
163
Daniel Veillard4255d502002-04-16 15:50:10 +0000164struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000165 void *userData; /* user specific data block */
166 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
167 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000168 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000169 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000170 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000171
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000172 xmlSchemaPtr topschema; /* The main schema */
173 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
174
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000175 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000176 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000177 int counter;
178
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000179 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000180 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000181 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000182
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000183 const char *buffer;
184 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000185
Daniel Veillard4255d502002-04-16 15:50:10 +0000186 /*
187 * Used to build complex element content models
188 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000189 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000190 xmlAutomataStatePtr start;
191 xmlAutomataStatePtr end;
192 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000193
194 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000195 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000196 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
197 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000198 xmlSchemaAssemblePtr assemble;
199 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000200 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000201 const xmlChar **localImports; /* list of locally imported namespaces */
202 int sizeLocalImports;
203 int nbLocalImports;
Daniel Veillard4255d502002-04-16 15:50:10 +0000204};
205
206
207#define XML_SCHEMAS_ATTR_UNKNOWN 1
208#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000209#define XML_SCHEMAS_ATTR_PROHIBITED 3
210#define XML_SCHEMAS_ATTR_MISSING 4
211#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
212#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000213#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
214#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000215#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
216#define XML_SCHEMAS_ATTR_WILD_NO_DECL 10
Daniel Veillard4255d502002-04-16 15:50:10 +0000217
218typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
219typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
220struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000221 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000222 xmlAttrPtr attr;
223 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000224 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000225 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000226};
227
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000228typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
229typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
230struct _xmlSchemaBasicItem {
231 xmlSchemaTypeType type;
232 xmlSchemaAnnotPtr annot;
233};
234
235typedef struct _xmlSchemaItemQNRef xmlSchemaItemQNRef;
236typedef xmlSchemaItemQNRef *xmlSchemaItemQNRefPtr;
237struct _xmlSchemaItemQNRef {
238 xmlSchemaBasicItemPtr item;
239 const xmlChar *name;
240 const xmlChar *targetNamespace;
241};
242
243typedef struct _xmlSchemaIDC xmlSchemaIDC;
244typedef xmlSchemaIDC *xmlSchemaIDCPtr;
245
246/**
247 * xmlSchemaIDCSelect:
248 *
249 * The identity-constraint "field" and "selector" item, holding the
250 * XPath expression.
251 */
252typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
253typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
254struct _xmlSchemaIDCSelect {
255 xmlSchemaIDCSelectPtr next;
256 xmlSchemaIDCPtr idc;
257 int index; /* an index position if significant for IDC key-sequences */
258 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000259 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000260};
261
262/**
263 * xmlSchemaIDC:
264 *
265 * The identity-constraint definition component.
266 */
267
268struct _xmlSchemaIDC {
269 xmlSchemaTypeType type;
270 xmlSchemaAnnotPtr annot;
271 xmlSchemaIDCPtr next;
272 xmlNodePtr node;
273 const xmlChar *name;
274 const xmlChar *targetNamespace;
275 xmlSchemaIDCSelectPtr selector;
276 xmlSchemaIDCSelectPtr fields;
277 int nbFields;
278 xmlSchemaItemQNRefPtr ref;
279};
280
281/**
282 * xmlSchemaIDCAug:
283 *
284 * The augmented IDC information used for validation.
285 */
286typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
287typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
288struct _xmlSchemaIDCAug {
289 xmlSchemaIDCAugPtr next; /* next in a list */
290 xmlSchemaIDCPtr def; /* the IDC definition */
291 int bubbleDepth; /* the lowest level to which IDC
292 tables need to be bubbled upwards */
293};
294
295/**
296 * xmlSchemaPSVIIDCKeySequence:
297 *
298 * The key sequence of a node table item.
299 */
300typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
301typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
302struct _xmlSchemaPSVIIDCKey {
303 xmlSchemaTypePtr type;
304 xmlSchemaValPtr compValue;
305};
306
307/**
308 * xmlSchemaPSVIIDCNode:
309 *
310 * The node table item of a node table.
311 */
312typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
313typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
314struct _xmlSchemaPSVIIDCNode {
315 xmlNodePtr node;
316 xmlSchemaPSVIIDCKeyPtr *keys;
317};
318
319/**
320 * xmlSchemaPSVIIDCBinding:
321 *
322 * The identity-constraint binding item of the [identity-constraint table].
323 */
324typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
325typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
326struct _xmlSchemaPSVIIDCBinding {
327 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
328 xmlSchemaIDCPtr definition; /* the IDC definition */
329 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
330 int nbNodes; /* number of entries in the node table */
331 int sizeNodes; /* size of the node table */
332 int nbDupls; /* number of already identified duplicates in the node
333 table */
334 /* int nbKeys; number of keys in each key-sequence */
335};
336
337#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
338#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
339
340#define XPATH_STATE_OBJ_MATCHES -2
341#define XPATH_STATE_OBJ_BLOCKED -3
342
343typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
344typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
345
346/**
347 * xmlSchemaIDCStateObj:
348 *
349 * The state object used to evaluate XPath expressions.
350 */
351typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
352typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
353struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000354 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000355 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000356 int depth; /* depth of creation */
357 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000358 int nbHistory;
359 int sizeHistory;
360 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
361 matcher */
362 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000363 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000364};
365
366#define IDC_MATCHER 0
367
368/**
369 * xmlSchemaIDCMatcher:
370 *
371 * Used to IDC selectors (and fields) successively.
372 */
373struct _xmlSchemaIDCMatcher {
374 int type;
375 int depth; /* the tree depth at creation time */
376 xmlSchemaIDCMatcherPtr next; /* next in the list */
377 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
378 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
379 elements */
380 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000381 int targetDepth;
382};
383
384/*
385* Element info flags.
386*/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000387#define XML_SCHEMA_ELEM_INFO_VALUE_NEEDED 1
388/* #define XML_SCHEMA_ELEM_INFO_ATTR 2 */
389/* #define XML_SCHEMA_ELEM_INFO_ELEM 4 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000390
391/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000392 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000393 *
394 * Holds information of an element node.
395 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000396typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
397typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
398struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000399 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000400 int flags; /* combination of node info flags */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000401 xmlNodePtr node;
402 const xmlChar *localName;
403 const xmlChar *namespaceName;
404 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +0000405 xmlSchemaTypePtr decl; /* the element/attribute declaration */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000406 xmlSchemaValPtr value; /* the pre-computed value if any */
407 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
408 for the scope element*/
409 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
410 element */
411};
412
Daniel Veillard4255d502002-04-16 15:50:10 +0000413/**
414 * xmlSchemaValidCtxt:
415 *
416 * A Schemas validation context
417 */
418
419struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000420 void *userData; /* user specific data block */
421 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000422 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000423 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000424
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000425 xmlSchemaPtr schema; /* The schema in use */
426 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000427 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000428 xmlCharEncoding enc;
429 xmlSAXHandlerPtr sax;
430 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000431
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000432 xmlDocPtr myDoc;
433 int err;
434 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000435
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000436 xmlNodePtr node;
437 xmlNodePtr cur;
438 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000439
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000440 xmlRegExecCtxtPtr regexp;
441 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000442
Daniel Veillard3646d642004-06-02 19:19:14 +0000443 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000444 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000445 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000446 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000447 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000448 xmlNodePtr validationRoot;
449 xmlSchemaParserCtxtPtr pctxt;
450 int xsiAssemble;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000451#ifdef ELEM_INFO_ENABLED
452 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000453 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000454 int sizeElemInfos;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000455 xmlSchemaNodeInfoPtr nodeInfo; /* the current element information */
456 xmlSchemaNodeInfoPtr attrInfo; /* node infor for the current attribute */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000457#endif
458#ifdef IDC_ENABLED
459 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
460
461 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
462 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
463
464 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
465 int nbIdcNodes;
466 int sizeIdcNodes;
467
468 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
469 int nbIdcKeys;
470 int sizeIdcKeys;
471#endif
Daniel Veillard4255d502002-04-16 15:50:10 +0000472};
473
Daniel Veillard1d913862003-11-21 00:28:39 +0000474/*
475 * These are the entries in the schemas importSchemas hash table
476 */
477typedef struct _xmlSchemaImport xmlSchemaImport;
478typedef xmlSchemaImport *xmlSchemaImportPtr;
479struct _xmlSchemaImport {
480 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000481 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000482 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000483 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000484};
Daniel Veillard4255d502002-04-16 15:50:10 +0000485
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000486/*
487 * These are the entries associated to includes in a schemas
488 */
489typedef struct _xmlSchemaInclude xmlSchemaInclude;
490typedef xmlSchemaInclude *xmlSchemaIncludePtr;
491struct _xmlSchemaInclude {
492 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000493 const xmlChar *schemaLocation;
494 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000495 const xmlChar *origTargetNamespace;
496 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000497};
498
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000499typedef struct _xmlSchemaParticle xmlSchemaParticle;
500typedef xmlSchemaParticle *xmlSchemaParticlePtr;
501struct _xmlSchemaParticle {
502 xmlSchemaTypeType type;
503 xmlSchemaParticlePtr next; /* the next particle if in a list */
504 int minOccurs;
505 int maxOccurs;
506 xmlSchemaTypePtr term;
507};
508
509
510typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
511typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
512struct _xmlSchemaModelGroup {
513 xmlSchemaTypeType type;
514 int compositor; /* one of all, choice or sequence */
515 xmlSchemaParticlePtr particles; /* list of particles */
516 xmlSchemaAnnotPtr annot;
517};
518
519typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
520typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
521struct _xmlSchemaModelGroupDef {
522 xmlSchemaTypeType type;
523 const xmlChar *name;
524 const xmlChar *targetNamespace;
525 xmlSchemaModelGroupPtr modelGroup;
526 xmlSchemaAnnotPtr annot;
527};
528
Daniel Veillard4255d502002-04-16 15:50:10 +0000529/************************************************************************
530 * *
531 * Some predeclarations *
532 * *
533 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000534
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000535static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
536 xmlSchemaPtr schema,
537 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000538static void
539xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
540 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000541static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000542xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
543static int
544xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000545 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000546 const xmlChar *value,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000547 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000548 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000549 int normalize,
550 int checkNodes);
551static int
552xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
553 xmlSchemaElementPtr elemDecl);
554static int
555xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
556 xmlSchemaTypePtr type);
557static int
558xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000559static int
560xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
561 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000562static void
563xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
564 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000565static void
566xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000567static int
568xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
569 xmlSchemaTypePtr type,
570 const xmlChar *value,
571 xmlSchemaValPtr *val);
572static xmlSchemaTypePtr
573xmlSchemaGetSimpleContentType(xmlSchemaTypePtr complexType);
574static int
575xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
William M. Brack87640d52004-04-17 14:58:15 +0000576
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000577/************************************************************************
578 * *
579 * Datatype error handlers *
580 * *
581 ************************************************************************/
582
583/**
584 * xmlSchemaPErrMemory:
585 * @node: a context node
586 * @extra: extra informations
587 *
588 * Handle an out of memory condition
589 */
590static void
591xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
592 const char *extra, xmlNodePtr node)
593{
594 if (ctxt != NULL)
595 ctxt->nberrors++;
596 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
597 extra);
598}
599
600/**
601 * xmlSchemaPErr:
602 * @ctxt: the parsing context
603 * @node: the context node
604 * @error: the error code
605 * @msg: the error message
606 * @str1: extra data
607 * @str2: extra data
608 *
609 * Handle a parser error
610 */
611static void
612xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
613 const char *msg, const xmlChar * str1, const xmlChar * str2)
614{
615 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000616 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000617 void *data = NULL;
618
619 if (ctxt != NULL) {
620 ctxt->nberrors++;
621 channel = ctxt->error;
622 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000623 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000624 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000625 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000626 error, XML_ERR_ERROR, NULL, 0,
627 (const char *) str1, (const char *) str2, NULL, 0, 0,
628 msg, str1, str2);
629}
630
631/**
632 * xmlSchemaPErr2:
633 * @ctxt: the parsing context
634 * @node: the context node
635 * @node: the current child
636 * @error: the error code
637 * @msg: the error message
638 * @str1: extra data
639 * @str2: extra data
640 *
641 * Handle a parser error
642 */
643static void
644xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
645 xmlNodePtr child, int error,
646 const char *msg, const xmlChar * str1, const xmlChar * str2)
647{
648 if (child != NULL)
649 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
650 else
651 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
652}
653
Daniel Veillard01fa6152004-06-29 17:04:39 +0000654
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000655/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000656 * xmlSchemaPErrExt:
657 * @ctxt: the parsing context
658 * @node: the context node
659 * @error: the error code
660 * @strData1: extra data
661 * @strData2: extra data
662 * @strData3: extra data
663 * @msg: the message
664 * @str1: extra parameter for the message display
665 * @str2: extra parameter for the message display
666 * @str3: extra parameter for the message display
667 * @str4: extra parameter for the message display
668 * @str5: extra parameter for the message display
669 *
670 * Handle a parser error
671 */
672static void
673xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
674 const xmlChar * strData1, const xmlChar * strData2,
675 const xmlChar * strData3, const char *msg, const xmlChar * str1,
676 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
677 const xmlChar * str5)
678{
679
680 xmlGenericErrorFunc channel = NULL;
681 xmlStructuredErrorFunc schannel = NULL;
682 void *data = NULL;
683
684 if (ctxt != NULL) {
685 ctxt->nberrors++;
686 channel = ctxt->error;
687 data = ctxt->userData;
688 schannel = ctxt->serror;
689 }
690 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
691 error, XML_ERR_ERROR, NULL, 0,
692 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000693 (const char *) strData3, 0, 0, msg, str1, str2,
694 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000695}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000696
Daniel Veillard3646d642004-06-02 19:19:14 +0000697
698/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000699 * xmlSchemaVTypeErrMemory:
700 * @node: a context node
701 * @extra: extra informations
702 *
703 * Handle an out of memory condition
704 */
705static void
706xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
707 const char *extra, xmlNodePtr node)
708{
709 if (ctxt != NULL) {
710 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000711 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000712 }
713 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
714 extra);
715}
716
717/**
718 * xmlSchemaVErr3:
719 * @ctxt: the validation context
720 * @node: the context node
721 * @error: the error code
722 * @msg: the error message
723 * @str1: extra data
724 * @str2: extra data
725 * @str3: extra data
726 *
727 * Handle a validation error
728 */
729static void
730xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
731 const char *msg, const xmlChar *str1, const xmlChar *str2,
732 const xmlChar *str3)
733{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000734 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000735 xmlGenericErrorFunc channel = NULL;
736 void *data = NULL;
737
738 if (ctxt != NULL) {
739 ctxt->nberrors++;
740 ctxt->err = error;
741 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000742 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000743 data = ctxt->userData;
744 }
745 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000746 /* Removed, since the old schema error codes have been
747 * substituted for the global error codes.
748 *
749 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
750 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000751 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000752 error, XML_ERR_ERROR, NULL, 0,
753 (const char *) str1, (const char *) str2,
754 (const char *) str3, 0, 0,
755 msg, str1, str2, str3);
756}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000757
758/**
759 * xmlSchemaVErrExt:
760 * @ctxt: the validation context
761 * @node: the context node
762 * @error: the error code
763 * @msg: the message
764 * @str1: extra parameter for the message display
765 * @str2: extra parameter for the message display
766 * @str3: extra parameter for the message display
767 * @str4: extra parameter for the message display
768 * @str5: extra parameter for the message display
769 *
770 * Handle a validation error
771 */
772static void
773xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
774 const char *msg, const xmlChar * str1,
775 const xmlChar * str2, const xmlChar * str3,
776 const xmlChar * str4, const xmlChar * str5)
777{
778 xmlStructuredErrorFunc schannel = NULL;
779 xmlGenericErrorFunc channel = NULL;
780 void *data = NULL;
781
782 if (ctxt != NULL) {
783 ctxt->nberrors++;
784 ctxt->err = error;
785 channel = ctxt->error;
786 schannel = ctxt->serror;
787 data = ctxt->userData;
788 }
789 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000790 /* Removed, since the old schema error codes have been
791 * substituted for the global error codes.
792 *
793 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
794 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000795 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
796 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
797 msg, str1, str2, str3, str4, str5);
798}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000799/**
800 * xmlSchemaVErr:
801 * @ctxt: the validation context
802 * @node: the context node
803 * @error: the error code
804 * @msg: the error message
805 * @str1: extra data
806 * @str2: extra data
807 *
808 * Handle a validation error
809 */
810static void
811xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
812 const char *msg, const xmlChar * str1, const xmlChar * str2)
813{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000814 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000815 xmlGenericErrorFunc channel = NULL;
816 void *data = NULL;
817
818 if (ctxt != NULL) {
819 ctxt->nberrors++;
820 ctxt->err = error;
821 channel = ctxt->error;
822 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000823 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000824 }
825 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000826 /* Removed, since the old schema error codes have been
827 * substituted for the global error codes.
828 *
829 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
830 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000831 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000832 error, XML_ERR_ERROR, NULL, 0,
833 (const char *) str1, (const char *) str2, NULL, 0, 0,
834 msg, str1, str2);
835}
Daniel Veillard4255d502002-04-16 15:50:10 +0000836
Daniel Veillardc0826a72004-08-10 14:17:33 +0000837/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000838 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000839 * @attr: the attribute declaration/use
840 *
841 * Returns the name of the attribute; if the attribute
842 * is a reference, the name of the referenced global type will be returned.
843 */
844static const xmlChar *
845xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
846{
847 if (attr->ref != NULL)
848 return(attr->ref);
849 else
850 return(attr->name);
851}
852
853/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000854 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000855 * @type: the type (element or attribute)
856 *
857 * Returns the target namespace URI of the type; if the type is a reference,
858 * the target namespace of the referenced type will be returned.
859 */
860static const xmlChar *
861xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
862{
863 if (attr->ref != NULL)
864 return (attr->refNs);
865 else
866 return(attr->targetNamespace);
867}
868
869/**
870 * xmlSchemaFormatNsUriLocal:
871 * @buf: the string buffer
872 * @uri: the namespace URI
873 * @local: the local name
874 *
875 * Returns a representation of the given URI used
876 * for error reports.
877 *
878 * Returns an empty string, if @ns is NULL, a formatted
879 * string otherwise.
880 */
881static const xmlChar*
882xmlSchemaFormatNsUriLocal(xmlChar **buf,
883 const xmlChar *uri, const xmlChar *local)
884{
885 if (*buf != NULL)
886 xmlFree(*buf);
887 if (uri == NULL) {
888 *buf = xmlStrdup(BAD_CAST "{'");
889 *buf = xmlStrcat(*buf, local);
890 } else {
891 *buf = xmlStrdup(BAD_CAST "{'");
892 *buf = xmlStrcat(*buf, uri);
893 *buf = xmlStrcat(*buf, BAD_CAST "', '");
894 *buf = xmlStrcat(*buf, local);
895 }
896 *buf = xmlStrcat(*buf, BAD_CAST "'}");
897 return ((const xmlChar *) *buf);
898}
899
900/**
901 * xmlSchemaFormatNsPrefixLocal:
902 * @buf: the string buffer
903 * @ns: the namespace
904 * @local: the local name
905 *
906 * Returns a representation of the given URI used
907 * for error reports.
908 *
909 * Returns an empty string, if @ns is NULL, a formatted
910 * string otherwise.
911 */
912static const xmlChar*
913xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
914 xmlNsPtr ns, const xmlChar *local)
915{
916 if (*buf != NULL) {
917 xmlFree(*buf);
918 *buf = NULL;
919 }
920 if ((ns == NULL) || (ns->prefix == NULL))
921 return(local);
922 else {
923 *buf = xmlStrdup(ns->prefix);
924 *buf = xmlStrcat(*buf, BAD_CAST ":");
925 *buf = xmlStrcat(*buf, local);
926 }
927 return ((const xmlChar *) *buf);
928}
929
930/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000931 * xmlSchemaFormatQName:
932 * @buf: the string buffer
933 * @namespaceName: the namespace name
934 * @localName: the local name
935 *
936 * Returns the given QName in the format "{namespaceName}localName" or
937 * just "localName" if @namespaceName is NULL.
938 *
939 * Returns the localName if @namespaceName is NULL, a formatted
940 * string otherwise.
941 */
942static const xmlChar*
943xmlSchemaFormatQName(xmlChar **buf,
944 const xmlChar *namespaceName,
945 const xmlChar *localName)
946{
947 FREE_AND_NULL(*buf)
948 if (namespaceName == NULL)
949 return(localName);
950
951 *buf = xmlStrdup(BAD_CAST "{");
952 *buf = xmlStrcat(*buf, namespaceName);
953 *buf = xmlStrcat(*buf, BAD_CAST "}");
954 *buf = xmlStrcat(*buf, localName);
955
956 return ((const xmlChar *) *buf);
957}
958
959/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000960 * xmlSchemaWildcardPCToString:
961 * @pc: the type of processContents
962 *
963 * Returns a string representation of the type of
964 * processContents.
965 */
966static const xmlChar *
967xmlSchemaWildcardPCToString(int pc)
968{
969 switch (pc) {
970 case XML_SCHEMAS_ANY_SKIP:
971 return (BAD_CAST "skip");
972 case XML_SCHEMAS_ANY_LAX:
973 return (BAD_CAST "lax");
974 case XML_SCHEMAS_ANY_STRICT:
975 return (BAD_CAST "strict");
976 default:
977 return (BAD_CAST "invalid process contents");
978 }
979}
980
981/**
Daniel Veillardc0826a72004-08-10 14:17:33 +0000982 * xmlSchemaFormatItemForReport:
983 * @buf: the string buffer
984 * @itemDes: the designation of the item
985 * @itemName: the name of the item
986 * @item: the item as an object
987 * @itemNode: the node of the item
988 * @local: the local name
989 * @parsing: if the function is used during the parse
990 *
991 * Returns a representation of the given item used
992 * for error reports.
993 *
994 * The following order is used to build the resulting
995 * designation if the arguments are not NULL:
996 * 1a. If itemDes not NULL -> itemDes
997 * 1b. If (itemDes not NULL) and (itemName not NULL)
998 * -> itemDes + itemName
999 * 2. If the preceding was NULL and (item not NULL) -> item
1000 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1001 *
1002 * If the itemNode is an attribute node, the name of the attribute
1003 * will be appended to the result.
1004 *
1005 * Returns the formatted string and sets @buf to the resulting value.
1006 */
1007static xmlChar*
1008xmlSchemaFormatItemForReport(xmlChar **buf,
1009 const xmlChar *itemDes,
1010 xmlSchemaTypePtr item,
1011 xmlNodePtr itemNode,
1012 int parsing)
1013{
1014 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00001015 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001016
1017 if (*buf != NULL) {
1018 xmlFree(*buf);
1019 *buf = NULL;
1020 }
1021
William M. Brack2f2a6632004-08-20 23:09:47 +00001022 if (itemDes != NULL) {
1023 *buf = xmlStrdup(itemDes);
1024 } else if (item != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001025 switch (item->type) {
1026 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001027 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
1028 *buf = xmlStrdup(BAD_CAST "'anyType'");
1029 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
1030 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
1031 else {
1032 /* *buf = xmlStrdup(BAD_CAST "bi "); */
1033 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
1034 *buf = xmlStrdup(BAD_CAST "'");
1035 *buf = xmlStrcat(*buf, item->name);
1036 *buf = xmlStrcat(*buf, BAD_CAST "'");
1037 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001038 break;
1039 case XML_SCHEMA_TYPE_SIMPLE:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001040 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1041 *buf = xmlStrdup(xmlSchemaElemDesST);
1042 *buf = xmlStrcat(*buf, BAD_CAST " '");
1043 *buf = xmlStrcat(*buf, item->name);
1044 *buf = xmlStrcat(*buf, BAD_CAST "'");
1045 } else {
1046 *buf = xmlStrdup(xmlSchemaElemDesST);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001047 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001048 break;
1049 case XML_SCHEMA_TYPE_COMPLEX:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001050 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1051 *buf = xmlStrdup(xmlSchemaElemDesCT);
1052 *buf = xmlStrcat(*buf, BAD_CAST " '");
1053 *buf = xmlStrcat(*buf, item->name);
1054 *buf = xmlStrcat(*buf, BAD_CAST "'");
1055 } else {
1056 *buf = xmlStrdup(xmlSchemaElemDesCT);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001057 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001058 break;
1059 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1060 xmlSchemaAttributePtr attr;
1061
1062 attr = (xmlSchemaAttributePtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001063 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001064 (attr->ref == NULL)) {
1065 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1066 *buf = xmlStrcat(*buf, BAD_CAST " '");
1067 *buf = xmlStrcat(*buf, attr->name);
1068 *buf = xmlStrcat(*buf, BAD_CAST "'");
1069 } else {
1070 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1071 *buf = xmlStrcat(*buf, BAD_CAST " '");
1072 *buf = xmlStrcat(*buf, attr->refPrefix);
1073 *buf = xmlStrcat(*buf, BAD_CAST ":");
1074 *buf = xmlStrcat(*buf, attr->ref);
1075 *buf = xmlStrcat(*buf, BAD_CAST "'");
1076 }
1077 }
1078 break;
1079 case XML_SCHEMA_TYPE_ELEMENT: {
1080 xmlSchemaElementPtr elem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001081
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001082 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001083 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001084 (elem->ref == NULL)) {
1085 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1086 *buf = xmlStrcat(*buf, BAD_CAST " '");
1087 *buf = xmlStrcat(*buf, elem->name);
1088 *buf = xmlStrcat(*buf, BAD_CAST "'");
1089 } else {
1090 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
1091 *buf = xmlStrcat(*buf, BAD_CAST " '");
1092 *buf = xmlStrcat(*buf, elem->refPrefix);
1093 *buf = xmlStrcat(*buf, BAD_CAST ":");
1094 *buf = xmlStrcat(*buf, elem->ref);
1095 *buf = xmlStrcat(*buf, BAD_CAST "'");
1096 }
1097 }
1098 break;
1099 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1100 case XML_SCHEMA_TYPE_IDC_KEY:
1101 case XML_SCHEMA_TYPE_IDC_KEYREF:
1102 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1103 *buf = xmlStrdup(BAD_CAST "unique '");
1104 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1105 *buf = xmlStrdup(BAD_CAST "key '");
1106 else
1107 *buf = xmlStrdup(BAD_CAST "keyRef '");
1108 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1109 *buf = xmlStrcat(*buf, BAD_CAST "'");
1110 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001111 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001112 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1113 ((xmlSchemaWildcardPtr) item)->processContents));
1114 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1115 break;
1116 case XML_SCHEMA_FACET_MININCLUSIVE:
1117 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1118 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1119 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1120 case XML_SCHEMA_FACET_TOTALDIGITS:
1121 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1122 case XML_SCHEMA_FACET_PATTERN:
1123 case XML_SCHEMA_FACET_ENUMERATION:
1124 case XML_SCHEMA_FACET_WHITESPACE:
1125 case XML_SCHEMA_FACET_LENGTH:
1126 case XML_SCHEMA_FACET_MAXLENGTH:
1127 case XML_SCHEMA_FACET_MINLENGTH:
1128 *buf = xmlStrdup(BAD_CAST "facet '");
1129 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1130 *buf = xmlStrcat(*buf, BAD_CAST "'");
1131 break;
1132 case XML_SCHEMA_TYPE_NOTATION:
1133 *buf = xmlStrdup(BAD_CAST "notation");
1134 break;
1135 case XML_SCHEMA_TYPE_GROUP:
1136 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1137 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1138 *buf = xmlStrcat(*buf, BAD_CAST " '");
1139 *buf = xmlStrcat(*buf, item->name);
1140 *buf = xmlStrcat(*buf, BAD_CAST "'");
1141 } else {
1142 *buf = xmlStrdup(xmlSchemaElemModelGrRef);
1143 *buf = xmlStrcat(*buf, BAD_CAST " '");
1144 *buf = xmlStrcat(*buf, item->ref);
1145 *buf = xmlStrcat(*buf, BAD_CAST "'");
1146 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001147 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001148 default:
William M. Brack2f2a6632004-08-20 23:09:47 +00001149 named = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001150 }
William M. Brack2f2a6632004-08-20 23:09:47 +00001151 } else
1152 named = 0;
1153
1154 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00001155 xmlNodePtr elem;
1156
1157 if (itemNode->type == XML_ATTRIBUTE_NODE)
1158 elem = itemNode->parent;
1159 else
1160 elem = itemNode;
1161 *buf = xmlStrdup(BAD_CAST "Element '");
1162 if (parsing)
1163 *buf = xmlStrcat(*buf, elem->name);
1164 else
1165 *buf = xmlStrcat(*buf,
1166 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
1167 *buf = xmlStrcat(*buf, BAD_CAST "'");
1168 }
1169 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1170 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1171 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
1172 itemNode->ns, itemNode->name));
1173 *buf = xmlStrcat(*buf, BAD_CAST "'");
1174 }
1175 FREE_AND_NULL(str);
1176
1177 return (*buf);
1178}
1179
1180/**
1181 * xmlSchemaPFormatItemDes:
1182 * @buf: the string buffer
1183 * @item: the item as a schema object
1184 * @itemNode: the item as a node
1185 *
1186 * If the pointer to @buf is not NULL and @but holds no value,
1187 * the value is set to a item designation using
1188 * xmlSchemaFormatItemForReport. This one avoids adding
1189 * an attribute designation postfix.
1190 *
1191 * Returns a string of all enumeration elements.
1192 */
1193static void
1194xmlSchemaPRequestItemDes(xmlChar **buf,
1195 xmlSchemaTypePtr item,
1196 xmlNodePtr itemNode)
1197{
1198 if ((buf == 0) || (*buf != NULL))
1199 return;
1200 if (itemNode->type == XML_ATTRIBUTE_NODE)
1201 itemNode = itemNode->parent;
1202 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
1203}
1204
1205/**
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001206 * xmlSchemaGetCanonValueWhtsp:
1207 * @val: the precomputed value
1208 * @retValue: the returned value
1209 * @ws: the whitespace type of the value
1210 *
1211 * Get a the cononical representation of the value.
1212 * The caller has to free the returned retValue.
1213 *
1214 * Returns 0 if the value could be built and -1 in case of
1215 * API errors or if the value type is not supported yet.
1216 */
1217static int
1218xmlSchemaGetCanonValueWhtsp(const xmlChar *value,
1219 xmlSchemaValPtr val,
1220 xmlSchemaWhitespaceValueType ws,
1221 const xmlChar **retValue)
1222{
1223 xmlSchemaValType valType;
1224
1225 if ((retValue == NULL) || (value == NULL) || (val == NULL))
1226 return (-1);
1227 *retValue = NULL;
1228 valType = xmlSchemaGetValType(val);
1229 switch (valType) {
1230 case XML_SCHEMAS_STRING:
1231 if (value == NULL)
1232 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
1233 else
1234 *retValue =
1235 BAD_CAST xmlStrdup(value);
1236 break;
1237 case XML_SCHEMAS_NORMSTRING:
1238 if (value == NULL)
1239 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
1240 else {
1241 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1242 *retValue = xmlSchemaCollapseString(value);
1243 else
1244 *retValue = xmlSchemaWhiteSpaceReplace(value);
1245 if ((*retValue) == NULL)
1246 *retValue = BAD_CAST xmlStrdup(value);
1247 }
1248 break;
1249 default:
1250 return (xmlSchemaGetCanonValue(val, retValue));
1251 }
1252 return (0);
1253}
1254
1255/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001256 * xmlSchemaFormatFacetEnumSet:
1257 * @buf: the string buffer
1258 * @type: the type holding the enumeration facets
1259 *
1260 * Builds a string consisting of all enumeration elements.
1261 *
1262 * Returns a string of all enumeration elements.
1263 */
1264static const xmlChar *
1265xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
1266{
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001267 xmlSchemaFacetPtr facet;
1268 xmlSchemaWhitespaceValueType ws;
1269 const xmlChar *value;
1270 int res;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001271
1272 if (*buf != NULL)
1273 xmlFree(*buf);
1274 *buf = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001275
1276 do {
1277 /*
1278 * Use the whitespace type of the base type.
1279 */
1280 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
1281 /* TODO: Get rid of this case. */
1282 ws = (xmlSchemaWhitespaceValueType)
1283 xmlSchemaGetWhiteSpaceFacetValue(
1284 xmlSchemaGetSimpleContentType(type));
1285 else
1286 ws = (xmlSchemaWhitespaceValueType)
1287 xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1288 for (facet = type->facets; facet != NULL; facet = facet->next) {
1289 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1290 continue;
1291 res = xmlSchemaGetCanonValueWhtsp(facet->value, facet->val,
1292 ws, &value);
1293 if (res == -1) {
1294 xmlSchemaVErr(NULL, NULL,
1295 XML_SCHEMAV_INTERNAL,
1296 "Internal error: xmlSchemaFormatFacetEnumSet, failed to "
1297 "compute the canonical lexical representation.\n",
1298 NULL, NULL);
1299 if (*buf != NULL)
1300 xmlFree(*buf);
1301 *buf = NULL;
1302 return (NULL);
1303 }
1304 if (*buf == NULL) {
1305 *buf = xmlStrdup(BAD_CAST "'");
1306 *buf = xmlStrcat(*buf, value);
1307 *buf = xmlStrcat(*buf, BAD_CAST "'");
1308 } else {
1309 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1310 *buf = xmlStrcat(*buf, value);
1311 *buf = xmlStrcat(*buf, BAD_CAST "'");
1312 }
1313 }
1314 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
1315 /* TODO: Get rid of this case. */
1316 type = xmlSchemaGetSimpleContentType(type);
1317 else
1318 type = type->baseType;
1319 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1320
1321#if 0
Daniel Veillardc0826a72004-08-10 14:17:33 +00001322 for (link = type->facetSet; link != NULL; link = link->next) {
1323 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
1324 if (*buf == NULL) {
1325 *buf = xmlStrdup(BAD_CAST "'");
1326 *buf = xmlStrcat(*buf, link->facet->value);
1327 *buf = xmlStrcat(*buf, BAD_CAST "'");
1328 } else {
1329 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1330 *buf = xmlStrcat(*buf, link->facet->value);
1331 *buf = xmlStrcat(*buf, BAD_CAST "'");
1332 }
1333 }
1334 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001335#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +00001336 return ((const xmlChar *) *buf);
1337}
1338
1339/**
1340 * xmlSchemaVFacetErr:
1341 * @ctxt: the schema validation context
1342 * @error: the error code
1343 * @node: the node to be validated
1344 * @value: the value of the node
1345 * @type: the type holding the facet
1346 * @facet: the facet
1347 * @message: the error message of NULL
1348 * @str1: extra data
1349 * @str2: extra data
1350 * @str3: extra data
1351 *
1352 * Reports a facet validation error.
1353 * TODO: Should this report the value of an element as well?
1354 */
1355static void
1356xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
1357 xmlParserErrors error,
1358 xmlNodePtr node,
1359 const xmlChar *value,
1360 unsigned long length,
1361 xmlSchemaTypePtr type,
1362 xmlSchemaFacetPtr facet,
1363 const char *message,
1364 const xmlChar *str1,
1365 const xmlChar *str2,
1366 const xmlChar *str3)
1367{
1368 xmlChar *str = NULL, *msg = NULL;
1369 xmlSchemaTypeType facetType;
1370
1371 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1372 msg = xmlStrcat(msg, BAD_CAST " [");
1373 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1374 msg = xmlStrcat(msg, BAD_CAST ", facet '");
1375 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1376 facetType = XML_SCHEMA_FACET_ENUMERATION;
1377 /*
1378 * If enumerations are validated, one must not expect the
1379 * facet to be given.
1380 */
1381 } else
1382 facetType = facet->type;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001383 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001384 msg = xmlStrcat(msg, BAD_CAST "']: ");
1385 if (message == NULL) {
1386 /*
1387 * Use a default message.
1388 */
1389 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1390 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1391 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1392
1393 char len[25], actLen[25];
1394
1395 /* FIXME, TODO: What is the max expected string length of the
1396 * this value?
1397 */
1398 if (node->type == XML_ATTRIBUTE_NODE)
1399 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1400 else
1401 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1402
1403 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1404 snprintf(actLen, 24, "%lu", length);
1405
1406 if (facetType == XML_SCHEMA_FACET_LENGTH)
1407 msg = xmlStrcat(msg,
1408 BAD_CAST "this differs from the allowed length of '%s'.\n");
1409 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
1410 msg = xmlStrcat(msg,
1411 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
1412 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
1413 msg = xmlStrcat(msg,
1414 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
1415
1416 if (node->type == XML_ATTRIBUTE_NODE)
1417 xmlSchemaVErrExt(ctxt, node, error,
1418 (const char *) msg,
1419 value, (const xmlChar *) actLen, (const xmlChar *) len,
1420 NULL, NULL);
1421 else
1422 xmlSchemaVErr(ctxt, node, error,
1423 (const char *) msg,
1424 (const xmlChar *) actLen, (const xmlChar *) len);
1425
1426 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
1427 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
1428 "of the set {%s}.\n");
1429 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1430 xmlSchemaFormatFacetEnumSet(&str, type));
1431 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1432 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1433 "by the pattern '%s'.\n");
1434 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001435 facet->value);
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001436 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
1437 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
1438 "minimum value allowed ('%s').\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001439 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001440 facet->value);
1441 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
1442 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
1443 "maximum value allowed ('%s').\n");
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001444 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001445 facet->value);
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00001446#if 0
1447 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
1448 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
1449 "minimum exclusive value allowed ('%s').\n");
1450 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1451 facet->value);
1452 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
1453 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
1454 "maximum exclusive value allowed ('%s').\n");
1455 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1456 facet->value);
1457#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +00001458 } else if (node->type == XML_ATTRIBUTE_NODE) {
1459 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1460 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1461 } else {
1462 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1463 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1464 }
1465 } else {
1466 msg = xmlStrcat(msg, (const xmlChar *) message);
1467 msg = xmlStrcat(msg, BAD_CAST ".\n");
1468 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1469 }
1470 FREE_AND_NULL(str)
1471 xmlFree(msg);
1472}
1473
1474/**
1475 * xmlSchemaVSimpleTypeErr:
1476 * @ctxt: the schema validation context
1477 * @error: the error code
1478 * @type: the type used for validation
1479 * @node: the node containing the validated value
1480 * @value: the validated value
1481 *
1482 * Reports a simple type validation error.
1483 * TODO: Should this report the value of an element as well?
1484 */
1485static void
1486xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1487 xmlParserErrors error,
1488 xmlNodePtr node,
1489 const xmlChar *value,
1490 xmlSchemaTypePtr type)
1491{
1492 xmlChar *str = NULL, *msg = NULL;
1493
1494 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1495 msg = xmlStrcat(msg, BAD_CAST " [");
1496 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1497 if (node->type == XML_ATTRIBUTE_NODE) {
1498 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1499 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1500 } else {
1501 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1502 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1503 }
1504 FREE_AND_NULL(str)
1505 xmlFree(msg);
1506}
1507
1508/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001509 * xmlSchemaVComplexTypeErr:
1510 * @ctxt: the schema validation context
1511 * @error: the error code
1512 * @node: the node containing the validated value
1513 * @type: the complex type used for validation
1514 * @message: the error message
1515 *
1516 * Reports a complex type validation error.
1517 */
1518static void
1519xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1520 xmlParserErrors error,
1521 xmlNodePtr node,
1522 xmlSchemaTypePtr type,
1523 const char *message)
1524{
1525 xmlChar *str = NULL, *msg = NULL;
1526
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001527 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001528 /* Specify the complex type only if it is global. */
1529 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001530 msg = xmlStrcat(msg, BAD_CAST " [");
1531 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1532 msg = xmlStrcat(msg, BAD_CAST "]");
1533 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001534 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1535 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001536 (const xmlChar *) message, NULL);
1537 FREE_AND_NULL(str)
1538 xmlFree(msg);
1539}
1540
1541/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001542 * xmlSchemaVComplexTypeElemErr:
1543 * @ctxt: the schema validation context
1544 * @error: the error code
1545 * @node: the node containing the validated value
1546 * @type: the complex type used for validation
1547 * @message: the error message
1548 *
1549 * Reports a complex type validation error.
1550 */
1551static void
1552xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1553 xmlParserErrors error,
1554 xmlNodePtr node,
1555 xmlSchemaTypePtr type,
1556 const char *message,
1557 int nbval,
1558 int nbneg,
1559 xmlChar **values)
1560{
1561 xmlChar *str = NULL, *msg = NULL;
1562 xmlChar *localName, *nsName;
1563 const xmlChar *cur, *end;
1564 int i;
1565
1566 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1567 /* Specify the complex type only if it is global. */
1568 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1569 msg = xmlStrcat(msg, BAD_CAST " [");
1570 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1571 msg = xmlStrcat(msg, BAD_CAST "]");
1572 FREE_AND_NULL(str)
1573 }
1574 msg = xmlStrcat(msg, BAD_CAST ": ");
1575 msg = xmlStrcat(msg, (const xmlChar *) message);
1576 /*
1577 * Note that is does not make sense to report that we have a
1578 * wildcard here, since the wildcard might be unfolded into
1579 * multiple transitions.
1580 */
1581 if (nbval + nbneg > 0) {
1582 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001583 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001584 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001585 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001586 nsName = NULL;
1587
1588 for (i = 0; i < nbval + nbneg; i++) {
1589 cur = values[i];
1590 /*
1591 * Get the local name.
1592 */
1593 localName = NULL;
1594
1595 end = cur;
1596 if (*end == '*') {
1597 localName = xmlStrdup(BAD_CAST "*");
1598 *end++;
1599 } else {
1600 while ((*end != 0) && (*end != '|'))
1601 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001602 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001603 }
1604 if (*end != 0) {
1605 *end++;
1606 /*
1607 * Skip "*|*" if they come with negated expressions, since
1608 * they represent the same negated wildcard.
1609 */
1610 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1611 /*
1612 * Get the namespace name.
1613 */
1614 cur = end;
1615 if (*end == '*') {
1616 nsName = xmlStrdup(BAD_CAST "{*}");
1617 } else {
1618 while (*end != 0)
1619 end++;
1620
1621 if (i >= nbval)
1622 nsName = xmlStrdup(BAD_CAST "{##other:");
1623 else
1624 nsName = xmlStrdup(BAD_CAST "{");
1625
1626 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1627 nsName = xmlStrcat(nsName, BAD_CAST "}");
1628 }
1629 str = xmlStrcat(str, BAD_CAST nsName);
1630 FREE_AND_NULL(nsName)
1631 } else {
1632 FREE_AND_NULL(localName);
1633 continue;
1634 }
1635 }
1636 str = xmlStrcat(str, BAD_CAST localName);
1637 FREE_AND_NULL(localName);
1638
1639 if (i < nbval + nbneg -1)
1640 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001641 }
1642 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001643 msg = xmlStrcat(msg, BAD_CAST str);
1644 FREE_AND_NULL(str)
1645 }
1646 msg = xmlStrcat(msg, BAD_CAST ".\n");
1647 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1648 xmlFree(msg);
1649}
1650
1651/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001652 * xmlSchemaPMissingAttrErr:
1653 * @ctxt: the schema validation context
1654 * @ownerDes: the designation of the owner
1655 * @ownerName: the name of the owner
1656 * @ownerItem: the owner as a schema object
1657 * @ownerElem: the owner as an element node
1658 * @node: the parent element node of the missing attribute node
1659 * @type: the corresponding type of the attribute node
1660 *
1661 * Reports an illegal attribute.
1662 */
1663static void
1664xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1665 xmlParserErrors error,
1666 xmlChar **ownerDes,
1667 xmlSchemaTypePtr ownerItem,
1668 xmlNodePtr ownerElem,
1669 const char *name,
1670 const char *message)
1671{
1672 xmlChar *des = NULL;
1673
1674 if (ownerDes == NULL)
1675 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1676 else if (*ownerDes == NULL) {
1677 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1678 des = *ownerDes;
1679 } else
1680 des = *ownerDes;
1681 if (message != NULL)
1682 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1683 else
1684 xmlSchemaPErr(ctxt, ownerElem, error,
1685 "%s: The attribute '%s' is required but missing.\n",
1686 BAD_CAST des, BAD_CAST name);
1687 if (ownerDes == NULL)
1688 FREE_AND_NULL(des);
1689}
1690
William M. Brack2f2a6632004-08-20 23:09:47 +00001691/**
1692 * xmlSchemaCompTypeToString:
1693 * @type: the type of the schema item
1694 *
1695 * Returns the component name of a schema item.
1696 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001697static const char *
1698xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1699{
1700 switch (type) {
1701 case XML_SCHEMA_TYPE_SIMPLE:
1702 return("simple type definition");
1703 case XML_SCHEMA_TYPE_COMPLEX:
1704 return("complex type definition");
1705 case XML_SCHEMA_TYPE_ELEMENT:
1706 return("element declaration");
1707 case XML_SCHEMA_TYPE_ATTRIBUTE:
1708 return("attribute declaration");
1709 case XML_SCHEMA_TYPE_GROUP:
1710 return("model group definition");
1711 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1712 return("attribute group definition");
1713 case XML_SCHEMA_TYPE_NOTATION:
1714 return("notation declaration");
1715 default:
1716 return("Not a schema component");
1717 }
1718}
1719/**
1720 * xmlSchemaPResCompAttrErr:
1721 * @ctxt: the schema validation context
1722 * @error: the error code
1723 * @ownerDes: the designation of the owner
1724 * @ownerItem: the owner as a schema object
1725 * @ownerElem: the owner as an element node
1726 * @name: the name of the attribute holding the QName
1727 * @refName: the referenced local name
1728 * @refURI: the referenced namespace URI
1729 * @message: optional message
1730 *
1731 * Used to report QName attribute values that failed to resolve
1732 * to schema components.
1733 */
1734static void
1735xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1736 xmlParserErrors error,
1737 xmlChar **ownerDes,
1738 xmlSchemaTypePtr ownerItem,
1739 xmlNodePtr ownerElem,
1740 const char *name,
1741 const xmlChar *refName,
1742 const xmlChar *refURI,
1743 xmlSchemaTypeType refType,
1744 const char *refTypeStr)
1745{
1746 xmlChar *des = NULL, *strA = NULL;
1747
1748 if (ownerDes == NULL)
1749 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1750 else if (*ownerDes == NULL) {
1751 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1752 des = *ownerDes;
1753 } else
1754 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001755 if (refTypeStr == NULL)
1756 refTypeStr = xmlSchemaCompTypeToString(refType);
1757 xmlSchemaPErrExt(ctxt, ownerElem, error,
1758 NULL, NULL, NULL,
1759 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1760 "%s.\n", BAD_CAST des, BAD_CAST name,
1761 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1762 BAD_CAST refTypeStr, NULL);
1763 if (ownerDes == NULL)
1764 FREE_AND_NULL(des)
1765 FREE_AND_NULL(strA)
1766}
1767
William M. Brack2f2a6632004-08-20 23:09:47 +00001768/**
1769 * xmlSchemaPCustomAttrErr:
1770 * @ctxt: the schema parser context
1771 * @error: the error code
1772 * @ownerDes: the designation of the owner
1773 * @ownerItem: the owner as a schema object
1774 * @attr: the illegal attribute node
1775 *
1776 * Reports an illegal attribute during the parse.
1777 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001778static void
1779xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001780 xmlParserErrors error,
1781 xmlChar **ownerDes,
1782 xmlSchemaTypePtr ownerItem,
1783 xmlAttrPtr attr,
1784 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001785{
1786 xmlChar *des = NULL;
1787
1788 if (ownerDes == NULL)
1789 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1790 else if (*ownerDes == NULL) {
1791 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1792 des = *ownerDes;
1793 } else
1794 des = *ownerDes;
1795 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1796 "%s, attribute '%s': %s.\n",
1797 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1798 if (ownerDes == NULL)
1799 FREE_AND_NULL(des);
1800}
1801
1802/**
1803 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001804 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001805 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001806 * @ownerDes: the designation of the attribute's owner
1807 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001808 * @attr: the illegal attribute node
1809 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001810 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001811 */
1812static void
1813xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1814 xmlParserErrors error,
1815 xmlChar **ownerDes,
1816 xmlSchemaTypePtr ownerItem,
1817 xmlAttrPtr attr)
1818{
1819 xmlChar *des = NULL, *strA = NULL;
1820
1821 if (ownerDes == NULL)
1822 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1823 else if (*ownerDes == NULL) {
1824 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1825 des = *ownerDes;
1826 } else
1827 des = *ownerDes;
1828 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1829 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1830 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1831 if (ownerDes == NULL)
1832 FREE_AND_NULL(des);
1833 FREE_AND_NULL(strA);
1834}
1835
William M. Brack2f2a6632004-08-20 23:09:47 +00001836/**
1837 * xmlSchemaPAquireDes:
1838 * @des: the first designation
1839 * @itemDes: the second designation
1840 * @item: the schema item
1841 * @itemElem: the node of the schema item
1842 *
1843 * Creates a designation for an item.
1844 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001845static void
1846xmlSchemaPAquireDes(xmlChar **des,
1847 xmlChar **itemDes,
1848 xmlSchemaTypePtr item,
1849 xmlNodePtr itemElem)
1850{
1851 if (itemDes == NULL)
1852 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1853 else if (*itemDes == NULL) {
1854 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1855 *des = *itemDes;
1856 } else
1857 *des = *itemDes;
1858}
1859
William M. Brack2f2a6632004-08-20 23:09:47 +00001860/**
1861 * xmlSchemaPCustomErr:
1862 * @ctxt: the schema parser context
1863 * @error: the error code
1864 * @itemDes: the designation of the schema item
1865 * @item: the schema item
1866 * @itemElem: the node of the schema item
1867 * @message: the error message
1868 * @str1: an optional param for the error message
1869 * @str2: an optional param for the error message
1870 * @str3: an optional param for the error message
1871 *
1872 * Reports an error during parsing.
1873 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001874static void
1875xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1876 xmlParserErrors error,
1877 xmlChar **itemDes,
1878 xmlSchemaTypePtr item,
1879 xmlNodePtr itemElem,
1880 const char *message,
1881 const xmlChar *str1,
1882 const xmlChar *str2,
1883 const xmlChar *str3)
1884{
1885 xmlChar *des = NULL, *msg = NULL;
1886
1887 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1888 msg = xmlStrdup(BAD_CAST "%s: ");
1889 msg = xmlStrcat(msg, (const xmlChar *) message);
1890 msg = xmlStrcat(msg, BAD_CAST ".\n");
1891 if ((itemElem == NULL) && (item != NULL))
1892 itemElem = item->node;
1893 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1894 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1895 if (itemDes == NULL)
1896 FREE_AND_NULL(des);
1897 FREE_AND_NULL(msg);
1898}
1899
William M. Brack2f2a6632004-08-20 23:09:47 +00001900/**
1901 * xmlSchemaPCustomErr:
1902 * @ctxt: the schema parser context
1903 * @error: the error code
1904 * @itemDes: the designation of the schema item
1905 * @item: the schema item
1906 * @itemElem: the node of the schema item
1907 * @message: the error message
1908 * @str1: the optional param for the error message
1909 *
1910 * Reports an error during parsing.
1911 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001912static void
1913xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1914 xmlParserErrors error,
1915 xmlChar **itemDes,
1916 xmlSchemaTypePtr item,
1917 xmlNodePtr itemElem,
1918 const char *message,
1919 const xmlChar *str1)
1920{
1921 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1922 str1, NULL, NULL);
1923}
1924
William M. Brack2f2a6632004-08-20 23:09:47 +00001925/**
1926 * xmlSchemaPAttrUseErr:
1927 * @ctxt: the schema parser context
1928 * @error: the error code
1929 * @itemDes: the designation of the schema type
1930 * @item: the schema type
1931 * @itemElem: the node of the schema type
1932 * @attr: the invalid schema attribute
1933 * @message: the error message
1934 * @str1: the optional param for the error message
1935 *
1936 * Reports an attribute use error during parsing.
1937 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001938static void
1939xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1940 xmlParserErrors error,
1941 xmlChar **itemDes,
1942 xmlSchemaTypePtr item,
1943 xmlNodePtr itemElem,
1944 const xmlSchemaAttributePtr attr,
1945 const char *message,
1946 const xmlChar *str1)
1947{
1948 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1949
1950 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1951 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1952 xmlSchemaGetAttrName(attr));
1953 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1954 msg = xmlStrcat(msg, (const xmlChar *) message);
1955 msg = xmlStrcat(msg, BAD_CAST ".\n");
1956 if ((itemElem == NULL) && (item != NULL))
1957 itemElem = item->node;
1958 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1959 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1960 if (itemDes == NULL)
1961 FREE_AND_NULL(des);
1962 FREE_AND_NULL(strA);
1963 xmlFree(msg);
1964}
1965
William M. Brack2f2a6632004-08-20 23:09:47 +00001966/**
1967 * xmlSchemaPIllegalFacetAtomicErr:
1968 * @ctxt: the schema parser context
1969 * @error: the error code
1970 * @itemDes: the designation of the type
1971 * @item: the schema type
1972 * @baseItem: the base type of type
1973 * @facet: the illegal facet
1974 *
1975 * Reports an illegal facet for atomic simple types.
1976 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001977static void
1978xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1979 xmlParserErrors error,
1980 xmlChar **itemDes,
1981 xmlSchemaTypePtr item,
1982 xmlSchemaTypePtr baseItem,
1983 xmlSchemaFacetPtr facet)
1984{
1985 xmlChar *des = NULL, *strT = NULL;
1986
1987 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1988 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1989 "%s: The facet '%s' is not allowed on types derived from the "
1990 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001991 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardc0826a72004-08-10 14:17:33 +00001992 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1993 NULL, NULL);
1994 if (itemDes == NULL)
1995 FREE_AND_NULL(des);
1996 FREE_AND_NULL(strT);
1997}
1998
William M. Brack2f2a6632004-08-20 23:09:47 +00001999/**
2000 * xmlSchemaPIllegalFacetListUnionErr:
2001 * @ctxt: the schema parser context
2002 * @error: the error code
2003 * @itemDes: the designation of the schema item involved
2004 * @item: the schema item involved
2005 * @facet: the illegal facet
2006 *
2007 * Reports an illegal facet for <list> and <union>.
2008 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002009static void
2010xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
2011 xmlParserErrors error,
2012 xmlChar **itemDes,
2013 xmlSchemaTypePtr item,
2014 xmlSchemaFacetPtr facet)
2015{
2016 xmlChar *des = NULL, *strT = NULL;
2017
2018 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2019 xmlSchemaPErr(ctxt, item->node, error,
2020 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002021 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002022 if (itemDes == NULL)
2023 FREE_AND_NULL(des);
2024 FREE_AND_NULL(strT);
2025}
2026
2027/**
2028 * xmlSchemaPMutualExclAttrErr:
2029 * @ctxt: the schema validation context
2030 * @error: the error code
2031 * @elemDes: the designation of the parent element node
2032 * @attr: the bad attribute node
2033 * @type: the corresponding type of the attribute node
2034 *
2035 * Reports an illegal attribute.
2036 */
2037static void
2038xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2039 xmlParserErrors error,
2040 xmlChar **ownerDes,
2041 xmlSchemaTypePtr ownerItem,
2042 xmlAttrPtr attr,
2043 const char *name1,
2044 const char *name2)
2045{
2046 xmlChar *des = NULL;
2047
2048 if (ownerDes == NULL)
2049 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2050 else if (*ownerDes == NULL) {
2051 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2052 des = *ownerDes;
2053 } else
2054 des = *ownerDes;
2055 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2056 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
2057 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2058 if (ownerDes == NULL)
2059 FREE_AND_NULL(des)
2060}
2061
2062/**
2063 * xmlSchemaPSimpleTypeErr:
2064 * @ctxt: the schema validation context
2065 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002066 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002067 * @ownerDes: the designation of the owner
2068 * @ownerItem: the schema object if existent
2069 * @node: the validated node
2070 * @value: the validated value
2071 *
2072 * Reports a simple type validation error.
2073 * TODO: Should this report the value of an element as well?
2074 */
2075static void
2076xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2077 xmlParserErrors error,
2078 xmlChar **ownerDes,
2079 xmlSchemaTypePtr ownerItem,
2080 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002081 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002082 const char *typeDes,
2083 const xmlChar *value,
2084 const char *message,
2085 const xmlChar *str1,
2086 const xmlChar *str2)
2087{
William M. Brack2f2a6632004-08-20 23:09:47 +00002088 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002089
2090 if (ownerDes == NULL)
2091 xmlSchemaPRequestItemDes(&des, ownerItem, node);
2092 else if (*ownerDes == NULL) {
2093 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
2094 des = *ownerDes;
2095 } else
2096 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00002097 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002098 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002099 if (message == NULL) {
2100 /*
2101 * Use default messages.
2102 */
2103 if (node->type == XML_ATTRIBUTE_NODE) {
2104 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2105 "%s, attribute '%s' [%s]: The value '%s' is not "
2106 "valid.\n",
2107 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
2108 node->name), BAD_CAST typeDes, value, NULL);
2109 } else {
2110 xmlSchemaPErr(ctxt, node, error,
2111 "%s [%s]: The character content is not valid.\n",
2112 BAD_CAST des, BAD_CAST typeDes);
2113 }
2114 } else {
2115 xmlChar *msg;
2116
2117 msg = xmlStrdup(BAD_CAST "%s");
2118 if (node->type == XML_ATTRIBUTE_NODE)
2119 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
2120 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
2121 msg = xmlStrcat(msg, (const xmlChar *) message);
2122 msg = xmlStrcat(msg, BAD_CAST ".\n");
2123 if (node->type == XML_ATTRIBUTE_NODE) {
2124 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2125 (const char *) msg,
2126 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
2127 node->ns, node->name), BAD_CAST typeDes, str1, str2);
2128 } else {
2129 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2130 (const char *) msg,
2131 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
2132 }
2133 xmlFree(msg);
2134 }
2135 /* Cleanup. */
2136 FREE_AND_NULL(strA)
2137 FREE_AND_NULL(strT)
2138 if (ownerDes == NULL)
2139 FREE_AND_NULL(des)
2140}
2141
William M. Brack2f2a6632004-08-20 23:09:47 +00002142/**
2143 * xmlSchemaPContentErr:
2144 * @ctxt: the schema parser context
2145 * @error: the error code
2146 * @onwerDes: the designation of the holder of the content
2147 * @ownerItem: the owner item of the holder of the content
2148 * @ownerElem: the node of the holder of the content
2149 * @child: the invalid child node
2150 * @message: the optional error message
2151 * @content: the optional string describing the correct content
2152 *
2153 * Reports an error concerning the content of a schema element.
2154 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002155static void
2156xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
2157 xmlParserErrors error,
2158 xmlChar **ownerDes,
2159 xmlSchemaTypePtr ownerItem,
2160 xmlNodePtr ownerElem,
2161 xmlNodePtr child,
2162 const char *message,
2163 const char *content)
2164{
2165 xmlChar *des = NULL;
2166
2167 if (ownerDes == NULL)
2168 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
2169 else if (*ownerDes == NULL) {
2170 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
2171 des = *ownerDes;
2172 } else
2173 des = *ownerDes;
2174 if (message != NULL)
2175 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2176 "%s: %s.\n",
2177 BAD_CAST des, BAD_CAST message);
2178 else {
2179 if (content != NULL) {
2180 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2181 "%s: The content is not valid. Expected is %s.\n",
2182 BAD_CAST des, BAD_CAST content);
2183 } else {
2184 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2185 "%s: The content is not valid.\n",
2186 BAD_CAST des, NULL);
2187 }
2188 }
2189 if (ownerDes == NULL)
2190 FREE_AND_NULL(des)
2191}
2192
2193/**
2194 * xmlSchemaVIllegalAttrErr:
2195 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002196 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00002197 * @attr: the illegal attribute node
2198 *
2199 * Reports an illegal attribute.
2200 */
2201static void
2202xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002203 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002204 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002205{
2206 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002207
2208 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
2209 error,
2210 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002211 "%s: The attribute '%s' is not allowed.\n",
2212 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
2213 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2214 FREE_AND_NULL(strE)
2215 FREE_AND_NULL(strA)
2216}
2217
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002218
2219static int
2220xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2221{
2222 switch (item->type) {
2223 case XML_SCHEMA_TYPE_COMPLEX:
2224 case XML_SCHEMA_TYPE_SIMPLE:
2225 case XML_SCHEMA_TYPE_GROUP:
2226 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2227 return(1);
2228 break;
2229 case XML_SCHEMA_TYPE_ELEMENT:
2230 if ( ((xmlSchemaElementPtr) item)->flags &
2231 XML_SCHEMAS_ELEM_GLOBAL)
2232 return(1);
2233 break;
2234 case XML_SCHEMA_TYPE_ATTRIBUTE:
2235 if ( ((xmlSchemaAttributePtr) item)->flags &
2236 XML_SCHEMAS_ATTR_GLOBAL)
2237 return(1);
2238 break;
2239 /* Note that attribute groups are always global. */
2240 default:
2241 return(1);
2242 }
2243 return (0);
2244}
2245
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002246
2247static void
2248xmlSchemaStreamVCustomErr(xmlSchemaValidCtxtPtr vctxt,
2249 xmlParserErrors error,
2250 xmlSchemaNodeInfoPtr nodeInfo,
2251 xmlSchemaTypePtr type,
2252 const char *message,
2253 const xmlChar *str1,
2254 const xmlChar *str2)
2255{
2256 xmlChar *msg = NULL, *str = NULL;
2257
2258 msg = xmlStrdup(BAD_CAST "Element '");
2259
2260 if (vctxt->elemInfos[vctxt->depth] != nodeInfo) {
2261 xmlSchemaNodeInfoPtr elemInfo;
2262 /*
2263 * The node info is an attribute info.
2264 */
2265 elemInfo = vctxt->elemInfos[vctxt->depth];
2266 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2267 elemInfo->namespaceName, elemInfo->localName));
2268 msg = xmlStrcat(msg, BAD_CAST "', ");
2269 msg = xmlStrcat(msg, BAD_CAST "attribute '");
2270 }
2271 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2272 nodeInfo->namespaceName, nodeInfo->localName));
2273 msg = xmlStrcat(msg, BAD_CAST "'");
2274
2275 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2276 msg = xmlStrcat(msg, BAD_CAST " [");
2277 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str,
2278 NULL, type, NULL, 0));
2279 msg = xmlStrcat(msg, BAD_CAST "]");
2280 }
2281 msg = xmlStrcat(msg, BAD_CAST ": ");
2282
2283 msg = xmlStrcat(msg, (const xmlChar *) message);
2284 msg = xmlStrcat(msg, BAD_CAST ".\n");
2285 xmlSchemaVErr(vctxt, nodeInfo->node, error, (const char *) msg,
2286 str1, str2);
2287 FREE_AND_NULL(msg)
2288 FREE_AND_NULL(str)
2289}
2290
William M. Brack2f2a6632004-08-20 23:09:47 +00002291/**
2292 * xmlSchemaVCustomErr:
2293 * @ctxt: the schema validation context
2294 * @error: the error code
2295 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002296 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00002297 * @message: the error message
2298 * @str1: the optional param for the message
2299 *
2300 * Reports a validation error.
2301 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002302static void
2303xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
2304 xmlParserErrors error,
2305 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002306 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002307 const char *message,
2308 const xmlChar *str1)
2309{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002310 xmlChar *msg = NULL, *str = NULL;
2311
2312 if (node == NULL) {
2313 xmlSchemaVErr(ctxt, NULL,
2314 XML_SCHEMAV_INTERNAL,
2315 "Internal error: xmlSchemaVCustomErr, no node "
2316 "given.\n", NULL, NULL);
2317 return;
2318 }
2319 /* TODO: Are the HTML and DOCB doc nodes expected here? */
2320 if (node->type != XML_DOCUMENT_NODE) {
2321 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002322 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002323 msg = xmlStrcat(msg, BAD_CAST " [");
2324 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
2325 msg = xmlStrcat(msg, BAD_CAST "]");
2326 }
2327 msg = xmlStrcat(msg, BAD_CAST ": ");
2328 } else
2329 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002330 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002331 msg = xmlStrcat(msg, BAD_CAST ".\n");
2332 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
2333 FREE_AND_NULL(msg)
2334 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002335}
2336
William M. Brack2f2a6632004-08-20 23:09:47 +00002337/**
William M. Brack2f2a6632004-08-20 23:09:47 +00002338 * xmlSchemaVWildcardErr:
2339 * @ctxt: the schema validation context
2340 * @error: the error code
2341 * @node: the validated node
2342 * @wild: the wildcard used
2343 * @message: the error message
2344 *
2345 * Reports an validation-by-wildcard error.
2346 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002347static void
2348xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
2349 xmlParserErrors error,
2350 xmlNodePtr node,
2351 xmlSchemaWildcardPtr wild,
2352 const char *message)
2353{
2354 xmlChar *des = NULL, *msg = NULL;
2355
2356 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00002357 msg = xmlStrdup(BAD_CAST "%s [");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002358 msg = xmlStrcat(msg, xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002359 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002360 msg = xmlStrcat(msg, (const xmlChar *) message);
2361 msg = xmlStrcat(msg, BAD_CAST ".\n");
2362 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
2363 FREE_AND_NULL(des);
2364 FREE_AND_NULL(msg);
2365}
2366
2367/**
2368 * xmlSchemaVMissingAttrErr:
2369 * @ctxt: the schema validation context
2370 * @node: the parent element node of the missing attribute node
2371 * @type: the corresponding type of the attribute node
2372 *
2373 * Reports an illegal attribute.
2374 */
2375static void
2376xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
2377 xmlNodePtr elem,
2378 xmlSchemaAttributePtr type)
2379{
2380 const xmlChar *name, *uri;
2381 xmlChar *strE = NULL, *strA = NULL;
2382
2383 if (type->ref != NULL) {
2384 name = type->ref;
2385 uri = type->refNs;
2386 } else {
2387 name = type->name;
2388 uri = type->targetNamespace;
2389 }
2390 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002391 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
2392 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002393 "%s: The attribute %s is required but missing.\n",
2394 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
2395 xmlSchemaFormatNsUriLocal(&strA, uri, name));
2396 FREE_AND_NULL(strE)
2397 FREE_AND_NULL(strA)
2398}
2399
Daniel Veillard4255d502002-04-16 15:50:10 +00002400/************************************************************************
2401 * *
2402 * Allocation functions *
2403 * *
2404 ************************************************************************/
2405
2406/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002407 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002408 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002409 *
2410 * Allocate a new Schema structure.
2411 *
2412 * Returns the newly allocated structure or NULL in case or error
2413 */
2414static xmlSchemaPtr
2415xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2416{
2417 xmlSchemaPtr ret;
2418
2419 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2420 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002421 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002422 return (NULL);
2423 }
2424 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002425 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002426 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002427
2428 return (ret);
2429}
2430
2431/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002432 * xmlSchemaNewSchema:
2433 * @ctxt: a schema validation context
2434 *
2435 * Allocate a new Schema structure.
2436 *
2437 * Returns the newly allocated structure or NULL in case or error
2438 */
2439static xmlSchemaAssemblePtr
2440xmlSchemaNewAssemble(void)
2441{
2442 xmlSchemaAssemblePtr ret;
2443
2444 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2445 if (ret == NULL) {
2446 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2447 return (NULL);
2448 }
2449 memset(ret, 0, sizeof(xmlSchemaAssemble));
2450 ret->items = NULL;
2451 return (ret);
2452}
2453
2454/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002455 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002456 *
2457 * Allocate a new Facet structure.
2458 *
2459 * Returns the newly allocated structure or NULL in case or error
2460 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002461xmlSchemaFacetPtr
2462xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002463{
2464 xmlSchemaFacetPtr ret;
2465
2466 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2467 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002468 return (NULL);
2469 }
2470 memset(ret, 0, sizeof(xmlSchemaFacet));
2471
2472 return (ret);
2473}
2474
2475/**
2476 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002477 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002478 * @node: a node
2479 *
2480 * Allocate a new annotation structure.
2481 *
2482 * Returns the newly allocated structure or NULL in case or error
2483 */
2484static xmlSchemaAnnotPtr
2485xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2486{
2487 xmlSchemaAnnotPtr ret;
2488
2489 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2490 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002491 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002492 return (NULL);
2493 }
2494 memset(ret, 0, sizeof(xmlSchemaAnnot));
2495 ret->content = node;
2496 return (ret);
2497}
2498
2499/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002500 * xmlSchemaFreeAnnot:
2501 * @annot: a schema type structure
2502 *
2503 * Deallocate a annotation structure
2504 */
2505static void
2506xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2507{
2508 if (annot == NULL)
2509 return;
2510 xmlFree(annot);
2511}
2512
2513/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002514 * xmlSchemaFreeImport:
2515 * @import: a schema import structure
2516 *
2517 * Deallocate an import structure
2518 */
2519static void
2520xmlSchemaFreeImport(xmlSchemaImportPtr import)
2521{
2522 if (import == NULL)
2523 return;
2524
2525 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002526 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002527 xmlFree(import);
2528}
2529
2530/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002531 * xmlSchemaFreeInclude:
2532 * @include: a schema include structure
2533 *
2534 * Deallocate an include structure
2535 */
2536static void
2537xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2538{
2539 if (include == NULL)
2540 return;
2541
2542 xmlFreeDoc(include->doc);
2543 xmlFree(include);
2544}
2545
2546/**
2547 * xmlSchemaFreeIncludeList:
2548 * @includes: a schema include list
2549 *
2550 * Deallocate an include structure
2551 */
2552static void
2553xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2554{
2555 xmlSchemaIncludePtr next;
2556
2557 while (includes != NULL) {
2558 next = includes->next;
2559 xmlSchemaFreeInclude(includes);
2560 includes = next;
2561 }
2562}
2563
2564/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002565 * xmlSchemaFreeNotation:
2566 * @schema: a schema notation structure
2567 *
2568 * Deallocate a Schema Notation structure.
2569 */
2570static void
2571xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2572{
2573 if (nota == NULL)
2574 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002575 xmlFree(nota);
2576}
2577
2578/**
2579 * xmlSchemaFreeAttribute:
2580 * @schema: a schema attribute structure
2581 *
2582 * Deallocate a Schema Attribute structure.
2583 */
2584static void
2585xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2586{
2587 if (attr == NULL)
2588 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002589 if (attr->annot != NULL)
2590 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002591 if (attr->defVal != NULL)
2592 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002593 xmlFree(attr);
2594}
2595
2596/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002597 * xmlSchemaFreeWildcardNsSet:
2598 * set: a schema wildcard namespace
2599 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002600 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002601 */
2602static void
2603xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2604{
2605 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002606
Daniel Veillard3646d642004-06-02 19:19:14 +00002607 while (set != NULL) {
2608 next = set->next;
2609 xmlFree(set);
2610 set = next;
2611 }
2612}
2613
2614/**
2615 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002616 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002617 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002618 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002619 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002620void
Daniel Veillard3646d642004-06-02 19:19:14 +00002621xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2622{
2623 if (wildcard == NULL)
2624 return;
2625 if (wildcard->annot != NULL)
2626 xmlSchemaFreeAnnot(wildcard->annot);
2627 if (wildcard->nsSet != NULL)
2628 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2629 if (wildcard->negNsSet != NULL)
2630 xmlFree(wildcard->negNsSet);
2631 xmlFree(wildcard);
2632}
2633
2634/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002635 * xmlSchemaFreeAttributeGroup:
2636 * @schema: a schema attribute group structure
2637 *
2638 * Deallocate a Schema Attribute Group structure.
2639 */
2640static void
2641xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2642{
2643 if (attr == NULL)
2644 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002645 if (attr->annot != NULL)
2646 xmlSchemaFreeAnnot(attr->annot);
2647 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2648 (attr->attributeWildcard != NULL))
2649 xmlSchemaFreeWildcard(attr->attributeWildcard);
2650
Daniel Veillard4255d502002-04-16 15:50:10 +00002651 xmlFree(attr);
2652}
2653
2654/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002655 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002656 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002657 *
2658 * Deallocate a list of schema attribute uses.
2659 */
2660static void
2661xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2662{
2663 xmlSchemaAttributeLinkPtr next;
2664
2665 while (attrUse != NULL) {
2666 next = attrUse->next;
2667 xmlFree(attrUse);
2668 attrUse = next;
2669 }
2670}
2671
2672/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002673 * xmlSchemaFreeTypeLinkList:
2674 * @alink: a type link
2675 *
2676 * Deallocate a list of types.
2677 */
2678static void
2679xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2680{
2681 xmlSchemaTypeLinkPtr next;
2682
2683 while (link != NULL) {
2684 next = link->next;
2685 xmlFree(link);
2686 link = next;
2687 }
2688}
2689
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002690#ifdef IDC_ENABLED
2691static void
2692xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
2693{
2694 xmlSchemaIDCStateObjPtr next;
2695 while (sto != NULL) {
2696 next = sto->next;
2697 if (sto->history != NULL)
2698 xmlFree(sto->history);
2699 if (sto->xpathCtxt != NULL)
2700 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
2701 xmlFree(sto);
2702 sto = next;
2703 }
2704}
2705
2706/**
2707 * xmlSchemaFreeIDC:
2708 * @idc: a identity-constraint definition
2709 *
2710 * Deallocates an identity-constraint definition.
2711 */
2712static void
2713xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
2714{
2715 xmlSchemaIDCSelectPtr cur, prev;
2716
2717 if (idcDef == NULL)
2718 return;
2719 if (idcDef->annot != NULL)
2720 xmlSchemaFreeAnnot(idcDef->annot);
2721 if (idcDef->ref != NULL)
2722 xmlFree(idcDef->ref);
2723 /* Selector */
2724 if (idcDef->selector != NULL) {
2725 if (idcDef->selector->xpathComp != NULL)
2726 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
2727 xmlFree(idcDef->selector);
2728 }
2729 /* Fields */
2730 if (idcDef->fields != NULL) {
2731 cur = idcDef->fields;
2732 do {
2733 prev = cur;
2734 cur = cur->next;
2735 if (prev->xpathComp != NULL)
2736 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
2737 xmlFree(prev);
2738 } while (cur != NULL);
2739 }
2740 xmlFree(idcDef);
2741}
2742#endif /* IDC_ENABLED */
2743
Daniel Veillard01fa6152004-06-29 17:04:39 +00002744/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002745 * xmlSchemaFreeElement:
2746 * @schema: a schema element structure
2747 *
2748 * Deallocate a Schema Element structure.
2749 */
2750static void
2751xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2752{
2753 if (elem == NULL)
2754 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002755 if (elem->annot != NULL)
2756 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002757 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002758 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002759 if (elem->defVal != NULL)
2760 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002761 xmlFree(elem);
2762}
2763
2764/**
2765 * xmlSchemaFreeFacet:
2766 * @facet: a schema facet structure
2767 *
2768 * Deallocate a Schema Facet structure.
2769 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002770void
Daniel Veillard4255d502002-04-16 15:50:10 +00002771xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2772{
2773 if (facet == NULL)
2774 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002775 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002776 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002777 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002778 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002779 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002780 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002781 xmlFree(facet);
2782}
2783
2784/**
2785 * xmlSchemaFreeType:
2786 * @type: a schema type structure
2787 *
2788 * Deallocate a Schema Type structure.
2789 */
2790void
2791xmlSchemaFreeType(xmlSchemaTypePtr type)
2792{
2793 if (type == NULL)
2794 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002795 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002796 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002797 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002798 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002799
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002800 facet = type->facets;
2801 while (facet != NULL) {
2802 next = facet->next;
2803 xmlSchemaFreeFacet(facet);
2804 facet = next;
2805 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002806 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002807 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2808 if (type->attributeUses != NULL)
2809 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002810 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002811 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002812 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2813 /*
2814 * NOTE: The only case where an attribute wildcard
2815 * is not owned, is if a complex type inherits it
2816 * from a base type.
2817 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002818 xmlSchemaFreeWildcard(type->attributeWildcard);
2819 }
2820 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002821 if (type->memberTypes != NULL)
2822 xmlSchemaFreeTypeLinkList(type->memberTypes);
2823 if (type->facetSet != NULL) {
2824 xmlSchemaFacetLinkPtr next, link;
2825
2826 link = type->facetSet;
2827 do {
2828 next = link->next;
2829 xmlFree(link);
2830 link = next;
2831 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002832 }
2833 if (type->contModel != NULL)
2834 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002835 xmlFree(type);
2836}
2837
2838/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002839 * xmlSchemaFreeTypeList:
2840 * @type: a schema type structure
2841 *
2842 * Deallocate a Schema Type structure.
2843 */
2844static void
2845xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2846{
2847 xmlSchemaTypePtr next;
2848
2849 while (type != NULL) {
2850 next = type->redef;
2851 xmlSchemaFreeType(type);
2852 type = next;
2853 }
2854}
2855
2856/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002857 * xmlSchemaFree:
2858 * @schema: a schema structure
2859 *
2860 * Deallocate a Schema structure.
2861 */
2862void
2863xmlSchemaFree(xmlSchemaPtr schema)
2864{
2865 if (schema == NULL)
2866 return;
2867
Daniel Veillard4255d502002-04-16 15:50:10 +00002868 if (schema->notaDecl != NULL)
2869 xmlHashFree(schema->notaDecl,
2870 (xmlHashDeallocator) xmlSchemaFreeNotation);
2871 if (schema->attrDecl != NULL)
2872 xmlHashFree(schema->attrDecl,
2873 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2874 if (schema->attrgrpDecl != NULL)
2875 xmlHashFree(schema->attrgrpDecl,
2876 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2877 if (schema->elemDecl != NULL)
2878 xmlHashFree(schema->elemDecl,
2879 (xmlHashDeallocator) xmlSchemaFreeElement);
2880 if (schema->typeDecl != NULL)
2881 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002882 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002883 if (schema->groupDecl != NULL)
2884 xmlHashFree(schema->groupDecl,
2885 (xmlHashDeallocator) xmlSchemaFreeType);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002886#ifdef IDC_ENABLED
2887 if (schema->idcDef != NULL)
2888 xmlHashFree(schema->idcDef,
2889 (xmlHashDeallocator) xmlSchemaFreeIDC);
2890#endif
Daniel Veillard1d913862003-11-21 00:28:39 +00002891 if (schema->schemasImports != NULL)
2892 xmlHashFree(schema->schemasImports,
2893 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002894 if (schema->includes != NULL) {
2895 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2896 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002897 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002898 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002899 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002900 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002901 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002902 xmlFree(schema);
2903}
2904
2905/************************************************************************
2906 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002907 * Debug functions *
2908 * *
2909 ************************************************************************/
2910
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002911#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002912
Daniel Veillard4255d502002-04-16 15:50:10 +00002913/**
2914 * xmlSchemaElementDump:
2915 * @elem: an element
2916 * @output: the file output
2917 *
2918 * Dump the element
2919 */
2920static void
2921xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002922 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002923 const xmlChar * namespace ATTRIBUTE_UNUSED,
2924 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002925{
2926 if (elem == NULL)
2927 return;
2928
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002929 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
2930 fprintf(output, "Particle: %s", name);
2931 fprintf(output, ", term element: %s", elem->ref);
2932 if (elem->refNs != NULL)
2933 fprintf(output, " ns %s", elem->refNs);
2934 } else {
2935 fprintf(output, "Element");
2936 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2937 fprintf(output, " (global)");
2938 fprintf(output, ": %s ", elem->name);
2939 if (namespace != NULL)
2940 fprintf(output, "ns %s", namespace);
2941 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002942 fprintf(output, "\n");
2943 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002944 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002945 if (elem->maxOccurs >= UNBOUNDED)
2946 fprintf(output, "max: unbounded\n");
2947 else if (elem->maxOccurs != 1)
2948 fprintf(output, "max: %d\n", elem->maxOccurs);
2949 else
2950 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002951 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002952 /*
2953 * Misc other properties.
2954 */
2955 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
2956 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
2957 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
2958 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
2959 (elem->id != NULL)) {
2960 fprintf(output, " props: ");
2961 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
2962 fprintf(output, "[fixed] ");
2963 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
2964 fprintf(output, "[default] ");
2965 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
2966 fprintf(output, "[abstract] ");
2967 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
2968 fprintf(output, "[nillable] ");
2969 if (elem->id != NULL)
2970 fprintf(output, "[id: '%s'] ", elem->id);
2971 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002972 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002973 /*
2974 * Default/fixed value.
2975 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002976 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002977 fprintf(output, " value: '%s'\n", elem->value);
2978 /*
2979 * Type.
2980 */
2981 if (elem->namedType != NULL) {
2982 fprintf(output, " type: %s ", elem->namedType);
2983 if (elem->namedTypeNs != NULL)
2984 fprintf(output, "ns %s\n", elem->namedTypeNs);
2985 else
2986 fprintf(output, "\n");
2987 }
2988 /*
2989 * Substitution group.
2990 */
2991 if (elem->substGroup != NULL) {
2992 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
2993 if (elem->substGroupNs != NULL)
2994 fprintf(output, "ns %s\n", elem->substGroupNs);
2995 else
2996 fprintf(output, "\n");
2997 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002998}
2999
3000/**
3001 * xmlSchemaAnnotDump:
3002 * @output: the file output
3003 * @annot: a annotation
3004 *
3005 * Dump the annotation
3006 */
3007static void
3008xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3009{
3010 xmlChar *content;
3011
3012 if (annot == NULL)
3013 return;
3014
3015 content = xmlNodeGetContent(annot->content);
3016 if (content != NULL) {
3017 fprintf(output, " Annot: %s\n", content);
3018 xmlFree(content);
3019 } else
3020 fprintf(output, " Annot: empty\n");
3021}
3022
3023/**
3024 * xmlSchemaTypeDump:
3025 * @output: the file output
3026 * @type: a type structure
3027 *
3028 * Dump a SchemaType structure
3029 */
3030static void
3031xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3032{
3033 if (type == NULL) {
3034 fprintf(output, "Type: NULL\n");
3035 return;
3036 }
3037 fprintf(output, "Type: ");
3038 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003039 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003040 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003041 fprintf(output, "no name ");
3042 if (type->targetNamespace != NULL)
3043 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003044 switch (type->type) {
3045 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003046 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003047 break;
3048 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003049 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003050 break;
3051 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003052 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003053 break;
3054 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003055 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003056 break;
3057 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003058 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003059 break;
3060 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003061 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003062 break;
3063 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003064 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003065 break;
3066 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003067 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003068 break;
3069 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003070 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003071 break;
3072 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003073 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003074 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003075 }
3076 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003077 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003078 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003079 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003080 break;
3081 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003082 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003083 break;
3084 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003085 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003086 break;
3087 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003088 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003089 break;
3090 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003091 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003092 break;
3093 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003094 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003095 break;
3096 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003097 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003098 break;
3099 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003100 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003101 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003102 }
3103 fprintf(output, "\n");
3104 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003105 fprintf(output, " min: %d ", type->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003106 if (type->maxOccurs >= UNBOUNDED)
3107 fprintf(output, "max: unbounded\n");
3108 else if (type->maxOccurs != 1)
3109 fprintf(output, "max: %d\n", type->maxOccurs);
3110 else
3111 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003112 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003113 if (type->base != NULL) {
3114 fprintf(output, " base type: %s", type->base);
3115 if (type->baseNs != NULL)
3116 fprintf(output, " ns %s\n", type->baseNs);
3117 else
3118 fprintf(output, "\n");
3119 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003120 if (type->annot != NULL)
3121 xmlSchemaAnnotDump(output, type->annot);
3122 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003123 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00003124
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003125 fprintf(output, " subtypes: ");
3126 while (sub != NULL) {
3127 fprintf(output, "%s ", sub->name);
3128 sub = sub->next;
3129 }
3130 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003131 }
3132
3133}
3134
3135/**
3136 * xmlSchemaDump:
3137 * @output: the file output
3138 * @schema: a schema structure
3139 *
3140 * Dump a Schema structure.
3141 */
3142void
3143xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3144{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003145 if (output == NULL)
3146 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003147 if (schema == NULL) {
3148 fprintf(output, "Schemas: NULL\n");
3149 return;
3150 }
3151 fprintf(output, "Schemas: ");
3152 if (schema->name != NULL)
3153 fprintf(output, "%s, ", schema->name);
3154 else
3155 fprintf(output, "no name, ");
3156 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003157 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003158 else
3159 fprintf(output, "no target namespace");
3160 fprintf(output, "\n");
3161 if (schema->annot != NULL)
3162 xmlSchemaAnnotDump(output, schema->annot);
3163
3164 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3165 output);
3166 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003167 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003168}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003169
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003170#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003171#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003172/**
3173 * xmlSchemaDebugDumpIDCTable:
3174 * @vctxt: the WXS validation context
3175 *
3176 * Displays the current IDC table for debug purposes.
3177 */
3178static void
3179xmlSchemaDebugDumpIDCTable(FILE * output,
3180 const xmlChar *namespaceName,
3181 const xmlChar *localName,
3182 xmlSchemaPSVIIDCBindingPtr bind)
3183{
3184 xmlChar *str = NULL, *value;
3185 xmlSchemaPSVIIDCNodePtr tab;
3186 xmlSchemaPSVIIDCKeyPtr key;
3187 int i, j, res;
3188
3189 fprintf(output, "IDC: TABLES on %s\n",
3190 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
3191 FREE_AND_NULL(str)
3192
3193 if (bind == NULL)
3194 return;
3195 do {
3196 fprintf(output, "IDC: BINDING %s\n",
3197 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
3198 bind->definition->name));
3199 FREE_AND_NULL(str)
3200 for (i = 0; i < bind->nbNodes; i++) {
3201 tab = bind->nodeTable[i];
3202 fprintf(output, " ( ");
3203 for (j = 0; j < bind->definition->nbFields; j++) {
3204 key = tab->keys[j];
3205 if ((key != NULL) && (key->compValue != NULL)) {
3206#ifdef IDC_VALUE_SUPPORT
3207 res = xmlSchemaGetCanonValue(key->compValue, &value);
3208#else
3209 value = xmlStrdup(BAD_CAST "dummy-value");
3210 res = 0;
3211#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003212 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003213 fprintf(output, "\"%s\" ", value);
3214 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003215 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003216 if (res == 0)
3217 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003218 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003219 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003220 else
3221 fprintf(output, "(key missing), ");
3222 }
3223 fprintf(output, ")\n");
3224 }
3225 bind = bind->next;
3226 } while (bind != NULL);
3227}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003228#endif /* DEBUG_IDC */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003229#endif /* IDC_ENABLED */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003230#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003231
3232/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003233 * *
3234 * Utilities *
3235 * *
3236 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003237
Daniel Veillardc0826a72004-08-10 14:17:33 +00003238/**
3239 * xmlSchemaGetPropNode:
3240 * @node: the element node
3241 * @name: the name of the attribute
3242 *
3243 * Seeks an attribute with a name of @name in
3244 * no namespace.
3245 *
3246 * Returns the attribute or NULL if not present.
3247 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003248static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003249xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003250{
3251 xmlAttrPtr prop;
3252
Daniel Veillardc0826a72004-08-10 14:17:33 +00003253 if ((node == NULL) || (name == NULL))
3254 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003255 prop = node->properties;
3256 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003257 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3258 return(prop);
3259 prop = prop->next;
3260 }
3261 return (NULL);
3262}
3263
3264/**
3265 * xmlSchemaGetPropNodeNs:
3266 * @node: the element node
3267 * @uri: the uri
3268 * @name: the name of the attribute
3269 *
3270 * Seeks an attribute with a local name of @name and
3271 * a namespace URI of @uri.
3272 *
3273 * Returns the attribute or NULL if not present.
3274 */
3275static xmlAttrPtr
3276xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3277{
3278 xmlAttrPtr prop;
3279
3280 if ((node == NULL) || (name == NULL))
3281 return(NULL);
3282 prop = node->properties;
3283 while (prop != NULL) {
3284 if ((prop->ns != NULL) &&
3285 xmlStrEqual(prop->name, BAD_CAST name) &&
3286 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003287 return(prop);
3288 prop = prop->next;
3289 }
3290 return (NULL);
3291}
3292
3293static const xmlChar *
3294xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3295{
3296 xmlChar *val;
3297 const xmlChar *ret;
3298
3299 val = xmlNodeGetContent(node);
3300 if (val == NULL)
3301 return(NULL);
3302 ret = xmlDictLookup(ctxt->dict, val, -1);
3303 xmlFree(val);
3304 return(ret);
3305}
3306
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003307/**
3308 * xmlSchemaGetProp:
3309 * @ctxt: the parser context
3310 * @node: the node
3311 * @name: the property name
3312 *
3313 * Read a attribute value and internalize the string
3314 *
3315 * Returns the string or NULL if not present.
3316 */
3317static const xmlChar *
3318xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3319 const char *name)
3320{
3321 xmlChar *val;
3322 const xmlChar *ret;
3323
3324 val = xmlGetProp(node, BAD_CAST name);
3325 if (val == NULL)
3326 return(NULL);
3327 ret = xmlDictLookup(ctxt->dict, val, -1);
3328 xmlFree(val);
3329 return(ret);
3330}
3331
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003332/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003333 * *
3334 * Parsing functions *
3335 * *
3336 ************************************************************************/
3337
3338/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003339 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003340 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003341 * @name: the element name
3342 * @ns: the element namespace
3343 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003344 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003345 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003346 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003347 */
3348static xmlSchemaElementPtr
3349xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003350 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003351{
3352 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003353
3354 if ((name == NULL) || (schema == NULL))
3355 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003356
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003357 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003358 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003359 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003360 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003361 } else
3362 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003363 /*
3364 * This one was removed, since top level element declarations have
3365 * the target namespace specified in targetNamespace of the <schema>
3366 * information element, even if elementFormDefault is "unqualified".
3367 */
3368
3369 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003370 if (xmlStrEqual(namespace, schema->targetNamespace))
3371 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3372 else
3373 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003374 if ((ret != NULL) &&
3375 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003376 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003377 }
William M. Bracke7091952004-05-11 15:09:58 +00003378 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003379
William M. Brack2f2a6632004-08-20 23:09:47 +00003380 /*
3381 * Removed since imported components will be hold by the main schema only.
3382 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003383 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003384 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003385 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003386 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003387 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003388 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003389 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3390 return (ret);
3391 } else
3392 ret = NULL;
3393 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003394 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003395#ifdef DEBUG
3396 if (ret == NULL) {
3397 if (namespace == NULL)
3398 fprintf(stderr, "Unable to lookup type %s", name);
3399 else
3400 fprintf(stderr, "Unable to lookup type %s:%s", name,
3401 namespace);
3402 }
3403#endif
3404 return (ret);
3405}
3406
3407/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003408 * xmlSchemaGetType:
3409 * @schema: the schemas context
3410 * @name: the type name
3411 * @ns: the type namespace
3412 *
3413 * Lookup a type in the schemas or the predefined types
3414 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003415 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003416 */
3417static xmlSchemaTypePtr
3418xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003419 const xmlChar * namespace)
3420{
Daniel Veillard4255d502002-04-16 15:50:10 +00003421 xmlSchemaTypePtr ret;
3422
3423 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003424 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003425 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003426 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003427 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003428 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003429 }
3430 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003431 if (ret != NULL)
3432 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003433 /*
3434 * Removed, since the imported components will be grafted on the
3435 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003436 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003437 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003438 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003439 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003440 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003441 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003442 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3443 return (ret);
3444 } else
3445 ret = NULL;
3446 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003447 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003448#ifdef DEBUG
3449 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003450 if (namespace == NULL)
3451 fprintf(stderr, "Unable to lookup type %s", name);
3452 else
3453 fprintf(stderr, "Unable to lookup type %s:%s", name,
3454 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003455 }
3456#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003457 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003458}
3459
Daniel Veillard3646d642004-06-02 19:19:14 +00003460/**
3461 * xmlSchemaGetAttribute:
3462 * @schema: the context of the schema
3463 * @name: the name of the attribute
3464 * @ns: the target namespace of the attribute
3465 *
3466 * Lookup a an attribute in the schema or imported schemas
3467 *
3468 * Returns the attribute declaration or NULL if not found.
3469 */
3470static xmlSchemaAttributePtr
3471xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
3472 const xmlChar * namespace)
3473{
3474 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003475
3476 if ((name == NULL) || (schema == NULL))
3477 return (NULL);
3478
3479
3480 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
3481 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
3482 return (ret);
3483 else
3484 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003485 /*
3486 * Removed, since imported components will be hold by the main schema only.
3487 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003488 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003489 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003490 else
3491 import = xmlHashLookup(schema->schemasImports, namespace);
3492 if (import != NULL) {
3493 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
3494 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
3495 return (ret);
3496 } else
3497 ret = NULL;
3498 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003499 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003500#ifdef DEBUG
3501 if (ret == NULL) {
3502 if (namespace == NULL)
3503 fprintf(stderr, "Unable to lookup attribute %s", name);
3504 else
3505 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
3506 namespace);
3507 }
3508#endif
3509 return (ret);
3510}
3511
3512/**
3513 * xmlSchemaGetAttributeGroup:
3514 * @schema: the context of the schema
3515 * @name: the name of the attribute group
3516 * @ns: the target namespace of the attribute group
3517 *
3518 * Lookup a an attribute group in the schema or imported schemas
3519 *
3520 * Returns the attribute group definition or NULL if not found.
3521 */
3522static xmlSchemaAttributeGroupPtr
3523xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
3524 const xmlChar * namespace)
3525{
3526 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003527
3528 if ((name == NULL) || (schema == NULL))
3529 return (NULL);
3530
3531
3532 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
3533 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3534 return (ret);
3535 else
3536 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003537 /*
3538 * Removed since imported components will be hold by the main schema only.
3539 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003540 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003541 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003542 else
3543 import = xmlHashLookup(schema->schemasImports, namespace);
3544 if (import != NULL) {
3545 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
3546 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3547 return (ret);
3548 else
3549 ret = NULL;
3550 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003551 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003552#ifdef DEBUG
3553 if (ret == NULL) {
3554 if (namespace == NULL)
3555 fprintf(stderr, "Unable to lookup attribute group %s", name);
3556 else
3557 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
3558 namespace);
3559 }
3560#endif
3561 return (ret);
3562}
3563
3564/**
3565 * xmlSchemaGetGroup:
3566 * @schema: the context of the schema
3567 * @name: the name of the group
3568 * @ns: the target namespace of the group
3569 *
3570 * Lookup a group in the schema or imported schemas
3571 *
3572 * Returns the group definition or NULL if not found.
3573 */
3574static xmlSchemaTypePtr
3575xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
3576 const xmlChar * namespace)
3577{
3578 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003579
3580 if ((name == NULL) || (schema == NULL))
3581 return (NULL);
3582
3583
3584 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
3585 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3586 return (ret);
3587 else
3588 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003589 /*
3590 * Removed since imported components will be hold by the main schema only.
3591 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003592 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003593 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003594 else
3595 import = xmlHashLookup(schema->schemasImports, namespace);
3596 if (import != NULL) {
3597 ret = xmlSchemaGetGroup(import->schema, name, namespace);
3598 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3599 return (ret);
3600 else
3601 ret = NULL;
3602 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003603 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003604#ifdef DEBUG
3605 if (ret == NULL) {
3606 if (namespace == NULL)
3607 fprintf(stderr, "Unable to lookup group %s", name);
3608 else
3609 fprintf(stderr, "Unable to lookup group %s:%s", name,
3610 namespace);
3611 }
3612#endif
3613 return (ret);
3614}
3615
Daniel Veillard4255d502002-04-16 15:50:10 +00003616/************************************************************************
3617 * *
3618 * Parsing functions *
3619 * *
3620 ************************************************************************/
3621
3622#define IS_BLANK_NODE(n) \
3623 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
3624
3625/**
3626 * xmlSchemaIsBlank:
3627 * @str: a string
3628 *
3629 * Check if a string is ignorable
3630 *
3631 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
3632 */
3633static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003634xmlSchemaIsBlank(xmlChar * str)
3635{
Daniel Veillard4255d502002-04-16 15:50:10 +00003636 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003637 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003638 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00003639 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003640 return (0);
3641 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003642 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003643 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003644}
3645
3646/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003647 * xmlSchemaAddAssembledItem:
3648 * @ctxt: a schema parser context
3649 * @schema: the schema being built
3650 * @item: the item
3651 *
3652 * Add a item to the schema's list of current items.
3653 * This is used if the schema was already constructed and
3654 * new schemata need to be added to it.
3655 * *WARNING* this interface is highly subject to change.
3656 *
3657 * Returns 0 if suceeds and -1 if an internal error occurs.
3658 */
3659static int
3660xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
3661 xmlSchemaTypePtr item)
3662{
3663 static int growSize = 100;
3664 xmlSchemaAssemblePtr ass;
3665
3666 ass = ctxt->assemble;
3667 if (ass->sizeItems < 0) {
3668 /* If disabled. */
3669 return (0);
3670 }
3671 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003672 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003673 if (ass->items == NULL) {
3674 xmlSchemaPErrMemory(ctxt,
3675 "allocating new item buffer", NULL);
3676 return (-1);
3677 }
3678 ass->sizeItems = growSize;
3679 } else if (ass->sizeItems <= ass->nbItems) {
3680 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003681 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003682 ass->sizeItems * sizeof(xmlSchemaTypePtr));
3683 if (ass->items == NULL) {
3684 xmlSchemaPErrMemory(ctxt,
3685 "growing item buffer", NULL);
3686 ass->sizeItems = 0;
3687 return (-1);
3688 }
3689 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003690 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003691 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
3692 return (0);
3693}
3694
3695/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003696 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003697 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003698 * @schema: the schema being built
3699 * @name: the item name
3700 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003701 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003702 * *WARNING* this interface is highly subject to change
3703 *
3704 * Returns the new struture or NULL in case of error
3705 */
3706static xmlSchemaNotationPtr
3707xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003708 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003709{
3710 xmlSchemaNotationPtr ret = NULL;
3711 int val;
3712
3713 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3714 return (NULL);
3715
3716 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003717 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003718 if (schema->notaDecl == NULL)
3719 return (NULL);
3720
3721 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
3722 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003723 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003724 return (NULL);
3725 }
3726 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003727 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003728 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
3729 ret);
3730 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003731 /*
3732 * TODO: This should never happen, since a unique name will be computed.
3733 * If it fails, then an other internal error must have occured.
3734 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003735 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3736 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003737 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003738 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003739 xmlFree(ret);
3740 return (NULL);
3741 }
3742 return (ret);
3743}
3744
3745
3746/**
3747 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003748 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003749 * @schema: the schema being built
3750 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003751 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003752 *
3753 * Add an XML schema Attrribute declaration
3754 * *WARNING* this interface is highly subject to change
3755 *
3756 * Returns the new struture or NULL in case of error
3757 */
3758static xmlSchemaAttributePtr
3759xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003760 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003761 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003762{
3763 xmlSchemaAttributePtr ret = NULL;
3764 int val;
3765
3766 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3767 return (NULL);
3768
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003769#ifdef DEBUG
3770 fprintf(stderr, "Adding attribute %s\n", name);
3771 if (namespace != NULL)
3772 fprintf(stderr, " target namespace %s\n", namespace);
3773#endif
3774
Daniel Veillard4255d502002-04-16 15:50:10 +00003775 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003776 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003777 if (schema->attrDecl == NULL)
3778 return (NULL);
3779
3780 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3781 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003782 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003783 return (NULL);
3784 }
3785 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003786 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003787 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00003788 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003789 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003790 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003791 if (topLevel) {
3792 xmlSchemaPCustomErr(ctxt,
3793 XML_SCHEMAP_REDEFINED_ATTR,
3794 NULL, NULL, node,
3795 "A global attribute declaration with the name '%s' does "
3796 "already exist", name);
3797 xmlFree(ret);
3798 return (NULL);
3799 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003800 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003801 /*
3802 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
3803 * in the scenario:
3804 * 1. multiple top-level complex types have different target
3805 * namespaces but have the SAME NAME; this can happen if
3806 * schemata are imported
3807 * 2. those complex types contain attributes with an equal name
3808 * 3. those attributes are in no namespace
3809 * We will compute a new context string.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003810 */
3811 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003812 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00003813 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003814
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003815 if (val != 0) {
3816 xmlSchemaPCustomErr(ctxt,
3817 XML_SCHEMAP_INTERNAL,
3818 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003819 "Internal error: xmlSchemaAddAttribute, "
3820 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003821 "could not be added to the hash.", name);
3822 xmlFree(ret);
3823 return (NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003824 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003825 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003826 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003827 if (ctxt->assemble != NULL)
3828 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003829 return (ret);
3830}
3831
3832/**
3833 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003834 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003835 * @schema: the schema being built
3836 * @name: the item name
3837 *
3838 * Add an XML schema Attrribute Group declaration
3839 *
3840 * Returns the new struture or NULL in case of error
3841 */
3842static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003843xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003844 xmlSchemaPtr schema, const xmlChar * name,
3845 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003846{
3847 xmlSchemaAttributeGroupPtr ret = NULL;
3848 int val;
3849
3850 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3851 return (NULL);
3852
3853 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003854 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003855 if (schema->attrgrpDecl == NULL)
3856 return (NULL);
3857
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003858 ret =
3859 (xmlSchemaAttributeGroupPtr)
3860 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003861 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003862 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003863 return (NULL);
3864 }
3865 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003866 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003867 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003868 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003869 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003870 xmlSchemaPCustomErr(ctxt,
3871 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3872 NULL, NULL, node,
3873 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003874 xmlFree(ret);
3875 return (NULL);
3876 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003877 if (ctxt->assemble != NULL)
3878 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003879 return (ret);
3880}
3881
3882/**
3883 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003884 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003885 * @schema: the schema being built
3886 * @name: the type name
3887 * @namespace: the type namespace
3888 *
3889 * Add an XML schema Element declaration
3890 * *WARNING* this interface is highly subject to change
3891 *
3892 * Returns the new struture or NULL in case of error
3893 */
3894static xmlSchemaElementPtr
3895xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003896 const xmlChar * name, const xmlChar * namespace,
3897 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003898{
3899 xmlSchemaElementPtr ret = NULL;
3900 int val;
3901
3902 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3903 return (NULL);
3904
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003905#ifdef DEBUG
3906 fprintf(stderr, "Adding element %s\n", name);
3907 if (namespace != NULL)
3908 fprintf(stderr, " target namespace %s\n", namespace);
3909#endif
3910
Daniel Veillard4255d502002-04-16 15:50:10 +00003911 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003912 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003913 if (schema->elemDecl == NULL)
3914 return (NULL);
3915
3916 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3917 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003918 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003919 return (NULL);
3920 }
3921 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003922 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003923 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003924 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003925 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003926 if (topLevel) {
3927 xmlSchemaPCustomErr(ctxt,
3928 XML_SCHEMAP_REDEFINED_ELEMENT,
3929 NULL, NULL, node,
3930 "A global element declaration with the name '%s' does "
3931 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003932 xmlFree(ret);
3933 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003934 } else {
3935 char buf[30];
3936
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003937 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003938 val = xmlHashAddEntry3(schema->elemDecl, name,
3939 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003940 if (val != 0) {
3941 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003942 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003943 NULL, NULL, node,
3944 "Internal error: xmlSchemaAddElement, "
3945 "a dublicate element declaration with the name '%s' "
3946 "could not be added to the hash.", name);
3947 xmlFree(ret);
3948 return (NULL);
3949 }
3950 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003951
Daniel Veillard4255d502002-04-16 15:50:10 +00003952 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003953 if (ctxt->assemble != NULL)
3954 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003955 return (ret);
3956}
3957
3958/**
3959 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003960 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003961 * @schema: the schema being built
3962 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003963 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003964 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003965 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003966 * *WARNING* this interface is highly subject to change
3967 *
3968 * Returns the new struture or NULL in case of error
3969 */
3970static xmlSchemaTypePtr
3971xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003972 const xmlChar * name, const xmlChar * namespace,
3973 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003974{
3975 xmlSchemaTypePtr ret = NULL;
3976 int val;
3977
3978 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3979 return (NULL);
3980
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003981#ifdef DEBUG
3982 fprintf(stderr, "Adding type %s\n", name);
3983 if (namespace != NULL)
3984 fprintf(stderr, " target namespace %s\n", namespace);
3985#endif
3986
Daniel Veillard4255d502002-04-16 15:50:10 +00003987 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003988 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003989 if (schema->typeDecl == NULL)
3990 return (NULL);
3991
3992 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3993 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003994 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003995 return (NULL);
3996 }
3997 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003998 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003999 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004000 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004001 if (val != 0) {
4002 if (ctxt->includes == 0) {
4003 xmlSchemaPCustomErr(ctxt,
4004 XML_SCHEMAP_REDEFINED_TYPE,
4005 NULL, NULL, node,
4006 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004007 xmlFree(ret);
4008 return (NULL);
4009 } else {
4010 xmlSchemaTypePtr prev;
4011
4012 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4013 if (prev == NULL) {
4014 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004015 XML_ERR_INTERNAL_ERROR,
4016 "Internal error: xmlSchemaAddType, on type "
4017 "'%s'.\n",
4018 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004019 xmlFree(ret);
4020 return (NULL);
4021 }
4022 ret->redef = prev->redef;
4023 prev->redef = ret;
4024 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004025 }
4026 ret->minOccurs = 1;
4027 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004028 ret->attributeUses = NULL;
4029 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004030 if (ctxt->assemble != NULL)
4031 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004032 return (ret);
4033}
4034
4035/**
4036 * xmlSchemaAddGroup:
4037 * @ctxt: a schema validation context
4038 * @schema: the schema being built
4039 * @name: the group name
4040 *
4041 * Add an XML schema Group definition
4042 *
4043 * Returns the new struture or NULL in case of error
4044 */
4045static xmlSchemaTypePtr
4046xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004047 const xmlChar *name, const xmlChar *namespaceName,
4048 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004049{
4050 xmlSchemaTypePtr ret = NULL;
4051 int val;
4052
4053 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4054 return (NULL);
4055
4056 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004057 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004058 if (schema->groupDecl == NULL)
4059 return (NULL);
4060
4061 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4062 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004063 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004064 return (NULL);
4065 }
4066 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004067 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004068 val =
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004069 xmlHashAddEntry2(schema->groupDecl, name, namespaceName,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004070 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004071 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004072 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004073 XML_SCHEMAP_REDEFINED_GROUP,
4074 NULL, NULL, node,
4075 "A global model group definition with the name '%s' does already "
4076 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004077 xmlFree(ret);
4078 return (NULL);
4079 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004080 ret->targetNamespace = namespaceName;
Daniel Veillard4255d502002-04-16 15:50:10 +00004081 ret->minOccurs = 1;
4082 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004083 if (ctxt->assemble != NULL)
4084 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004085 return (ret);
4086}
4087
Daniel Veillard3646d642004-06-02 19:19:14 +00004088/**
4089 * xmlSchemaNewWildcardNs:
4090 * @ctxt: a schema validation context
4091 *
4092 * Creates a new wildcard namespace constraint.
4093 *
4094 * Returns the new struture or NULL in case of error
4095 */
4096static xmlSchemaWildcardNsPtr
4097xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4098{
4099 xmlSchemaWildcardNsPtr ret;
4100
4101 ret = (xmlSchemaWildcardNsPtr)
4102 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4103 if (ret == NULL) {
4104 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
4105 return (NULL);
4106 }
4107 ret->value = NULL;
4108 ret->next = NULL;
4109 return (ret);
4110}
4111
4112/**
4113 * xmlSchemaAddWildcard:
4114 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00004115 * Adds a wildcard. It corresponds to a
4116 * xsd:anyAttribute and is used as storage for namespace
4117 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004118 *
4119 * Returns the new struture or NULL in case of error
4120 */
4121static xmlSchemaWildcardPtr
4122xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
4123{
4124 xmlSchemaWildcardPtr ret = NULL;
4125
4126 if (ctxt == NULL)
4127 return (NULL);
4128
4129 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4130 if (ret == NULL) {
4131 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4132 return (NULL);
4133 }
4134 memset(ret, 0, sizeof(xmlSchemaWildcard));
4135 ret->minOccurs = 1;
4136 ret->maxOccurs = 1;
4137
4138 return (ret);
4139}
4140
Daniel Veillard4255d502002-04-16 15:50:10 +00004141/************************************************************************
4142 * *
4143 * Utilities for parsing *
4144 * *
4145 ************************************************************************/
4146
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004147#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004148/**
4149 * xmlGetQNameProp:
4150 * @ctxt: a schema validation context
4151 * @node: a subtree containing XML Schema informations
4152 * @name: the attribute name
4153 * @namespace: the result namespace if any
4154 *
4155 * Extract a QName Attribute value
4156 *
4157 * Returns the NCName or NULL if not found, and also update @namespace
4158 * with the namespace URI
4159 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004160static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004161xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004162 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004163{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004164 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004165 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004166 const xmlChar *ret, *prefix;
4167 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004168 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004169
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004170 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004171 attr = xmlSchemaGetPropNode(node, name);
4172 if (attr == NULL)
4173 return (NULL);
4174 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004175
Daniel Veillard4255d502002-04-16 15:50:10 +00004176 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004177 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004178
Daniel Veillardba0153a2004-04-01 10:42:31 +00004179 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004180 ns = xmlSearchNs(node->doc, node, 0);
4181 if (ns) {
4182 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4183 return (val);
4184 }
4185 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004186 ret = xmlSplitQName3(val, &len);
4187 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004188 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004189 }
4190 ret = xmlDictLookup(ctxt->dict, ret, -1);
4191 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004192
4193 ns = xmlSearchNs(node->doc, node, prefix);
4194 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004195 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4196 NULL, NULL, (xmlNodePtr) attr,
4197 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004198 "The QName value '%s' has no corresponding namespace "
4199 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004200 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004201 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004202 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004203 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004204}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004205#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004206
4207/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004208 * xmlSchemaPValAttrNodeQNameValue:
4209 * @ctxt: a schema parser context
4210 * @schema: the schema context
4211 * @ownerDes: the designation of the parent element
4212 * @ownerItem: the parent as a schema object
4213 * @value: the QName value
4214 * @local: the resulting local part if found, the attribute value otherwise
4215 * @uri: the resulting namespace URI if found
4216 *
4217 * Extracts the local name and the URI of a QName value and validates it.
4218 * This one is intended to be used on attribute values that
4219 * should resolve to schema components.
4220 *
4221 * Returns 0, in case the QName is valid, a positive error code
4222 * if not valid and -1 if an internal error occurs.
4223 */
4224static int
4225xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
4226 xmlSchemaPtr schema,
4227 xmlChar **ownerDes,
4228 xmlSchemaTypePtr ownerItem,
4229 xmlAttrPtr attr,
4230 const xmlChar *value,
4231 const xmlChar **uri,
4232 const xmlChar **prefix,
4233 const xmlChar **local)
4234{
4235 const xmlChar *pref;
4236 xmlNsPtr ns;
4237 int len, ret;
4238
4239 *uri = NULL;
4240 *local = NULL;
4241 if (prefix != 0)
4242 *prefix = NULL;
4243 ret = xmlValidateQName(value, 1);
4244 if (ret > 0) {
4245 xmlSchemaPSimpleTypeErr(ctxt,
4246 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4247 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004248 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4249 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004250 NULL, NULL, NULL);
4251 *local = value;
4252 return (ctxt->err);
4253 } else if (ret < 0)
4254 return (-1);
4255
4256 if (!strchr((char *) value, ':')) {
4257 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4258 if (ns)
4259 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4260 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4261 /*
4262 * This one takes care of included schemas with no
4263 * target namespace.
4264 */
4265 *uri = schema->targetNamespace;
4266 }
4267 *local = value;
4268 return (0);
4269 }
4270 /*
4271 * At this point xmlSplitQName3 has to return a local name.
4272 */
4273 *local = xmlSplitQName3(value, &len);
4274 *local = xmlDictLookup(ctxt->dict, *local, -1);
4275 pref = xmlDictLookup(ctxt->dict, value, len);
4276 if (prefix != 0)
4277 *prefix = pref;
4278 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4279 if (ns == NULL) {
4280 xmlSchemaPSimpleTypeErr(ctxt,
4281 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4282 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004283 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
4284 "The QName value '%s' has no corresponding namespace "
4285 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004286 return (ctxt->err);
4287 } else {
4288 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4289 }
4290 return (0);
4291}
4292
4293/**
4294 * xmlSchemaPValAttrNodeQName:
4295 * @ctxt: a schema parser context
4296 * @schema: the schema context
4297 * @ownerDes: the designation of the owner element
4298 * @ownerItem: the owner as a schema object
4299 * @attr: the attribute node
4300 * @local: the resulting local part if found, the attribute value otherwise
4301 * @uri: the resulting namespace URI if found
4302 *
4303 * Extracts and validates the QName of an attribute value.
4304 * This one is intended to be used on attribute values that
4305 * should resolve to schema components.
4306 *
4307 * Returns 0, in case the QName is valid, a positive error code
4308 * if not valid and -1 if an internal error occurs.
4309 */
4310static int
4311xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
4312 xmlSchemaPtr schema,
4313 xmlChar **ownerDes,
4314 xmlSchemaTypePtr ownerItem,
4315 xmlAttrPtr attr,
4316 const xmlChar **uri,
4317 const xmlChar **prefix,
4318 const xmlChar **local)
4319{
4320 const xmlChar *value;
4321
4322 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4323 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
4324 ownerDes, ownerItem, attr, value, uri, prefix, local));
4325}
4326
4327/**
4328 * xmlSchemaPValAttrQName:
4329 * @ctxt: a schema parser context
4330 * @schema: the schema context
4331 * @ownerDes: the designation of the parent element
4332 * @ownerItem: the owner as a schema object
4333 * @ownerElem: the parent node of the attribute
4334 * @name: the name of the attribute
4335 * @local: the resulting local part if found, the attribute value otherwise
4336 * @uri: the resulting namespace URI if found
4337 *
4338 * Extracts and validates the QName of an attribute value.
4339 *
4340 * Returns 0, in case the QName is valid, a positive error code
4341 * if not valid and -1 if an internal error occurs.
4342 */
4343static int
4344xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
4345 xmlSchemaPtr schema,
4346 xmlChar **ownerDes,
4347 xmlSchemaTypePtr ownerItem,
4348 xmlNodePtr ownerElem,
4349 const char *name,
4350 const xmlChar **uri,
4351 const xmlChar **prefix,
4352 const xmlChar **local)
4353{
4354 xmlAttrPtr attr;
4355
4356 attr = xmlSchemaGetPropNode(ownerElem, name);
4357 if (attr == NULL) {
4358 *local = NULL;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004359 if (prefix != NULL)
4360 *prefix = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004361 *uri = NULL;
4362 return (0);
4363 }
4364 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
4365 ownerDes, ownerItem, attr, uri, prefix, local));
4366}
4367
4368/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004369 * xmlSchemaPValAttrID:
4370 * @ctxt: a schema parser context
4371 * @schema: the schema context
4372 * @ownerDes: the designation of the parent element
4373 * @ownerItem: the owner as a schema object
4374 * @ownerElem: the parent node of the attribute
4375 * @name: the name of the attribute
4376 *
4377 * Extracts and validates the ID of an attribute value.
4378 *
4379 * Returns 0, in case the ID is valid, a positive error code
4380 * if not valid and -1 if an internal error occurs.
4381 */
4382static int
4383xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
4384 xmlChar **ownerDes,
4385 xmlSchemaTypePtr ownerItem,
4386 xmlNodePtr ownerElem,
4387 const xmlChar *name)
4388{
4389 int ret;
4390 xmlChar *value;
4391 xmlAttrPtr attr;
4392
4393 value = xmlGetNoNsProp(ownerElem, name);
4394 if (value == NULL)
4395 return (0);
4396
4397 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
4398 if (attr == NULL)
4399 return (-1);
4400
4401 ret = xmlValidateNCName(BAD_CAST value, 1);
4402 if (ret == 0) {
4403 /*
4404 * NOTE: the IDness might have already be declared in the DTD
4405 */
4406 if (attr->atype != XML_ATTRIBUTE_ID) {
4407 xmlIDPtr res;
4408 xmlChar *strip;
4409
4410 /*
4411 * TODO: Use xmlSchemaStrip here; it's not exported at this
4412 * moment.
4413 */
4414 strip = xmlSchemaCollapseString(BAD_CAST value);
4415 if (strip != NULL)
4416 value = strip;
4417 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
4418 if (res == NULL) {
4419 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
4420 xmlSchemaPSimpleTypeErr(ctxt,
4421 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4422 ownerDes, ownerItem, (xmlNodePtr) attr,
4423 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00004424 NULL, NULL, "The ID '%s' is already defined",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004425 BAD_CAST value, NULL);
4426 } else
4427 attr->atype = XML_ATTRIBUTE_ID;
4428 if (strip != NULL)
4429 xmlFree(strip);
4430 }
4431 } else if (ret > 0) {
4432 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
4433 xmlSchemaPSimpleTypeErr(ctxt,
4434 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4435 ownerDes, ownerItem, (xmlNodePtr) attr,
4436 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
4437 NULL, BAD_CAST value, NULL, NULL, NULL);
4438 }
4439 xmlFree(value);
4440
4441 return (ret);
4442}
4443
4444/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004445 * xmlGetMaxOccurs:
4446 * @ctxt: a schema validation context
4447 * @node: a subtree containing XML Schema informations
4448 *
4449 * Get the maxOccurs property
4450 *
4451 * Returns the default if not found, or the value
4452 */
4453static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004454xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4455 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004456{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004457 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004458 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004459 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004460
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004461 attr = xmlSchemaGetPropNode(node, "maxOccurs");
4462 if (attr == NULL)
4463 return (def);
4464 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004465
4466 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004467 if (max != UNBOUNDED) {
4468 xmlSchemaPSimpleTypeErr(ctxt,
4469 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4470 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4471 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4472 val, NULL, NULL, NULL);
4473 return (def);
4474 } else
4475 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00004476 }
4477
4478 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004479 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004480 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004481 if (*cur == 0) {
4482 xmlSchemaPSimpleTypeErr(ctxt,
4483 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4484 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4485 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4486 val, NULL, NULL, NULL);
4487 return (def);
4488 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004489 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004490 ret = ret * 10 + (*cur - '0');
4491 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004492 }
William M. Brack76e95df2003-10-18 16:20:14 +00004493 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004494 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004495 /*
4496 * TODO: Restrict the maximal value to Integer.
4497 */
4498 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4499 xmlSchemaPSimpleTypeErr(ctxt,
4500 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4501 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4502 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4503 val, NULL, NULL, NULL);
4504 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004505 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004506 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004507}
4508
4509/**
4510 * xmlGetMinOccurs:
4511 * @ctxt: a schema validation context
4512 * @node: a subtree containing XML Schema informations
4513 *
4514 * Get the minOccurs property
4515 *
4516 * Returns the default if not found, or the value
4517 */
4518static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004519xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4520 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004521{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004522 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004523 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004524 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004525
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004526 attr = xmlSchemaGetPropNode(node, "minOccurs");
4527 if (attr == NULL)
4528 return (def);
4529 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004530 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004531 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004532 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004533 if (*cur == 0) {
4534 xmlSchemaPSimpleTypeErr(ctxt,
4535 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4536 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4537 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4538 val, NULL, NULL, NULL);
4539 return (def);
4540 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004541 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004542 ret = ret * 10 + (*cur - '0');
4543 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004544 }
William M. Brack76e95df2003-10-18 16:20:14 +00004545 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004546 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004547 /*
4548 * TODO: Restrict the maximal value to Integer.
4549 */
4550 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4551 xmlSchemaPSimpleTypeErr(ctxt,
4552 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4553 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4554 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4555 val, NULL, NULL, NULL);
4556 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004557 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004558 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004559}
4560
4561/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004562 * xmlSchemaPGetBoolNodeValue:
4563 * @ctxt: a schema validation context
4564 * @ownerDes: owner designation
4565 * @ownerItem: the owner as a schema item
4566 * @node: the node holding the value
4567 *
4568 * Converts a boolean string value into 1 or 0.
4569 *
4570 * Returns 0 or 1.
4571 */
4572static int
4573xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
4574 xmlChar **ownerDes,
4575 xmlSchemaTypePtr ownerItem,
4576 xmlNodePtr node)
4577{
4578 xmlChar *value = NULL;
4579 int res = 0;
4580
4581 value = xmlNodeGetContent(node);
4582 /*
4583 * 3.2.2.1 Lexical representation
4584 * An instance of a datatype that is defined as ·boolean·
4585 * can have the following legal literals {true, false, 1, 0}.
4586 */
4587 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
4588 res = 1;
4589 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
4590 res = 0;
4591 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
4592 res = 1;
4593 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
4594 res = 0;
4595 else {
4596 xmlSchemaPSimpleTypeErr(ctxt,
4597 XML_SCHEMAP_INVALID_BOOLEAN,
4598 ownerDes, ownerItem, node,
4599 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4600 "(1 | 0 | true | false)", BAD_CAST value,
4601 NULL, NULL, NULL);
4602 }
4603 if (value != NULL)
4604 xmlFree(value);
4605 return (res);
4606}
4607
4608/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004609 * xmlGetBooleanProp:
4610 * @ctxt: a schema validation context
4611 * @node: a subtree containing XML Schema informations
4612 * @name: the attribute name
4613 * @def: the default value
4614 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004615 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00004616 *
4617 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004618 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00004619 */
4620static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004621xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
4622 xmlChar **ownerDes,
4623 xmlSchemaTypePtr ownerItem,
4624 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004625 const char *name, int def)
4626{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004627 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004628
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004629 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004630 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004631 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004632 /*
4633 * 3.2.2.1 Lexical representation
4634 * An instance of a datatype that is defined as ·boolean·
4635 * can have the following legal literals {true, false, 1, 0}.
4636 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004637 if (xmlStrEqual(val, BAD_CAST "true"))
4638 def = 1;
4639 else if (xmlStrEqual(val, BAD_CAST "false"))
4640 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004641 else if (xmlStrEqual(val, BAD_CAST "1"))
4642 def = 1;
4643 else if (xmlStrEqual(val, BAD_CAST "0"))
4644 def = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004645 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004646 xmlSchemaPSimpleTypeErr(ctxt,
4647 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004648 ownerDes, ownerItem,
4649 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
William M. Brack2f2a6632004-08-20 23:09:47 +00004650 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4651 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004652 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004653 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004654}
4655
4656/************************************************************************
4657 * *
4658 * Shema extraction from an Infoset *
4659 * *
4660 ************************************************************************/
4661static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
4662 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004663 xmlNodePtr node,
4664 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004665static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
4666 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004667 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004668 xmlNodePtr node,
4669 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004670static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
4671 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004672 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004673 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004674static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
4675 xmlSchemaPtr schema,
4676 xmlNodePtr node);
4677static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
4678 xmlSchemaPtr schema,
4679 xmlNodePtr node);
4680static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
4681 ctxt,
4682 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004683 xmlNodePtr node,
4684 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004685static xmlSchemaAttributeGroupPtr
4686xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004687 xmlSchemaPtr schema, xmlNodePtr node,
4688 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004689static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
4690 xmlSchemaPtr schema,
4691 xmlNodePtr node);
4692static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
4693 xmlSchemaPtr schema,
4694 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00004695static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004696xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4697 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004698
4699/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004700 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004701 *
4702 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00004703 * @ownerDes: the designation of the parent element
4704 * @ownerItem: the schema object owner if existent
4705 * @attr: the schema attribute node being validated
4706 * @value: the value
4707 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00004708 *
4709 * Validates a value against the given built-in type.
4710 * This one is intended to be used internally for validation
4711 * of schema attribute values during parsing of the schema.
4712 *
4713 * Returns 0 if the value is valid, a positive error code
4714 * number otherwise and -1 in case of an internal or API error.
4715 */
4716static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004717xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
4718 xmlChar **ownerDes,
4719 xmlSchemaTypePtr ownerItem,
4720 xmlAttrPtr attr,
4721 const xmlChar *value,
4722 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004723{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004724
Daniel Veillardc0826a72004-08-10 14:17:33 +00004725 int ret = 0;
4726
4727 /*
4728 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
4729 * one is really meant to be used internally, so better not.
4730 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004731 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004732 return (-1);
4733 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4734 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004735 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004736 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004737 "type '%s' is not a built-in type.\n",
4738 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004739 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004740 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004741 switch (type->builtInType) {
4742 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004743 case XML_SCHEMAS_QNAME:
4744 case XML_SCHEMAS_ANYURI:
4745 case XML_SCHEMAS_TOKEN:
4746 case XML_SCHEMAS_LANGUAGE:
4747 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
4748 break;
4749
4750 /*
4751 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004752 ret = xmlValidateNCName(value, 1);
4753 break;
4754 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00004755 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004756 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004757 "Internal error: xmlSchemaPvalueAttrNode, use "
4758 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
4759 "for extracting QName valueues instead.\n",
4760 NULL, NULL);
4761 return (-1);
4762 case XML_SCHEMAS_ANYURI:
4763 if (value != NULL) {
4764 xmlURIPtr uri = xmlParseURI((const char *) value);
4765 if (uri == NULL)
4766 ret = 1;
4767 else
4768 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004769 }
4770 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004771 case XML_SCHEMAS_TOKEN: {
4772 const xmlChar *cur = value;
4773
4774 if (IS_BLANK_CH(*cur)) {
4775 ret = 1;
4776 } else while (*cur != 0) {
4777 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
4778 ret = 1;
4779 break;
4780 } else if (*cur == ' ') {
4781 cur++;
4782 if ((*cur == 0) || (*cur == ' ')) {
4783 ret = 1;
4784 break;
4785 }
4786 } else {
4787 cur++;
4788 }
4789 }
4790 }
4791 break;
4792 case XML_SCHEMAS_LANGUAGE:
4793 if (xmlCheckLanguageID(value) != 1)
4794 ret = 1;
4795 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004796 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004797 default: {
4798 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004799 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004800 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004801 "valueidation using the type '%s' is not implemented "
4802 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00004803 type->name, NULL);
4804 return (-1);
4805 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004806 }
4807 /*
4808 * TODO: Should we use the S4S error codes instead?
4809 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004810 if (ret < 0) {
4811 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
4812 XML_SCHEMAP_INTERNAL,
4813 "Internal error: xmlSchemaPValAttrNodeValue, "
4814 "failed to validate a schema attribute value.\n",
4815 NULL, NULL);
4816 return (-1);
4817 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004818 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
4819 xmlSchemaPSimpleTypeErr(ctxt,
4820 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
4821 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004822 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004823 NULL, NULL, NULL);
4824 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
4825 } else {
4826 xmlSchemaPSimpleTypeErr(ctxt,
4827 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
4828 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004829 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004830 NULL, NULL, NULL);
4831 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
4832 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004833 }
4834 return (ret);
4835}
4836
4837/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004838 * xmlSchemaPValAttrNode:
4839 *
4840 * @ctxt: a schema parser context
4841 * @ownerDes: the designation of the parent element
4842 * @ownerItem: the schema object owner if existent
4843 * @attr: the schema attribute node being validated
4844 * @type: the built-in type to be validated against
4845 * @value: the resulting value if any
4846 *
4847 * Extracts and validates a value against the given built-in type.
4848 * This one is intended to be used internally for validation
4849 * of schema attribute values during parsing of the schema.
4850 *
4851 * Returns 0 if the value is valid, a positive error code
4852 * number otherwise and -1 in case of an internal or API error.
4853 */
4854static int
4855xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4856 xmlChar **ownerDes,
4857 xmlSchemaTypePtr ownerItem,
4858 xmlAttrPtr attr,
4859 xmlSchemaTypePtr type,
4860 const xmlChar **value)
4861{
4862 const xmlChar *val;
4863
4864 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4865 return (-1);
4866
4867 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4868 if (value != NULL)
4869 *value = val;
4870
4871 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4872 val, type));
4873}
4874
4875/**
4876 * xmlSchemaPValAttr:
4877 *
4878 * @ctxt: a schema parser context
4879 * @node: the element node of the attribute
4880 * @ownerDes: the designation of the parent element
4881 * @ownerItem: the schema object owner if existent
4882 * @ownerElem: the owner element node
4883 * @name: the name of the schema attribute node
4884 * @type: the built-in type to be validated against
4885 * @value: the resulting value if any
4886 *
4887 * Extracts and validates a value against the given built-in type.
4888 * This one is intended to be used internally for validation
4889 * of schema attribute values during parsing of the schema.
4890 *
4891 * Returns 0 if the value is valid, a positive error code
4892 * number otherwise and -1 in case of an internal or API error.
4893 */
4894static int
4895xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4896 xmlChar **ownerDes,
4897 xmlSchemaTypePtr ownerItem,
4898 xmlNodePtr ownerElem,
4899 const char *name,
4900 xmlSchemaTypePtr type,
4901 const xmlChar **value)
4902{
4903 xmlAttrPtr attr;
4904
4905 if ((ctxt == NULL) || (type == NULL)) {
4906 if (value != NULL)
4907 *value = NULL;
4908 return (-1);
4909 }
4910 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4911 if (value != NULL)
4912 *value = NULL;
4913 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004914 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004915 "Internal error: xmlSchemaPValAttr, the given "
4916 "type '%s' is not a built-in type.\n",
4917 type->name, NULL);
4918 return (-1);
4919 }
4920 attr = xmlSchemaGetPropNode(ownerElem, name);
4921 if (attr == NULL) {
4922 if (value != NULL)
4923 *value = NULL;
4924 return (0);
4925 }
4926 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4927 type, value));
4928}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004929
4930static int
4931xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
4932 xmlSchemaPtr schema,
4933 xmlNodePtr node,
4934 xmlSchemaTypePtr item,
4935 const xmlChar *namespaceName)
4936{
4937 if (xmlStrEqual(schema->targetNamespace, namespaceName))
4938 return (1);
4939 if (pctxt->localImports != NULL) {
4940 int i;
4941 for (i = 0; i < pctxt->nbLocalImports; i++)
4942 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
4943 return (1);
4944 }
4945 if (namespaceName == NULL)
4946 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
4947 NULL, item, node, "References from this schema to components in no "
4948 "namespace are not valid, since not indicated by an import "
4949 "statement", NULL);
4950 else
4951 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
4952 NULL, item, node, "References from this schema to components in the "
4953 "namespace '%s' are not valid, since not indicated by an import "
4954 "statement", namespaceName);
4955 return (0);
4956}
4957
Daniel Veillardc0826a72004-08-10 14:17:33 +00004958/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004959 * xmlSchemaParseAttrDecls:
4960 * @ctxt: a schema validation context
4961 * @schema: the schema being built
4962 * @node: a subtree containing XML Schema informations
4963 * @type: the hosting type
4964 *
4965 * parse a XML schema attrDecls declaration corresponding to
4966 * <!ENTITY % attrDecls
4967 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4968 */
4969static xmlNodePtr
4970xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4971 xmlNodePtr child, xmlSchemaTypePtr type)
4972{
4973 xmlSchemaAttributePtr lastattr, attr;
4974
4975 lastattr = NULL;
4976 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004977 (IS_SCHEMA(child, "attributeGroup"))) {
4978 attr = NULL;
4979 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004980 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004981 } else if (IS_SCHEMA(child, "attributeGroup")) {
4982 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004983 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004984 }
4985 if (attr != NULL) {
4986 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004987 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4988 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4989 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004990 type->attributes = attr;
4991 lastattr = attr;
4992 } else {
4993 lastattr->next = attr;
4994 lastattr = attr;
4995 }
4996 }
4997 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004998 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004999 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005000}
5001
5002/**
5003 * xmlSchemaParseAnnotation:
5004 * @ctxt: a schema validation context
5005 * @schema: the schema being built
5006 * @node: a subtree containing XML Schema informations
5007 *
5008 * parse a XML schema Attrribute declaration
5009 * *WARNING* this interface is highly subject to change
5010 *
William M. Bracke7091952004-05-11 15:09:58 +00005011 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005012 * 1 in case of success.
5013 */
5014static xmlSchemaAnnotPtr
5015xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5016 xmlNodePtr node)
5017{
5018 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005019 xmlNodePtr child = NULL;
5020 xmlAttrPtr attr;
5021 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005022
Daniel Veillardc0826a72004-08-10 14:17:33 +00005023 /*
5024 * INFO: S4S completed.
5025 */
5026 /*
5027 * id = ID
5028 * {any attributes with non-schema namespace . . .}>
5029 * Content: (appinfo | documentation)*
5030 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005031 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5032 return (NULL);
5033 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005034 attr = node->properties;
5035 while (attr != NULL) {
5036 if (((attr->ns == NULL) &&
5037 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
5038 ((attr->ns != NULL) &&
5039 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
5040
5041 xmlSchemaPIllegalAttrErr(ctxt,
5042 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5043 NULL, NULL, attr);
5044 }
5045 attr = attr->next;
5046 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005047 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005048 /*
5049 * And now for the children...
5050 */
5051 child = node->children;
5052 while (child != NULL) {
5053 if (IS_SCHEMA(child, "appinfo")) {
5054 /* TODO: make available the content of "appinfo". */
5055 /*
5056 * source = anyURI
5057 * {any attributes with non-schema namespace . . .}>
5058 * Content: ({any})*
5059 */
5060 attr = child->properties;
5061 while (attr != NULL) {
5062 if (((attr->ns == NULL) &&
5063 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
5064 ((attr->ns != NULL) &&
5065 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005066
Daniel Veillardc0826a72004-08-10 14:17:33 +00005067 xmlSchemaPIllegalAttrErr(ctxt,
5068 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5069 NULL, NULL, attr);
5070 }
5071 attr = attr->next;
5072 }
5073 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5074 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
5075 child = child->next;
5076 } else if (IS_SCHEMA(child, "documentation")) {
5077 /* TODO: make available the content of "documentation". */
5078 /*
5079 * source = anyURI
5080 * {any attributes with non-schema namespace . . .}>
5081 * Content: ({any})*
5082 */
5083 attr = child->properties;
5084 while (attr != NULL) {
5085 if (attr->ns == NULL) {
5086 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
5087 xmlSchemaPIllegalAttrErr(ctxt,
5088 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5089 NULL, NULL, attr);
5090 }
5091 } else {
5092 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5093 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5094 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
5095
5096 xmlSchemaPIllegalAttrErr(ctxt,
5097 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5098 NULL, NULL, attr);
5099 }
5100 }
5101 attr = attr->next;
5102 }
5103 /*
5104 * Attribute "xml:lang".
5105 */
5106 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5107 if (attr != NULL)
5108 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
5109 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
5110 child = child->next;
5111 } else {
5112 if (!barked)
5113 xmlSchemaPContentErr(ctxt,
5114 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5115 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5116 barked = 1;
5117 child = child->next;
5118 }
5119 }
5120
Daniel Veillard4255d502002-04-16 15:50:10 +00005121 return (ret);
5122}
5123
5124/**
5125 * xmlSchemaParseFacet:
5126 * @ctxt: a schema validation context
5127 * @schema: the schema being built
5128 * @node: a subtree containing XML Schema informations
5129 *
5130 * parse a XML schema Facet declaration
5131 * *WARNING* this interface is highly subject to change
5132 *
5133 * Returns the new type structure or NULL in case of error
5134 */
5135static xmlSchemaFacetPtr
5136xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005137 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005138{
5139 xmlSchemaFacetPtr facet;
5140 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005141 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005142
5143 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5144 return (NULL);
5145
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005146 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005147 if (facet == NULL) {
5148 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5149 return (NULL);
5150 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005151 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005152 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005153 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005154 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5155 "Facet %s has no value\n", node->name, NULL);
5156 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005157 return (NULL);
5158 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005159 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005160 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005161 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005162 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005163 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005164 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005165 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005166 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005167 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005168 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005169 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005170 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005171 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005172 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005173 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005174 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005175 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005176 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005177 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005178 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005179 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005180 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5181 } else if (IS_SCHEMA(node, "minLength")) {
5182 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5183 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005184 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5185 "Unknown facet type %s\n", node->name, NULL);
5186 xmlSchemaFreeFacet(facet);
5187 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005188 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005189 xmlSchemaPValAttrID(ctxt, NULL,
5190 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005191 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005192 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5193 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5194 const xmlChar *fixed;
5195
5196 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5197 if (fixed != NULL) {
5198 if (xmlStrEqual(fixed, BAD_CAST "true"))
5199 facet->fixed = 1;
5200 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005201 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005202 child = node->children;
5203
5204 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005205 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5206 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005207 }
5208 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005209 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5210 "Facet %s has unexpected child content\n",
5211 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005212 }
5213 return (facet);
5214}
5215
5216/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005217 * xmlSchemaParseWildcardNs:
5218 * @ctxt: a schema parser context
5219 * @wildc: the wildcard, already created
5220 * @node: a subtree containing XML Schema informations
5221 *
5222 * Parses the attribute "processContents" and "namespace"
5223 * of a xsd:anyAttribute and xsd:any.
5224 * *WARNING* this interface is highly subject to change
5225 *
5226 * Returns 0 if everything goes fine, a positive error code
5227 * if something is not valid and -1 if an internal error occurs.
5228 */
5229static int
5230xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5231 xmlSchemaPtr schema,
5232 xmlSchemaWildcardPtr wildc,
5233 xmlNodePtr node)
5234{
5235 const xmlChar *pc, *ns, *dictnsItem;
5236 int ret = 0;
5237 xmlChar *nsItem;
5238 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5239 xmlAttrPtr attr;
5240
5241 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5242 if ((pc == NULL)
5243 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5244 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5245 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5246 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5247 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5248 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5249 } else {
5250 xmlSchemaPSimpleTypeErr(ctxt,
5251 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
5252 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00005253 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005254 NULL, NULL, NULL);
5255 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5256 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
5257 }
5258 /*
5259 * Build the namespace constraints.
5260 */
5261 attr = xmlSchemaGetPropNode(node, "namespace");
5262 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5263 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
5264 wildc->any = 1;
5265 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5266 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5267 if (wildc->negNsSet == NULL) {
5268 return (-1);
5269 }
5270 wildc->negNsSet->value = schema->targetNamespace;
5271 } else {
5272 const xmlChar *end, *cur;
5273
5274 cur = ns;
5275 do {
5276 while (IS_BLANK_CH(*cur))
5277 cur++;
5278 end = cur;
5279 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5280 end++;
5281 if (end == cur)
5282 break;
5283 nsItem = xmlStrndup(cur, end - cur);
5284 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5285 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
5286 xmlSchemaPSimpleTypeErr(ctxt,
5287 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
5288 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005289 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005290 "((##any | ##other) | List of (anyURI | "
5291 "(##targetNamespace | ##local)))",
5292 nsItem, NULL, NULL, NULL);
5293 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5294 } else {
5295 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5296 dictnsItem = schema->targetNamespace;
5297 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5298 dictnsItem = NULL;
5299 } else {
5300 /*
5301 * Validate the item (anyURI).
5302 */
5303 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
5304 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5305 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5306 }
5307 /*
5308 * Avoid dublicate namespaces.
5309 */
5310 tmp = wildc->nsSet;
5311 while (tmp != NULL) {
5312 if (dictnsItem == tmp->value)
5313 break;
5314 tmp = tmp->next;
5315 }
5316 if (tmp == NULL) {
5317 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5318 if (tmp == NULL) {
5319 xmlFree(nsItem);
5320 return (-1);
5321 }
5322 tmp->value = dictnsItem;
5323 tmp->next = NULL;
5324 if (wildc->nsSet == NULL)
5325 wildc->nsSet = tmp;
5326 else
5327 lastNs->next = tmp;
5328 lastNs = tmp;
5329 }
5330
5331 }
5332 xmlFree(nsItem);
5333 cur = end;
5334 } while (*cur != 0);
5335 }
5336 return (ret);
5337}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005338
5339static int
5340xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
5341 xmlSchemaTypePtr item,
5342 xmlNodePtr node,
5343 int minOccurs,
5344 int maxOccurs) {
5345
5346 if (maxOccurs != UNBOUNDED) {
5347 /*
5348 * TODO: Maby we should better not create the particle,
5349 * if min/max is invalid, since it could confuse the build of the
5350 * content model.
5351 */
5352 /*
5353 * 3.9.6 Schema Component Constraint: Particle Correct
5354 *
5355 */
5356 if (maxOccurs < 1) {
5357 /*
5358 * 2.2 {max occurs} must be greater than or equal to 1.
5359 */
5360 xmlSchemaPCustomAttrErr(ctxt,
5361 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
5362 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
5363 "The value must be greater than or equal to 1");
5364 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
5365 } else if (minOccurs > maxOccurs) {
5366 /*
5367 * 2.1 {min occurs} must not be greater than {max occurs}.
5368 */
5369 xmlSchemaPCustomAttrErr(ctxt,
5370 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
5371 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
5372 "The value must not be greater than the value of 'maxOccurs'");
5373 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
5374 }
5375 }
5376 return (0);
5377}
5378
Daniel Veillardc0826a72004-08-10 14:17:33 +00005379/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005380 * xmlSchemaParseAny:
5381 * @ctxt: a schema validation context
5382 * @schema: the schema being built
5383 * @node: a subtree containing XML Schema informations
5384 *
5385 * parse a XML schema Any declaration
5386 * *WARNING* this interface is highly subject to change
5387 *
5388 * Returns the new type structure or NULL in case of error
5389 */
5390static xmlSchemaTypePtr
5391xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5392 xmlNodePtr node)
5393{
5394 xmlSchemaTypePtr type;
5395 xmlNodePtr child = NULL;
5396 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005397 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005398 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005399
5400 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5401 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005402 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
5403 "(nonNegativeInteger | unbounded)");
5404 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
5405 "nonNegativeInteger");
5406 if ((minOccurs == 0) && (maxOccurs == 0))
5407 return (NULL);
5408
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005409 snprintf((char *) name, 30, "#any%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005410 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005411 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005412 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005413 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005414 type->type = XML_SCHEMA_TYPE_ANY;
5415
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005416 /*
5417 * TODO: Use a particle component here.
5418 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005419 wildc = xmlSchemaAddWildcard(ctxt);
5420 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005421 * Check min/max sanity.
5422 */
5423 type->maxOccurs = maxOccurs;
5424 type->minOccurs = minOccurs;
5425 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
5426 node, type->minOccurs, type->maxOccurs);
5427 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005428 * This is not nice, since it is won't be used as a attribute wildcard,
5429 * but better than adding a field to the structure.
5430 */
5431 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005432 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005433 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005434 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005435 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5436 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005437 }
5438 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005439 xmlSchemaPErr2(ctxt, node, child,
5440 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
5441 "Sequence %s has unexpected content\n", type->name,
5442 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005443 }
5444
5445 return (type);
5446}
5447
5448/**
5449 * xmlSchemaParseNotation:
5450 * @ctxt: a schema validation context
5451 * @schema: the schema being built
5452 * @node: a subtree containing XML Schema informations
5453 *
5454 * parse a XML schema Notation declaration
5455 *
5456 * Returns the new structure or NULL in case of error
5457 */
5458static xmlSchemaNotationPtr
5459xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005460 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005461{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005462 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005463 xmlSchemaNotationPtr ret;
5464 xmlNodePtr child = NULL;
5465
5466 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5467 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005468 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005469 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005470 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
5471 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005472 return (NULL);
5473 }
5474 ret = xmlSchemaAddNotation(ctxt, schema, name);
5475 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005476 return (NULL);
5477 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005478 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00005479
5480 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5481 node, BAD_CAST "id");
5482
5483 if (IS_SCHEMA(child, "annotation")) {
5484 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5485 child = child->next;
5486 }
5487
Daniel Veillard4255d502002-04-16 15:50:10 +00005488 child = node->children;
5489 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005490 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5491 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005492 }
5493 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005494 xmlSchemaPErr2(ctxt, node, child,
5495 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
5496 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005497 }
5498
5499 return (ret);
5500}
5501
5502/**
5503 * xmlSchemaParseAnyAttribute:
5504 * @ctxt: a schema validation context
5505 * @schema: the schema being built
5506 * @node: a subtree containing XML Schema informations
5507 *
5508 * parse a XML schema AnyAttrribute declaration
5509 * *WARNING* this interface is highly subject to change
5510 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005511 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00005512 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005513static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005514xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5515 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005516{
Daniel Veillard3646d642004-06-02 19:19:14 +00005517 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005518 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005519 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005520
5521 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5522 return (NULL);
5523
Daniel Veillard3646d642004-06-02 19:19:14 +00005524 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005525 if (ret == NULL) {
5526 return (NULL);
5527 }
William M. Bracke7091952004-05-11 15:09:58 +00005528 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005529 /*
5530 * Check for illegal attributes.
5531 */
5532 attr = node->properties;
5533 while (attr != NULL) {
5534 if (attr->ns == NULL) {
5535 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5536 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
5537 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
5538 xmlSchemaPIllegalAttrErr(ctxt,
5539 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5540 NULL, NULL, attr);
5541 }
5542 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5543 xmlSchemaPIllegalAttrErr(ctxt,
5544 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5545 NULL, NULL, attr);
5546 }
5547 attr = attr->next;
5548 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005549 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5550 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005551 /*
5552 * Parse the namespace list.
5553 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005554 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
5555 xmlSchemaFreeWildcard(ret);
5556 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005557 }
5558 /*
5559 * And now for the children...
5560 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005561 child = node->children;
5562 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005563 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5564 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005565 }
5566 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005567 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005568 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5569 NULL, NULL, node, child,
5570 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005571 }
5572
5573 return (ret);
5574}
5575
5576
5577/**
5578 * xmlSchemaParseAttribute:
5579 * @ctxt: a schema validation context
5580 * @schema: the schema being built
5581 * @node: a subtree containing XML Schema informations
5582 *
5583 * parse a XML schema Attrribute declaration
5584 * *WARNING* this interface is highly subject to change
5585 *
William M. Bracke7091952004-05-11 15:09:58 +00005586 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005587 */
5588static xmlSchemaAttributePtr
5589xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005590 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005591{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005592 const xmlChar *name, *attrValue;
5593 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00005594 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005595 xmlNodePtr child = NULL;
5596 xmlAttrPtr attr, nameAttr;
5597 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005598
5599 /*
5600 * Note that the w3c spec assumes the schema to be validated with schema
5601 * for schemas beforehand.
5602 *
5603 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00005604 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005605
5606 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5607 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005608 attr = xmlSchemaGetPropNode(node, "ref");
5609 nameAttr = xmlSchemaGetPropNode(node, "name");
5610
5611 if ((attr == NULL) && (nameAttr == NULL)) {
5612 /*
5613 * 3.2.3 : 3.1
5614 * One of ref or name must be present, but not both
5615 */
5616 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5617 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
5618 "One of the attributes 'ref' or 'name' must be present");
5619 return (NULL);
5620 }
5621 if ((topLevel) || (attr == NULL)) {
5622 if (nameAttr == NULL) {
5623 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
5624 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5625 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005626 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005627 }
5628 } else
5629 isRef = 1;
5630
5631 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005632 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005633 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
5634
5635 /*
5636 * Parse as attribute reference.
5637 */
5638 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
5639 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
5640 &refPrefix, &ref) != 0) {
5641 return (NULL);
5642 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005643 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005644 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005645 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005646 if (ret == NULL) {
5647 if (repName != NULL)
5648 xmlFree(repName);
5649 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005650 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005651 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5652 ret->node = node;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005653 ret->refNs = refNs;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005654 ret->refPrefix = refPrefix;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005655 ret->ref = ref;
5656 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaTypePtr) ret, refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005657 /*
5658 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
5659 */
5660 if (nameAttr != NULL)
5661 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5662 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5663 "ref", "name");
5664 /*
5665 * Check for illegal attributes.
5666 */
5667 attr = node->properties;
5668 while (attr != NULL) {
5669 if (attr->ns == NULL) {
5670 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
5671 xmlStrEqual(attr->name, BAD_CAST "form")) {
5672 /*
5673 * 3.2.3 : 3.2
5674 * If ref is present, then all of <simpleType>,
5675 * form and type must be absent.
5676 */
5677 xmlSchemaPIllegalAttrErr(ctxt,
5678 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
5679 (xmlSchemaTypePtr) ret, attr);
5680 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
5681 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
5682 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5683 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5684 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5685 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
5686 xmlSchemaPIllegalAttrErr(ctxt,
5687 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5688 &repName, (xmlSchemaTypePtr) ret, attr);
5689 }
5690 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5691 xmlSchemaPIllegalAttrErr(ctxt,
5692 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5693 &repName, (xmlSchemaTypePtr) ret, attr);
5694 }
5695 attr = attr->next;
5696 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005697 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005698 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005699
5700 /*
5701 * Parse as attribute declaration.
5702 */
5703 if (xmlSchemaPValAttrNode(ctxt,
5704 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
5705 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5706 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005707 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005708 /*
5709 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
5710 */
5711 /*
5712 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
5713 */
5714 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
5715 xmlSchemaPSimpleTypeErr(ctxt,
5716 XML_SCHEMAP_NO_XMLNS,
5717 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005718 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005719 "The value must not match 'xmlns'",
5720 NULL, NULL);
5721 if (repName != NULL)
5722 xmlFree(repName);
5723 return (NULL);
5724 }
5725 /*
5726 * Evaluate the target namespace
5727 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005728 if (topLevel) {
5729 ns = schema->targetNamespace;
5730 } else {
5731 attr = xmlSchemaGetPropNode(node, "form");
5732 if (attr != NULL) {
5733 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5734 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
5735 ns = schema->targetNamespace;
5736 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5737 xmlSchemaPSimpleTypeErr(ctxt,
5738 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5739 &repName, NULL, (xmlNodePtr) attr,
5740 NULL, "(qualified | unqualified)",
5741 attrValue, NULL, NULL, NULL);
5742 }
5743 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
5744 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005745 }
5746 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005747 if (ret == NULL) {
5748 if (repName != NULL)
5749 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00005750 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005751 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005752 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005753 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005754 if (topLevel)
5755 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
5756 /*
5757 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
5758 */
5759 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
5760 xmlSchemaPCustomErr(ctxt,
5761 XML_SCHEMAP_NO_XSI,
5762 &repName, (xmlSchemaTypePtr) ret, node,
5763 "The target namespace must not match '%s'",
5764 xmlSchemaInstanceNs);
5765 }
5766 /*
5767 * Check for illegal attributes.
5768 */
5769 attr = node->properties;
5770 while (attr != NULL) {
5771 if (attr->ns == NULL) {
5772 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5773 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5774 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5775 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5776 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
5777 if ((topLevel) ||
5778 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
5779 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
5780 xmlSchemaPIllegalAttrErr(ctxt,
5781 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5782 &repName, (xmlSchemaTypePtr) ret, attr);
5783 }
5784 }
5785 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5786 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5787 &repName, (xmlSchemaTypePtr) ret, attr);
5788 }
5789 attr = attr->next;
5790 }
5791 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
5792 node, "type", &ret->typeNs, NULL, &ret->typeName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005793 }
5794 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5795 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00005796 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005797 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00005798 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005799 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
5800 if (ret->defValue != NULL)
5801 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
5802 /*
5803 * Attribute "default".
5804 */
5805 attr = xmlSchemaGetPropNode(node, "default");
5806 if (attr != NULL) {
5807 /*
5808 * 3.2.3 : 1
5809 * default and fixed must not both be present.
5810 */
5811 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
5812 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
5813 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
5814 } else
5815 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5816 }
5817 if (topLevel == 0) {
5818 /*
5819 * Attribute "use".
5820 */
5821 attr = xmlSchemaGetPropNode(node, "use");
5822 if (attr != NULL) {
5823 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5824 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
5825 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5826 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
5827 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
5828 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
5829 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
5830 else
5831 xmlSchemaPSimpleTypeErr(ctxt,
5832 XML_SCHEMAP_INVALID_ATTR_USE,
5833 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005834 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005835 attrValue, NULL, NULL, NULL);
5836 } else
5837 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5838 /*
5839 * 3.2.3 : 2
5840 * If default and use are both present, use must have
5841 * the actual value optional.
5842 */
5843 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
5844 (ret->defValue != NULL) &&
5845 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
5846 xmlSchemaPSimpleTypeErr(ctxt,
5847 XML_SCHEMAP_SRC_ATTRIBUTE_2,
5848 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005849 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005850 "The value must be 'optional' if the attribute "
5851 "'default' is present as well", NULL, NULL);
5852 }
5853 }
5854 /*
5855 * And now for the children...
5856 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005857 child = node->children;
5858 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005859 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5860 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005861 }
5862 if (isRef) {
5863 if (child != NULL) {
5864 if (IS_SCHEMA(child, "simpleType"))
5865 /*
5866 * 3.2.3 : 3.2
5867 * If ref is present, then all of <simpleType>,
5868 * form and type must be absent.
5869 */
5870 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
5871 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5872 "(annotation?)");
5873 else
5874 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5875 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5876 "(annotation?)");
5877 }
5878 } else {
5879 if (IS_SCHEMA(child, "simpleType")) {
5880 if (ret->typeName != NULL) {
5881 /*
5882 * 3.2.3 : 4
5883 * type and <simpleType> must not both be present.
5884 */
5885 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
5886 &repName, (xmlSchemaTypePtr) ret, node, child,
5887 "The attribute 'type' and the <simpleType> child "
5888 "are mutually exclusive", NULL);
5889 } else
5890 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5891 child = child->next;
5892 }
5893 if (child != NULL)
5894 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5895 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5896 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005897 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005898 /*
5899 * Cleanup.
5900 */
5901 if (repName != NULL)
5902 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005903 return (ret);
5904}
5905
5906/**
5907 * xmlSchemaParseAttributeGroup:
5908 * @ctxt: a schema validation context
5909 * @schema: the schema being built
5910 * @node: a subtree containing XML Schema informations
5911 *
5912 * parse a XML schema Attribute Group declaration
5913 * *WARNING* this interface is highly subject to change
5914 *
5915 * Returns the attribute group or NULL in case of error.
5916 */
5917static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005918xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005919 xmlSchemaPtr schema, xmlNodePtr node,
5920 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005921{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005922 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005923 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005924 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005925 const xmlChar *oldcontainer;
5926 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005927
5928 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5929 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005930
5931 nameAttr = xmlSchemaGetPropNode(node, "name");
5932 attr = xmlSchemaGetPropNode(node, "ref");
5933 if ((topLevel) || (attr == NULL)) {
5934 /*
5935 * Parse as an attribute group definition.
5936 * Note that those are allowed at top level only.
5937 */
5938 if (nameAttr == NULL) {
5939 xmlSchemaPMissingAttrErr(ctxt,
5940 XML_SCHEMAP_S4S_ATTR_MISSING,
5941 NULL, NULL, node, "name", NULL);
5942 return (NULL);
5943 }
5944 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5945 /*
5946 * The name is crucial, exit if invalid.
5947 */
5948 if (xmlSchemaPValAttrNode(ctxt,
5949 NULL, NULL, nameAttr,
5950 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5951 return (NULL);
5952 }
5953 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5954 if (ret == NULL)
5955 return (NULL);
5956 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5957 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5958 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005959 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005960 } else {
5961 char buf[50];
5962 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5963
5964 /*
5965 * Parse as an attribute group definition reference.
5966 */
5967 if (attr == NULL) {
5968 xmlSchemaPMissingAttrErr(ctxt,
5969 XML_SCHEMAP_S4S_ATTR_MISSING,
5970 NULL, NULL, node, "ref", NULL);
5971 }
5972 xmlSchemaPValAttrNodeQName(ctxt, schema,
5973 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5974
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005975 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005976 name = (const xmlChar *) buf;
5977 if (name == NULL) {
5978 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5979 "attribute group definition reference", node);
5980 return (NULL);
5981 }
5982 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5983 if (ret == NULL)
5984 return (NULL);
5985 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5986 ret->ref = ref;
5987 ret->refNs = refNs;
5988 /* TODO: Is @refPrefix currently used? */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005989 ret->refPrefix = refPrefix;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005990 ret->node = node;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005991 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaTypePtr) ret, refNs);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005992 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005993 /*
5994 * Check for illegal attributes.
5995 */
5996 attr = node->properties;
5997 while (attr != NULL) {
5998 if (attr->ns == NULL) {
5999 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6000 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
6001 (!xmlStrEqual(attr->name, BAD_CAST "id")))
6002 {
6003 xmlSchemaPIllegalAttrErr(ctxt,
6004 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6005 NULL, NULL, attr);
6006 }
6007 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6008 xmlSchemaPIllegalAttrErr(ctxt,
6009 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6010 NULL, NULL, attr);
6011 }
6012 attr = attr->next;
6013 }
6014 /* TODO: Validate "id" ? */
6015 /*
6016 * And now for the children...
6017 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006018 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006019 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006020 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006021 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006022 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6023 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006024 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006025 if (topLevel) {
6026 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
6027 if (IS_SCHEMA(child, "anyAttribute")) {
6028 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6029 child = child->next;
6030 }
6031 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006032 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006033 xmlSchemaPContentErr(ctxt,
6034 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6035 NULL, NULL, node, child, NULL,
6036 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006037 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006038 ctxt->container = oldcontainer;
6039 return (ret);
6040}
6041
6042/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006043 * xmlSchemaPValAttrFormDefault:
6044 * @value: the value
6045 * @flags: the flags to be modified
6046 * @flagQualified: the specific flag for "qualified"
6047 *
6048 * Returns 0 if the value is valid, 1 otherwise.
6049 */
6050static int
6051xmlSchemaPValAttrFormDefault(const xmlChar *value,
6052 int *flags,
6053 int flagQualified)
6054{
6055 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6056 if ((*flags & flagQualified) == 0)
6057 *flags |= flagQualified;
6058 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
6059 return (1);
6060
6061 return (0);
6062}
6063
6064/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006065 * xmlSchemaPValAttrBlockFinal:
6066 * @value: the value
6067 * @flags: the flags to be modified
6068 * @flagAll: the specific flag for "#all"
6069 * @flagExtension: the specific flag for "extension"
6070 * @flagRestriction: the specific flag for "restriction"
6071 * @flagSubstitution: the specific flag for "substitution"
6072 * @flagList: the specific flag for "list"
6073 * @flagUnion: the specific flag for "union"
6074 *
6075 * Validates the value of the attribute "final" and "block". The value
6076 * is converted into the specified flag values and returned in @flags.
6077 *
6078 * Returns 0 if the value is valid, 1 otherwise.
6079 */
6080
6081static int
6082xmlSchemaPValAttrBlockFinal(const xmlChar *value,
6083 int *flags,
6084 int flagAll,
6085 int flagExtension,
6086 int flagRestriction,
6087 int flagSubstitution,
6088 int flagList,
6089 int flagUnion)
6090{
6091 int ret = 0;
6092
6093 /*
6094 * TODO: This does not check for dublicate entries.
6095 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006096 if (value == NULL)
6097 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006098 if (xmlStrEqual(value, BAD_CAST "#all")) {
6099 if (flagAll != -1)
6100 *flags |= flagAll;
6101 else {
6102 if (flagExtension != -1)
6103 *flags |= flagExtension;
6104 if (flagRestriction != -1)
6105 *flags |= flagRestriction;
6106 if (flagSubstitution != -1)
6107 *flags |= flagSubstitution;
6108 if (flagList != -1)
6109 *flags |= flagList;
6110 if (flagUnion != -1)
6111 *flags |= flagUnion;
6112 }
6113 } else {
6114 const xmlChar *end, *cur = value;
6115 xmlChar *item;
6116
6117 do {
6118 while (IS_BLANK_CH(*cur))
6119 cur++;
6120 end = cur;
6121 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6122 end++;
6123 if (end == cur)
6124 break;
6125 item = xmlStrndup(cur, end - cur);
6126 if (xmlStrEqual(item, BAD_CAST "extension")) {
6127 if (flagExtension != -1) {
6128 if ((*flags & flagExtension) == 0)
6129 *flags |= flagExtension;
6130 } else
6131 ret = 1;
6132 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6133 if (flagRestriction != -1) {
6134 if ((*flags & flagRestriction) == 0)
6135 *flags |= flagRestriction;
6136 } else
6137 ret = 1;
6138 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6139 if (flagSubstitution != -1) {
6140 if ((*flags & flagSubstitution) == 0)
6141 *flags |= flagSubstitution;
6142 } else
6143 ret = 1;
6144 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6145 if (flagList != -1) {
6146 if ((*flags & flagList) == 0)
6147 *flags |= flagList;
6148 } else
6149 ret = 1;
6150 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6151 if (flagUnion != -1) {
6152 if ((*flags & flagUnion) == 0)
6153 *flags |= flagUnion;
6154 } else
6155 ret = 1;
6156 } else
6157 ret = 1;
6158 if (item != NULL)
6159 xmlFree(item);
6160 cur = end;
6161 } while ((ret == 0) && (*cur != 0));
6162 }
6163
6164 return (ret);
6165}
6166
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006167#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006168static int
6169xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006170 xmlSchemaIDCPtr idc,
6171 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006172 xmlAttrPtr attr,
6173 int isField)
6174{
6175 xmlNodePtr node;
6176
6177 /*
6178 * c-selector-xpath:
6179 * Schema Component Constraint: Selector Value OK
6180 *
6181 * TODO: 1 The {selector} must be a valid XPath expression, as defined
6182 * in [XPath].
6183 */
6184 if (selector == NULL) {
6185 xmlSchemaPErr(ctxt, idc->node,
6186 XML_SCHEMAP_INTERNAL,
6187 "Internal error: xmlSchemaCheckCSelectorXPath, "
6188 "the selector is not specified.\n", NULL, NULL);
6189 return (-1);
6190 }
6191 if (attr == NULL)
6192 node = idc->node;
6193 else
6194 node = (xmlNodePtr) attr;
6195 if (selector->xpath == NULL) {
6196 xmlSchemaPCustomErr(ctxt,
6197 /* TODO: Adjust error code. */
6198 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6199 NULL, NULL, node,
6200 "The XPath expression of the selector is not valid", NULL);
6201 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6202 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006203 const xmlChar **nsArray = NULL;
6204 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006205 /*
6206 * Compile the XPath expression.
6207 */
6208 /*
6209 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006210 * TODO: Call xmlPatterncompile with different options for selector/
6211 * field.
6212 */
6213 nsList = xmlGetNsList(attr->doc, attr->parent);
6214 /*
6215 * Build an array of prefixes and namespaces.
6216 */
6217 if (nsList != NULL) {
6218 int i, count = 0;
6219 xmlNsPtr ns;
6220
6221 for (i = 0; nsList[i] != NULL; i++)
6222 count++;
6223
6224 nsArray = (const xmlChar **) xmlMalloc(
6225 (count * 2 + 1) * sizeof(const xmlChar *));
6226 if (nsArray == NULL) {
6227 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6228 NULL);
6229 return (-1);
6230 }
6231 for (i = 0; i < count; i++) {
6232 ns = nsList[i];
6233 nsArray[2 * i] = nsList[i]->href;
6234 nsArray[2 * i + 1] = nsList[i]->prefix;
6235 }
6236 nsArray[count * 2] = NULL;
6237 xmlFree(nsList);
6238 }
6239 if (isField)
6240 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006241 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006242 else
6243 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006244 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006245 if (nsArray != NULL)
6246 xmlFree((xmlChar **) nsArray);
6247
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006248#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006249 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006250 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006251 /* TODO: Adjust error code? */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006252 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6253 NULL, NULL, node,
6254 "The XPath expression '%s' could not be "
6255 "compiled", selector->xpath);
6256 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6257 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006258#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006259 }
6260 return (0);
6261}
6262
6263/**
6264 * xmlSchemaAssignAnnotation:
6265 * @item: the schema component
6266 * @annot: the annotation
6267 *
6268 * Adds the annotation to the given schema component.
6269 *
6270 * Returns the given annotaion.
6271 */
6272static xmlSchemaAnnotPtr
6273xmlSchemaAssignAnnotation(xmlSchemaBasicItemPtr item,
6274 xmlSchemaAnnotPtr annot)
6275{
6276 xmlSchemaAnnotPtr cur = item->annot;
6277
6278 if (item->annot == NULL) {
6279 item->annot = annot;
6280 return (annot);
6281 }
6282 cur = item->annot;
6283 if (cur->next != NULL) {
6284 cur = cur->next;
6285 }
6286 cur->next = annot;
6287 return (annot);
6288}
6289
6290/**
6291 * xmlSchemaParseIDCSelectorAndField:
6292 * @ctxt: a schema validation context
6293 * @schema: the schema being built
6294 * @node: a subtree containing XML Schema informations
6295 *
6296 * Parses a XML Schema identity-contraint definition's
6297 * <selector> and <field> elements.
6298 *
6299 * Returns the parsed identity-constraint definition.
6300 */
6301static xmlSchemaIDCSelectPtr
6302xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
6303 xmlSchemaPtr schema,
6304 xmlSchemaIDCPtr idc,
6305 xmlNodePtr node,
6306 int isField)
6307{
6308 xmlSchemaIDCSelectPtr item;
6309 xmlNodePtr child = NULL;
6310 xmlAttrPtr attr;
6311
6312 /*
6313 * Check for illegal attributes.
6314 */
6315 attr = node->properties;
6316 while (attr != NULL) {
6317 if (attr->ns == NULL) {
6318 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6319 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
6320 xmlSchemaPIllegalAttrErr(ctxt,
6321 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6322 NULL, NULL, attr);
6323 }
6324 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6325 xmlSchemaPIllegalAttrErr(ctxt,
6326 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6327 NULL, NULL, attr);
6328 }
6329 attr = attr->next;
6330 }
6331 /*
6332 * Create the item.
6333 */
6334 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
6335 if (item == NULL) {
6336 xmlSchemaPErrMemory(ctxt,
6337 "allocating a 'selector' of an identity-constraint definition",
6338 NULL);
6339 return (NULL);
6340 }
6341 memset(item, 0, sizeof(xmlSchemaIDCSelect));
6342 /*
6343 * Attribute "xpath" (mandatory).
6344 */
6345 attr = xmlSchemaGetPropNode(node, "xpath");
6346 if (attr == NULL) {
6347 xmlSchemaPMissingAttrErr(ctxt,
6348 XML_SCHEMAP_S4S_ATTR_MISSING,
6349 NULL, NULL, node,
6350 "name", NULL);
6351 } else {
6352 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6353 /*
6354 * URGENT TODO: "field"s have an other syntax than "selector"s.
6355 */
6356
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006357 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
6358 isField) == -1) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006359 xmlSchemaPErr(ctxt,
6360 (xmlNodePtr) attr,
6361 XML_SCHEMAP_INTERNAL,
6362 "Internal error: xmlSchemaParseIDCSelectorAndField, "
6363 "validating the XPath expression of a IDC selector.\n",
6364 NULL, NULL);
6365 }
6366
6367 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006368 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006369 /*
6370 * And now for the children...
6371 */
6372 child = node->children;
6373 if (IS_SCHEMA(child, "annotation")) {
6374 /*
6375 * Add the annotation to the parent IDC.
6376 */
6377 xmlSchemaAssignAnnotation((xmlSchemaBasicItemPtr) idc,
6378 xmlSchemaParseAnnotation(ctxt, schema, child));
6379 child = child->next;
6380 }
6381 if (child != NULL) {
6382 xmlSchemaPContentErr(ctxt,
6383 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6384 NULL, NULL, node, child,
6385 NULL, "(annotation?)");
6386 }
6387
6388 return (item);
6389}
6390
6391/**
6392 * xmlSchemaParseIDC:
6393 * @ctxt: a schema validation context
6394 * @schema: the schema being built
6395 * @node: a subtree containing XML Schema informations
6396 *
6397 * Parses a XML Schema identity-contraint definition.
6398 *
6399 * Returns the parsed identity-constraint definition.
6400 */
6401static xmlSchemaIDCPtr
6402xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
6403 xmlSchemaPtr schema,
6404 xmlNodePtr node,
6405 xmlSchemaTypeType idcCategory,
6406 const xmlChar *targetNamespace)
6407{
6408 xmlSchemaIDCPtr item = NULL;
6409 xmlNodePtr child = NULL;
6410 xmlAttrPtr attr;
6411 const xmlChar *name = NULL;
6412 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
6413 int resAdd;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006414
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006415 /*
6416 * Check for illegal attributes.
6417 */
6418 attr = node->properties;
6419 while (attr != NULL) {
6420 if (attr->ns == NULL) {
6421 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6422 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6423 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
6424 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
6425 xmlSchemaPIllegalAttrErr(ctxt,
6426 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6427 NULL, NULL, attr);
6428 }
6429 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6430 xmlSchemaPIllegalAttrErr(ctxt,
6431 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6432 NULL, NULL, attr);
6433 }
6434 attr = attr->next;
6435 }
6436 /*
6437 * Attribute "name" (mandatory).
6438 */
6439 attr = xmlSchemaGetPropNode(node, "name");
6440 if (attr == NULL) {
6441 xmlSchemaPMissingAttrErr(ctxt,
6442 XML_SCHEMAP_S4S_ATTR_MISSING,
6443 NULL, NULL, node,
6444 "name", NULL);
6445 return (NULL);
6446 } else if (xmlSchemaPValAttrNode(ctxt,
6447 NULL, NULL, attr,
6448 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6449 return (NULL);
6450 }
6451 /*
6452 * Create the component.
6453 */
6454 if (schema->idcDef == NULL)
6455 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
6456 if (schema->idcDef == NULL)
6457 return (NULL);
6458
6459 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
6460 if (item == NULL) {
6461 xmlSchemaPErrMemory(ctxt,
6462 "allocating an identity-constraint definition", NULL);
6463 return (NULL);
6464 }
6465 /*
6466 * Add the IDC to the list of IDCs on the schema component.
6467 */
6468 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
6469 if (resAdd != 0) {
6470 xmlSchemaPCustomErrExt(ctxt,
6471 XML_SCHEMAP_REDEFINED_TYPE,
6472 NULL, NULL, node,
6473 "An identity-constraint definition with the name '%s' "
6474 "and targetNamespace '%s' does already exist",
6475 name, targetNamespace, NULL);
6476 xmlFree(item);
6477 return (NULL);
6478 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006479 memset(item, 0, sizeof(xmlSchemaIDC));
6480 item->name = name;
6481 item->type = idcCategory;
6482 item->node = node;
6483 /*
6484 * The target namespace of the parent element declaration.
6485 */
6486 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006487 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
6488 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006489 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
6490 /*
6491 * Attribute "refer" (mandatory).
6492 */
6493 attr = xmlSchemaGetPropNode(node, "refer");
6494 if (attr == NULL) {
6495 xmlSchemaPMissingAttrErr(ctxt,
6496 XML_SCHEMAP_S4S_ATTR_MISSING,
6497 NULL, NULL, node,
6498 "refer", NULL);
6499 } else {
6500 /*
6501 * Create a reference item.
6502 */
6503 item->ref = (xmlSchemaItemQNRefPtr) xmlMalloc(
6504 sizeof(xmlSchemaItemQNRef));
6505 if (item->ref == NULL) {
6506 xmlSchemaPErrMemory(ctxt,
6507 "allocating a QName reference item", NULL);
6508 return (NULL);
6509 }
6510 memset(item->ref, 0, sizeof(xmlSchemaItemQNRef));
6511 xmlSchemaPValAttrNodeQName(ctxt, schema,
6512 NULL, NULL, attr,
6513 &(item->ref->targetNamespace), 0,
6514 &(item->ref->name));
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006515 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaTypePtr) item,
6516 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006517 }
6518 }
6519 /*
6520 * And now for the children...
6521 */
6522 child = node->children;
6523 if (IS_SCHEMA(child, "annotation")) {
6524 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6525 child = child->next;
6526 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006527 if (child == NULL) {
6528 xmlSchemaPContentErr(ctxt,
6529 XML_SCHEMAP_S4S_ELEM_MISSING,
6530 NULL, NULL, node, child,
6531 "A child element is missing",
6532 "(annotation?, (selector, field+))");
6533 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006534 /*
6535 * Child element <selector>.
6536 */
6537 if (IS_SCHEMA(child, "selector")) {
6538 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6539 item, child, 0);
6540 child = child->next;
6541 /*
6542 * Child elements <field>.
6543 */
6544 if (IS_SCHEMA(child, "field")) {
6545 do {
6546 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6547 item, child, 1);
6548 if (field != NULL) {
6549 field->index = item->nbFields;
6550 item->nbFields++;
6551 if (lastField != NULL)
6552 lastField->next = field;
6553 else
6554 item->fields = field;
6555 lastField = field;
6556 }
6557 child = child->next;
6558 } while (IS_SCHEMA(child, "field"));
6559 } else {
6560 xmlSchemaPContentErr(ctxt,
6561 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6562 NULL, NULL, node, child,
6563 NULL, "(annotation?, (selector, field+))");
6564 }
6565 }
6566 if (child != NULL) {
6567 xmlSchemaPContentErr(ctxt,
6568 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6569 NULL, NULL, node, child,
6570 NULL, "(annotation?, (selector, field+))");
6571 }
6572
6573 return (item);
6574}
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006575#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006576
Daniel Veillardc0826a72004-08-10 14:17:33 +00006577/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006578 * xmlSchemaParseElement:
6579 * @ctxt: a schema validation context
6580 * @schema: the schema being built
6581 * @node: a subtree containing XML Schema informations
6582 *
6583 * parse a XML schema Element declaration
6584 * *WARNING* this interface is highly subject to change
6585 *
William M. Bracke7091952004-05-11 15:09:58 +00006586 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006587 */
6588static xmlSchemaElementPtr
6589xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006590 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006591{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006592 const xmlChar *name = NULL;
6593 const xmlChar *attrValue;
6594 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006595 xmlSchemaElementPtr ret;
6596 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006597 const xmlChar *oldcontainer;
6598 xmlAttrPtr attr, nameAttr;
6599 int minOccurs, maxOccurs;
6600 int isRef = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006601#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006602 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006603#endif
William M. Bracke7091952004-05-11 15:09:58 +00006604
6605 /* 3.3.3 Constraints on XML Representations of Element Declarations */
6606 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006607
Daniel Veillard4255d502002-04-16 15:50:10 +00006608 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6609 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006610
Daniel Veillardc0826a72004-08-10 14:17:33 +00006611 oldcontainer = ctxt->container;
6612
6613 nameAttr = xmlSchemaGetPropNode(node, "name");
6614 attr = xmlSchemaGetPropNode(node, "ref");
6615 if ((topLevel) || (attr == NULL)) {
6616 if (nameAttr == NULL) {
6617 xmlSchemaPMissingAttrErr(ctxt,
6618 XML_SCHEMAP_S4S_ATTR_MISSING,
6619 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
6620 "name", NULL);
6621 return (NULL);
6622 }
6623 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
6624 } else {
6625 isRef = 1;
6626
6627 }
6628 /*
6629 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
6630 * to no component at all
6631 * TODO: It might be better to validate the element, even if it won't be
6632 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006633 */
6634 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6635 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006636 if ((minOccurs == 0) && (maxOccurs == 0))
6637 return (NULL);
6638 /*
6639 * If we get a "ref" attribute on a local <element> we will assume it's
6640 * a reference - even if there's a "name" attribute; this seems to be more
6641 * robust.
6642 */
6643 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006644 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006645 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6646
6647 /*
6648 * Parse as a particle.
6649 */
6650 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006651 (xmlChar **) &xmlSchemaElemDesElemRef,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006652 NULL, attr, &refNs, &refPrefix, &ref);
6653
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006654 snprintf(buf, 49, "#eRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006655 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006656 if (ret == NULL) {
6657 if (repName != NULL)
6658 xmlFree(repName);
6659 return (NULL);
6660 }
6661 ret->type = XML_SCHEMA_TYPE_ELEMENT;
6662 ret->node = node;
6663 ret->ref = ref;
6664 ret->refNs = refNs;
6665 ret->refPrefix = refPrefix;
6666 ret->flags |= XML_SCHEMAS_ELEM_REF;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006667 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaTypePtr) ret, refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006668 /*
6669 * Check for illegal attributes.
6670 */
6671 /*
6672 * 3.3.3 : 2.1
6673 * One of ref or name must be present, but not both
6674 */
6675 if (nameAttr != NULL) {
6676 xmlSchemaPMutualExclAttrErr(ctxt,
6677 XML_SCHEMAP_SRC_ELEMENT_2_1,
6678 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6679 "ref", "name");
6680 }
6681 /* 3.3.3 : 2.2 */
6682 attr = node->properties;
6683 while (attr != NULL) {
6684 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006685 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
6686 xmlStrEqual(attr->name, BAD_CAST "name") ||
6687 xmlStrEqual(attr->name, BAD_CAST "id") ||
6688 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
6689 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
6690 {
6691 attr = attr->next;
6692 continue;
6693 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006694 xmlSchemaPCustomAttrErr(ctxt,
6695 XML_SCHEMAP_SRC_ELEMENT_2_2,
6696 &repName, (xmlSchemaTypePtr) ret, attr,
6697 "Only the attributes 'minOccurs', 'maxOccurs' and "
6698 "'id' are allowed in addition to 'ref'");
6699 break;
6700 }
6701 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6702 xmlSchemaPIllegalAttrErr(ctxt,
6703 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6704 &repName, (xmlSchemaTypePtr) ret, attr);
6705 }
6706 attr = attr->next;
6707 }
6708 } else {
6709 const xmlChar *ns = NULL, *fixed;
6710
6711 /*
6712 * Parse as an element declaration.
6713 */
6714 if (xmlSchemaPValAttrNode(ctxt,
6715 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
6716 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
6717 return (NULL);
6718 /*
6719 * Evaluate the target namespace.
6720 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006721 if (topLevel) {
6722 ns = schema->targetNamespace;
6723 } else {
6724 attr = xmlSchemaGetPropNode(node, "form");
6725 if (attr != NULL) {
6726 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6727 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00006728 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006729 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6730 xmlSchemaPSimpleTypeErr(ctxt,
6731 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6732 &repName, NULL, (xmlNodePtr) attr,
6733 NULL, "(qualified | unqualified)",
6734 attrValue, NULL, NULL, NULL);
6735 }
6736 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6737 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00006738 }
6739 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006740 if (ret == NULL) {
6741 if (repName != NULL)
6742 xmlFree(repName);
6743 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006744 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006745 ret->type = XML_SCHEMA_TYPE_ELEMENT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006746 ret->node = node;
6747 ret->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006748 /*
6749 * Check for illegal attributes.
6750 */
William M. Bracke7091952004-05-11 15:09:58 +00006751 attr = node->properties;
6752 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006753 if (attr->ns == NULL) {
6754 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6755 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6756 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6757 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6758 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6759 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006760 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
6761 {
6762 if (topLevel == 0) {
6763 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006764 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006765 (!xmlStrEqual(attr->name, BAD_CAST "form")))
6766 {
6767 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
6768 /*
6769 * 3.3.6 : 3 If there is a non-·absent· {substitution
6770 * group affiliation}, then {scope} must be global.
6771 * TODO: This one is redundant, since the S4S does
6772 * prohibit this attribute on local declarations already;
6773 * so why an explicit error code? Weird spec.
6774 * TODO: Move this to the proper constraint layer.
6775 * TODO: Or better wait for spec 1.1 to come.
6776 */
6777 xmlSchemaPIllegalAttrErr(ctxt,
6778 XML_SCHEMAP_E_PROPS_CORRECT_3,
6779 &repName, (xmlSchemaTypePtr) ret, attr);
6780 } else {
6781 xmlSchemaPIllegalAttrErr(ctxt,
6782 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6783 &repName, (xmlSchemaTypePtr) ret, attr);
6784 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006785 }
6786 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
6787 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
6788 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
6789
6790 xmlSchemaPIllegalAttrErr(ctxt,
6791 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6792 &repName, (xmlSchemaTypePtr) ret, attr);
6793 }
6794 }
6795 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6796
6797 xmlSchemaPIllegalAttrErr(ctxt,
6798 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6799 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00006800 }
6801 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006802 }
William M. Bracke7091952004-05-11 15:09:58 +00006803 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006804 * Extract/validate attributes.
6805 */
6806 if (topLevel) {
6807 /*
6808 * Process top attributes of global element declarations here.
6809 */
6810 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
6811 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
6812 xmlSchemaPValAttrQName(ctxt, schema, &repName,
6813 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
6814 &(ret->substGroupNs), NULL, &(ret->substGroup));
6815 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6816 node, "abstract", 0))
6817 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
6818 /*
6819 * Attribute "final".
6820 */
6821 attr = xmlSchemaGetPropNode(node, "final");
6822 if (attr == NULL) {
6823 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
6824 } else {
6825 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6826 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6827 -1,
6828 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
6829 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
6830 xmlSchemaPSimpleTypeErr(ctxt,
6831 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6832 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006833 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006834 attrValue, NULL, NULL, NULL);
6835 }
6836 }
6837 }
6838 /*
6839 * Attribute "block".
6840 */
6841 attr = xmlSchemaGetPropNode(node, "block");
6842 if (attr == NULL) {
6843 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
6844 } else {
6845 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6846 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6847 -1,
6848 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
6849 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
6850 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
6851 xmlSchemaPSimpleTypeErr(ctxt,
6852 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6853 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006854 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00006855 "restriction | substitution))", attrValue,
6856 NULL, NULL, NULL);
6857 }
6858 }
6859 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6860 node, "nillable", 0))
6861 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006862
Daniel Veillardc0826a72004-08-10 14:17:33 +00006863 xmlSchemaPValAttrQName(ctxt, schema,
6864 &repName, (xmlSchemaTypePtr) ret, node,
6865 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00006866
Daniel Veillardc0826a72004-08-10 14:17:33 +00006867 ret->value = xmlSchemaGetProp(ctxt, node, "default");
6868 attr = xmlSchemaGetPropNode(node, "fixed");
6869 if (attr != NULL) {
6870 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6871 if (ret->value != NULL) {
6872 /*
6873 * 3.3.3 : 1
6874 * default and fixed must not both be present.
6875 */
6876 xmlSchemaPMutualExclAttrErr(ctxt,
6877 XML_SCHEMAP_SRC_ELEMENT_1,
6878 &repName, (xmlSchemaTypePtr) ret, attr,
6879 "default", "fixed");
6880 } else {
6881 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
6882 ret->value = fixed;
6883 }
6884 }
6885 }
6886 /*
6887 * Extract/validate common attributes.
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006888 */
6889 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6890 node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006891 ret->minOccurs = minOccurs;
6892 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006893 if (topLevel != 1)
6894 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
6895 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006896 /*
6897 * And now for the children...
6898 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006899 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006900 child = node->children;
6901 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006902 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6903 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006904 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006905 if (isRef) {
6906 if (child != NULL) {
6907 xmlSchemaPContentErr(ctxt,
6908 XML_SCHEMAP_SRC_ELEMENT_2_2,
6909 &repName, (xmlSchemaTypePtr) ret, node, child,
6910 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00006911 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006912 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006913 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006914 /*
6915 * 3.3.3 : 3
6916 * "type" and either <simpleType> or <complexType> are mutually
6917 * exclusive
6918 */
William M. Bracke7091952004-05-11 15:09:58 +00006919 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006920 xmlSchemaPContentErr(ctxt,
6921 XML_SCHEMAP_SRC_ELEMENT_3,
6922 &repName, (xmlSchemaTypePtr) ret, node, child,
6923 "The attribute 'type' and the <complexType> child are "
6924 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006925 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006926 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006927 child = child->next;
6928 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006929 /*
6930 * 3.3.3 : 3
6931 * "type" and either <simpleType> or <complexType> are
6932 * mutually exclusive
6933 */
William M. Bracke7091952004-05-11 15:09:58 +00006934 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006935 xmlSchemaPContentErr(ctxt,
6936 XML_SCHEMAP_SRC_ELEMENT_3,
6937 &repName, (xmlSchemaTypePtr) ret, node, child,
6938 "The attribute 'type' and the <simpleType> child are "
6939 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006940 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006941 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006942 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006943 }
William M. Bracke7091952004-05-11 15:09:58 +00006944 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006945 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006946#ifdef IDC_ENABLED
6947 if (IS_SCHEMA(child, "unique")) {
6948 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6949 XML_SCHEMA_TYPE_IDC_UNIQUE, ret->targetNamespace);
6950 } else if (IS_SCHEMA(child, "key")) {
6951 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6952 XML_SCHEMA_TYPE_IDC_KEY, ret->targetNamespace);
6953 } else if (IS_SCHEMA(child, "keyref")) {
6954 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6955 XML_SCHEMA_TYPE_IDC_KEYREF, ret->targetNamespace);
6956 }
6957 if (lastIDC != NULL)
6958 lastIDC->next = curIDC;
6959 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006960 ret->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006961 lastIDC = curIDC;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006962#else
6963 TODO
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006964#endif
6965 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00006966 }
6967 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006968 xmlSchemaPContentErr(ctxt,
6969 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6970 &repName, (xmlSchemaTypePtr) ret, node, child,
6971 NULL, "(annotation?, ((simpleType | complexType)?, "
6972 "(unique | key | keyref)*))");
6973 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006974
Daniel Veillardc0826a72004-08-10 14:17:33 +00006975 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006976 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006977 /*
6978 * Cleanup.
6979 */
6980 if (repName != NULL)
6981 xmlFree(repName);
6982 /*
6983 * NOTE: Element Declaration Representation OK 4. will be checked at a
6984 * different layer.
6985 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006986 return (ret);
6987}
6988
6989/**
6990 * xmlSchemaParseUnion:
6991 * @ctxt: a schema validation context
6992 * @schema: the schema being built
6993 * @node: a subtree containing XML Schema informations
6994 *
6995 * parse a XML schema Union definition
6996 * *WARNING* this interface is highly subject to change
6997 *
William M. Bracke7091952004-05-11 15:09:58 +00006998 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006999 * 1 in case of success.
7000 */
7001static xmlSchemaTypePtr
7002xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007003 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007004{
7005 xmlSchemaTypePtr type, subtype, last = NULL;
7006 xmlNodePtr child = NULL;
7007 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007008 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007009
7010 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7011 return (NULL);
7012
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007013 snprintf((char *) name, 30, "#union%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007014 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007015 if (type == NULL)
7016 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00007017 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007018 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00007019 /*
7020 * Check for illegal attributes.
7021 */
7022 attr = node->properties;
7023 while (attr != NULL) {
7024 if (attr->ns == NULL) {
7025 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7026 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
7027 xmlSchemaPIllegalAttrErr(ctxt,
7028 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7029 NULL, type, attr);
7030 }
7031 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7032 xmlSchemaPIllegalAttrErr(ctxt,
7033 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7034 NULL, type, attr);
7035 }
7036 attr = attr->next;
7037 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007038 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007039 /*
7040 * Attribute "memberTypes". This is a list of QNames.
7041 * TODO: Validate the QNames.
7042 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007043 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00007044 /*
7045 * And now for the children...
7046 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007047 child = node->children;
7048 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007049 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7050 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007051 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007052 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007053 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00007054 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007055 if (subtype != NULL) {
7056 if (last == NULL) {
7057 type->subtypes = subtype;
7058 last = subtype;
7059 } else {
7060 last->next = subtype;
7061 last = subtype;
7062 }
7063 last->next = NULL;
7064 }
7065 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007066 }
7067 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007068 /* TODO: Think about the error code. */
7069 xmlSchemaPContentErr(ctxt,
7070 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
7071 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007072 }
7073 return (type);
7074}
7075
7076/**
7077 * xmlSchemaParseList:
7078 * @ctxt: a schema validation context
7079 * @schema: the schema being built
7080 * @node: a subtree containing XML Schema informations
7081 *
7082 * parse a XML schema List definition
7083 * *WARNING* this interface is highly subject to change
7084 *
William M. Bracke7091952004-05-11 15:09:58 +00007085 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007086 * 1 in case of success.
7087 */
7088static xmlSchemaTypePtr
7089xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007090 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007091{
7092 xmlSchemaTypePtr type, subtype;
7093 xmlNodePtr child = NULL;
7094 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007095 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007096
7097 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7098 return (NULL);
7099
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007100 snprintf((char *) name, 30, "#list%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007101 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007102 if (type == NULL)
7103 return (NULL);
7104 type->node = node;
7105 type->type = XML_SCHEMA_TYPE_LIST;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007106 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007107 /*
7108 * Check for illegal attributes.
7109 */
7110 attr = node->properties;
7111 while (attr != NULL) {
7112 if (attr->ns == NULL) {
7113 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7114 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
7115 xmlSchemaPIllegalAttrErr(ctxt,
7116 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7117 NULL, type, attr);
7118 }
7119 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7120 xmlSchemaPIllegalAttrErr(ctxt,
7121 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7122 NULL, type, attr);
7123 }
7124 attr = attr->next;
7125 }
7126 /*
7127 * Attribute "itemType".
7128 */
7129 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
7130 node, "itemType", &(type->baseNs), NULL, &(type->base));
7131 /*
7132 * And now for the children...
7133 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007134 child = node->children;
7135 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007136 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7137 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007138 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007139 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007140 if (IS_SCHEMA(child, "simpleType")) {
7141 if (type->base != NULL) {
7142 xmlSchemaPCustomErr(ctxt,
7143 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
7144 NULL, type, node,
7145 "The attribute 'itemType' and the <simpleType> child "
7146 "are mutually exclusive", NULL);
7147 } else {
7148 subtype = (xmlSchemaTypePtr)
7149 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7150 type->subtypes = subtype;
7151 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007152 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007153 }
7154 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007155 /* TODO: Think about the error code. */
7156 xmlSchemaPContentErr(ctxt,
7157 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
7158 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007159 }
7160 return (type);
7161}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007162
Daniel Veillard4255d502002-04-16 15:50:10 +00007163/**
7164 * xmlSchemaParseSimpleType:
7165 * @ctxt: a schema validation context
7166 * @schema: the schema being built
7167 * @node: a subtree containing XML Schema informations
7168 *
7169 * parse a XML schema Simple Type definition
7170 * *WARNING* this interface is highly subject to change
7171 *
William M. Bracke7091952004-05-11 15:09:58 +00007172 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00007173 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00007174 */
7175static xmlSchemaTypePtr
7176xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007177 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007178{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007179 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007180 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007181 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007182 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007183 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007184
7185 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7186 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007187
Daniel Veillardc0826a72004-08-10 14:17:33 +00007188 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007189 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007190 if (attr == NULL) {
7191 xmlSchemaPMissingAttrErr(ctxt,
7192 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007193 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007194 "name", NULL);
7195 return (NULL);
7196 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007197 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007198 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007199 return (NULL);
7200 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007201 }
7202
7203 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007204 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00007205
Daniel Veillard01fa6152004-06-29 17:04:39 +00007206 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007207 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00007208 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007209 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007210 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007211 if (type == NULL)
7212 return (NULL);
7213 type->node = node;
7214 type->type = XML_SCHEMA_TYPE_SIMPLE;
7215 /*
7216 * Check for illegal attributes.
7217 */
7218 attr = node->properties;
7219 while (attr != NULL) {
7220 if (attr->ns == NULL) {
7221 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
7222 xmlSchemaPIllegalAttrErr(ctxt,
7223 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007224 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007225 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007226 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7227 xmlSchemaPIllegalAttrErr(ctxt,
7228 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007229 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007230 }
7231 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007232 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007233 } else {
7234 /*
7235 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007236 *
7237 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007238 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007239 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007240 if (type == NULL)
7241 return (NULL);
7242 type->node = node;
7243 type->type = XML_SCHEMA_TYPE_SIMPLE;
7244 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
7245 /*
7246 * Check for illegal attributes.
7247 */
7248 attr = node->properties;
7249 while (attr != NULL) {
7250 if (attr->ns == NULL) {
7251 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7252 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007253 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007254 xmlSchemaPIllegalAttrErr(ctxt,
7255 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007256 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007257 }
7258 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7259 xmlSchemaPIllegalAttrErr(ctxt,
7260 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007261 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007262 }
7263 attr = attr->next;
7264 }
7265 /*
7266 * Attribute "final".
7267 */
7268 attr = xmlSchemaGetPropNode(node, "final");
7269 if (attr == NULL) {
7270 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
7271 } else {
7272 attrValue = xmlSchemaGetProp(ctxt, node, "final");
7273 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
7274 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
7275 XML_SCHEMAS_TYPE_FINAL_LIST,
7276 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
7277
7278 xmlSchemaPSimpleTypeErr(ctxt,
7279 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007280 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007281 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007282 attrValue, NULL, NULL, NULL);
7283 }
7284 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007285 }
7286 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007287 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007288 /*
7289 * And now for the children...
7290 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007291 oldCtxtType = ctxt->ctxtType;
7292 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007293 ctxt->ctxtType = type;
7294 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007295 child = node->children;
7296 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007297 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7298 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007299 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007300 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007301 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007302 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007303 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007304 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007305 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007306 subtype = (xmlSchemaTypePtr)
7307 xmlSchemaParseList(ctxt, schema, child);
7308 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007309 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007310 subtype = (xmlSchemaTypePtr)
7311 xmlSchemaParseUnion(ctxt, schema, child);
7312 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007313 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007314 type->subtypes = subtype;
7315 if ((child != NULL) || (subtype == NULL)) {
7316 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007317 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007318 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007319 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007320 ctxt->parentItem = oldParentItem;
7321 ctxt->ctxtType = oldCtxtType;
7322 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00007323
Daniel Veillard4255d502002-04-16 15:50:10 +00007324 return (type);
7325}
7326
7327
7328/**
7329 * xmlSchemaParseGroup:
7330 * @ctxt: a schema validation context
7331 * @schema: the schema being built
7332 * @node: a subtree containing XML Schema informations
7333 *
7334 * parse a XML schema Group definition
7335 * *WARNING* this interface is highly subject to change
7336 *
William M. Bracke7091952004-05-11 15:09:58 +00007337 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007338 * 1 in case of success.
7339 */
7340static xmlSchemaTypePtr
7341xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007342 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007343{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007344 xmlSchemaTypePtr item;
7345 xmlNodePtr child = NULL;
7346 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007347
7348 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007349 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007350
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007351 if (topLevel) {
7352 const xmlChar *name;
7353 /*
7354 * Parse as model group definition.
7355 */
7356 attr = xmlSchemaGetPropNode(node, "name");
7357 if (attr == NULL) {
7358 xmlSchemaPMissingAttrErr(ctxt,
7359 XML_SCHEMAP_S4S_ATTR_MISSING,
7360 NULL, NULL, node,
7361 "name", NULL);
7362 return (NULL);
7363 } else if (xmlSchemaPValAttrNode(ctxt,
7364 NULL, NULL, attr,
7365 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7366 return (NULL);
7367 }
7368 item = xmlSchemaAddGroup(ctxt, schema, name,
7369 schema->targetNamespace, node);
7370 if (item == NULL)
7371 return (NULL);
7372 item->node = node;
7373 item->type = XML_SCHEMA_TYPE_GROUP;
7374 item->flags |= XML_SCHEMAS_TYPE_GLOBAL;
7375 /*
7376 * Check for illegal attributes.
7377 */
7378 attr = node->properties;
7379 while (attr != NULL) {
7380 if (attr->ns == NULL) {
7381 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7382 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
7383 xmlSchemaPIllegalAttrErr(ctxt,
7384 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7385 NULL, item, attr);
7386 }
7387 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7388 xmlSchemaPIllegalAttrErr(ctxt,
7389 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7390 NULL, item, attr);
7391 }
7392 attr = attr->next;
7393 }
7394 xmlSchemaPValAttrID(ctxt, NULL, item, node, BAD_CAST "id");
7395 /*
7396 * And now for the children...
7397 */
7398 child = node->children;
7399 if (IS_SCHEMA(child, "annotation")) {
7400 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7401 child = child->next;
7402 }
7403 if (IS_SCHEMA(child, "all")) {
7404 item->subtypes = (xmlSchemaTypePtr)
7405 xmlSchemaParseAll(ctxt, schema, child);
7406 child = child->next;
7407 } else if (IS_SCHEMA(child, "choice")) {
7408 item->subtypes = xmlSchemaParseChoice(ctxt, schema, child);
7409 child = child->next;
7410 } else if (IS_SCHEMA(child, "sequence")) {
7411 item->subtypes = xmlSchemaParseSequence(ctxt, schema, child);
7412 child = child->next;
7413 }
7414 if (child != NULL) {
7415 xmlSchemaPContentErr(ctxt,
7416 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7417 NULL, item, node, child, NULL,
7418 "(annotation?, (all | choice | sequence)?)");
7419 }
7420 } else {
7421 const xmlChar *ref = NULL, *refNs = NULL, *refPrefix = NULL;
7422 int minOccurs, maxOccurs;
7423 char buf[40];
Daniel Veillard4255d502002-04-16 15:50:10 +00007424
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007425 /*
7426 * Parse as particle.
7427 */
7428 attr = xmlSchemaGetPropNode(node, "ref");
7429 if (attr == NULL) {
7430 xmlSchemaPMissingAttrErr(ctxt,
7431 XML_SCHEMAP_S4S_ATTR_MISSING,
7432 NULL, NULL, node,
7433 "ref", NULL);
7434 return (NULL);
7435 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
7436 attr, &refNs, &refPrefix, &ref) != 0) {
7437 return (NULL);
7438 }
7439
7440 /*
7441 * TODO: Validate the element even if no item is created
7442 * (i.e. min/maxOccurs == 0).
7443 */
7444 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7445 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7446 "(nonNegativeInteger | unbounded)");
7447 if ((minOccurs == 0) && (maxOccurs == 0)) {
7448 return (NULL);
7449 }
7450
7451 snprintf(buf, 39, "#grRef%d", ctxt->counter++ + 1);
7452 item = xmlSchemaAddGroup(ctxt, schema, (const xmlChar *)buf, NULL, node);
7453 if (item == NULL)
7454 return (NULL);
7455 item->node = node;
7456 item->type = XML_SCHEMA_TYPE_GROUP;
7457 item->ref = ref;
7458 item->refNs = refNs;
7459 xmlSchemaCheckReference(ctxt, schema, node, item, refNs);
7460 item->minOccurs = minOccurs;
7461 item->maxOccurs = maxOccurs;
7462 xmlSchemaPCheckParticleCorrect_2(ctxt, item,
7463 node, item->minOccurs, item->maxOccurs);
7464 /*
7465 * Check for illegal attributes.
7466 */
7467 attr = node->properties;
7468 while (attr != NULL) {
7469 if (attr->ns == NULL) {
7470 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7471 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7472 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
7473 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
7474 xmlSchemaPIllegalAttrErr(ctxt,
7475 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7476 NULL, item, attr);
7477 }
7478 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7479 xmlSchemaPIllegalAttrErr(ctxt,
7480 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7481 NULL, item, attr);
7482 }
7483 attr = attr->next;
7484 }
7485 xmlSchemaPValAttrID(ctxt, NULL, item, node, BAD_CAST "id");
7486 /*
7487 * And now for the children...
7488 */
7489 child = node->children;
7490 if (IS_SCHEMA(child, "annotation")) {
7491 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7492 child = child->next;
7493 }
7494 if (child != NULL) {
7495 xmlSchemaPContentErr(ctxt,
7496 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7497 NULL, item, node, child, NULL,
7498 "(annotation?, (all | choice | sequence)?)");
7499 }
7500 }
7501
7502 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00007503}
7504
7505/**
7506 * xmlSchemaParseAll:
7507 * @ctxt: a schema validation context
7508 * @schema: the schema being built
7509 * @node: a subtree containing XML Schema informations
7510 *
7511 * parse a XML schema All definition
7512 * *WARNING* this interface is highly subject to change
7513 *
William M. Bracke7091952004-05-11 15:09:58 +00007514 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007515 * 1 in case of success.
7516 */
7517static xmlSchemaTypePtr
7518xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007519 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007520{
7521 xmlSchemaTypePtr type, subtype, last = NULL;
7522 xmlNodePtr child = NULL;
7523 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007524 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007525
7526 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7527 return (NULL);
7528
7529
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007530 snprintf((char *) name, 30, "#all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007531 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007532 if (type == NULL)
7533 return (NULL);
7534 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00007535 type->type = XML_SCHEMA_TYPE_ALL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007536
7537 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007538
7539 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
7540 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007541
7542 oldcontainer = ctxt->container;
7543 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007544 child = node->children;
7545 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007546 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7547 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007548 }
7549 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007550 subtype = (xmlSchemaTypePtr)
7551 xmlSchemaParseElement(ctxt, schema, child, 0);
7552 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00007553 if (subtype->minOccurs > 1)
7554 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007555 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007556 NULL, NULL);
7557 if (subtype->maxOccurs > 1)
7558 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007559 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007560 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007561 if (last == NULL) {
7562 type->subtypes = subtype;
7563 last = subtype;
7564 } else {
7565 last->next = subtype;
7566 last = subtype;
7567 }
7568 last->next = NULL;
7569 }
7570 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007571 }
7572 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007573 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007574 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007575 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007576 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007577 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007578 return (type);
7579}
7580
7581/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007582 * xmlSchemaCleanupDoc:
7583 * @ctxt: a schema validation context
7584 * @node: the root of the document.
7585 *
7586 * removes unwanted nodes in a schemas document tree
7587 */
7588static void
7589xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
7590{
7591 xmlNodePtr delete, cur;
7592
7593 if ((ctxt == NULL) || (root == NULL)) return;
7594
7595 /*
7596 * Remove all the blank text nodes
7597 */
7598 delete = NULL;
7599 cur = root;
7600 while (cur != NULL) {
7601 if (delete != NULL) {
7602 xmlUnlinkNode(delete);
7603 xmlFreeNode(delete);
7604 delete = NULL;
7605 }
7606 if (cur->type == XML_TEXT_NODE) {
7607 if (IS_BLANK_NODE(cur)) {
7608 if (xmlNodeGetSpacePreserve(cur) != 1) {
7609 delete = cur;
7610 }
7611 }
7612 } else if ((cur->type != XML_ELEMENT_NODE) &&
7613 (cur->type != XML_CDATA_SECTION_NODE)) {
7614 delete = cur;
7615 goto skip_children;
7616 }
7617
7618 /*
7619 * Skip to next node
7620 */
7621 if (cur->children != NULL) {
7622 if ((cur->children->type != XML_ENTITY_DECL) &&
7623 (cur->children->type != XML_ENTITY_REF_NODE) &&
7624 (cur->children->type != XML_ENTITY_NODE)) {
7625 cur = cur->children;
7626 continue;
7627 }
7628 }
7629 skip_children:
7630 if (cur->next != NULL) {
7631 cur = cur->next;
7632 continue;
7633 }
7634
7635 do {
7636 cur = cur->parent;
7637 if (cur == NULL)
7638 break;
7639 if (cur == root) {
7640 cur = NULL;
7641 break;
7642 }
7643 if (cur->next != NULL) {
7644 cur = cur->next;
7645 break;
7646 }
7647 } while (cur != NULL);
7648 }
7649 if (delete != NULL) {
7650 xmlUnlinkNode(delete);
7651 xmlFreeNode(delete);
7652 delete = NULL;
7653 }
7654}
7655
William M. Brack2f2a6632004-08-20 23:09:47 +00007656
7657/**
7658 * xmlSchemaImportSchema
7659 *
7660 * @ctxt: a schema validation context
7661 * @schemaLocation: an URI defining where to find the imported schema
7662 *
7663 * import a XML schema
7664 * *WARNING* this interface is highly subject to change
7665 *
7666 * Returns -1 in case of error and 1 in case of success.
7667 */
7668#if 0
7669static xmlSchemaImportPtr
7670xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
7671 const xmlChar *schemaLocation)
7672{
7673 xmlSchemaImportPtr import;
7674 xmlSchemaParserCtxtPtr newctxt;
7675
7676 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7677 if (newctxt == NULL) {
7678 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
7679 NULL);
7680 return (NULL);
7681 }
7682 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
7683 /* Keep the same dictionnary for parsing, really */
7684 xmlDictReference(ctxt->dict);
7685 newctxt->dict = ctxt->dict;
7686 newctxt->includes = 0;
7687 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
7688
7689 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
7690 ctxt->userData);
7691
7692 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7693 if (import == NULL) {
7694 xmlSchemaPErrMemory(NULL, "allocating imported schema",
7695 NULL);
7696 xmlSchemaFreeParserCtxt(newctxt);
7697 return (NULL);
7698 }
7699
7700 memset(import, 0, sizeof(xmlSchemaImport));
7701 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7702 import->schema = xmlSchemaParse(newctxt);
7703
7704 if (import->schema == NULL) {
7705 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00007706 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00007707 "Failed to import schema from location \"%s\".\n",
7708 schemaLocation, NULL);
7709
7710 xmlSchemaFreeParserCtxt(newctxt);
7711 /* The schemaLocation is held by the dictionary.
7712 if (import->schemaLocation != NULL)
7713 xmlFree((xmlChar *)import->schemaLocation);
7714 */
7715 xmlFree(import);
7716 return NULL;
7717 }
7718
7719 xmlSchemaFreeParserCtxt(newctxt);
7720 return import;
7721}
7722#endif
7723
7724static void
7725xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
7726{
7727 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7728 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
7729
7730 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
7731 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
7732
7733 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7734 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
7735 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7736 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
7737 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
7738 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
7739 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
7740 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
7741
7742 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7743 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
7744 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7745 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
7746 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7747 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
7748}
7749
7750static void
7751xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
7752 xmlSchemaPtr schema,
7753 xmlNodePtr node)
7754{
7755 xmlAttrPtr attr;
7756 const xmlChar *val;
7757
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007758 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7759 if (schema->version == NULL)
7760 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
7761 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
7762 else
7763 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
7764 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
7765
William M. Brack2f2a6632004-08-20 23:09:47 +00007766 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
7767 if (attr != NULL) {
7768 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7769 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7770 XML_SCHEMAS_QUALIF_ELEM) != 0) {
7771 xmlSchemaPSimpleTypeErr(ctxt,
7772 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
7773 NULL, NULL, (xmlNodePtr) attr, NULL,
7774 "(qualified | unqualified)", val, NULL, NULL, NULL);
7775 }
7776 }
7777
7778 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
7779 if (attr != NULL) {
7780 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7781 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7782 XML_SCHEMAS_QUALIF_ATTR) != 0) {
7783 xmlSchemaPSimpleTypeErr(ctxt,
7784 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
7785 NULL, NULL, (xmlNodePtr) attr, NULL,
7786 "(qualified | unqualified)", val, NULL, NULL, NULL);
7787 }
7788 }
7789
7790 attr = xmlSchemaGetPropNode(node, "finalDefault");
7791 if (attr != NULL) {
7792 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7793 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7794 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
7795 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
7796 -1,
7797 XML_SCHEMAS_FINAL_DEFAULT_LIST,
7798 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
7799 xmlSchemaPSimpleTypeErr(ctxt,
7800 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7801 NULL, NULL, (xmlNodePtr) attr, NULL,
7802 "(#all | List of (extension | restriction | list | union))",
7803 val, NULL, NULL, NULL);
7804 }
7805 }
7806
7807 attr = xmlSchemaGetPropNode(node, "blockDefault");
7808 if (attr != NULL) {
7809 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7810 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7811 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
7812 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
7813 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
7814 xmlSchemaPSimpleTypeErr(ctxt,
7815 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7816 NULL, NULL, (xmlNodePtr) attr, NULL,
7817 "(#all | List of (extension | restriction | substitution))",
7818 val, NULL, NULL, NULL);
7819 }
7820 }
7821}
7822
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007823/**
7824 * xmlSchemaParseSchemaTopLevel:
7825 * @ctxt: a schema validation context
7826 * @schema: the schemas
7827 * @nodes: the list of top level nodes
7828 *
7829 * Returns the internal XML Schema structure built from the resource or
7830 * NULL in case of error
7831 */
7832static void
7833xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
7834 xmlSchemaPtr schema, xmlNodePtr nodes)
7835{
7836 xmlNodePtr child;
7837 xmlSchemaAnnotPtr annot;
7838
7839 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
7840 return;
7841
7842 child = nodes;
7843 while ((IS_SCHEMA(child, "include")) ||
7844 (IS_SCHEMA(child, "import")) ||
7845 (IS_SCHEMA(child, "redefine")) ||
7846 (IS_SCHEMA(child, "annotation"))) {
7847 if (IS_SCHEMA(child, "annotation")) {
7848 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7849 if (schema->annot == NULL)
7850 schema->annot = annot;
7851 else
7852 xmlSchemaFreeAnnot(annot);
7853 } else if (IS_SCHEMA(child, "import")) {
7854 xmlSchemaParseImport(ctxt, schema, child);
7855 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007856 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007857 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007858 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007859 } else if (IS_SCHEMA(child, "redefine")) {
7860 TODO
7861 }
7862 child = child->next;
7863 }
7864 while (child != NULL) {
7865 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007866 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007867 child = child->next;
7868 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007869 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007870 child = child->next;
7871 } else if (IS_SCHEMA(child, "element")) {
7872 xmlSchemaParseElement(ctxt, schema, child, 1);
7873 child = child->next;
7874 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00007875 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007876 child = child->next;
7877 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007878 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007879 child = child->next;
7880 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007881 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007882 child = child->next;
7883 } else if (IS_SCHEMA(child, "notation")) {
7884 xmlSchemaParseNotation(ctxt, schema, child);
7885 child = child->next;
7886 } else {
7887 xmlSchemaPErr2(ctxt, NULL, child,
7888 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007889 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007890 child->name, NULL);
7891 child = child->next;
7892 }
7893 while (IS_SCHEMA(child, "annotation")) {
7894 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7895 if (schema->annot == NULL)
7896 schema->annot = annot;
7897 else
7898 xmlSchemaFreeAnnot(annot);
7899 child = child->next;
7900 }
7901 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007902 ctxt->parentItem = NULL;
7903 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007904}
7905
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007906static xmlSchemaImportPtr
7907xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
7908 xmlHashTablePtr *imports,
7909 const xmlChar *nsName)
7910{
7911 xmlSchemaImportPtr ret;
7912
7913 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00007914 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007915 if (*imports == NULL) {
7916 xmlSchemaPCustomErr(ctxt,
7917 XML_SCHEMAP_FAILED_BUILD_IMPORT,
7918 NULL, NULL, (xmlNodePtr) ctxt->doc,
7919 "Internal error: failed to build the import table",
7920 NULL);
7921 return (NULL);
7922 }
7923 }
7924 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7925 if (ret == NULL) {
7926 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
7927 return (NULL);
7928 }
7929 memset(ret, 0, sizeof(xmlSchemaImport));
7930 if (nsName == NULL)
7931 nsName = XML_SCHEMAS_NO_NAMESPACE;
7932 xmlHashAddEntry(*imports, nsName, ret);
7933
7934 return (ret);
7935}
7936
7937static int
7938xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007939 xmlSchemaPtr schema,
7940 xmlNodePtr node,
7941 const xmlChar *nsName,
7942 const xmlChar *location,
7943 xmlDocPtr *doc,
7944 const xmlChar **targetNamespace,
7945 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007946{
7947 xmlParserCtxtPtr parserCtxt;
7948 xmlSchemaImportPtr import;
7949 const xmlChar *ns;
7950 xmlNodePtr root;
7951
7952 /*
7953 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
7954 * <xsi:noNamespaceSchemaLocation>.
7955 */
7956 *doc = NULL;
7957 /*
7958 * Given that the schemaLocation [attribute] is only a hint, it is open
7959 * to applications to ignore all but the first <import> for a given
7960 * namespace, regardless of the ·actual value· of schemaLocation, but
7961 * such a strategy risks missing useful information when new
7962 * schemaLocations are offered.
7963 *
7964 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
7965 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
7966 * valid or not.
7967 * We will follow XSV here.
7968 */
7969 if (location == NULL) {
7970 /*
7971 * Schema Document Location Strategy:
7972 *
7973 * 3 Based on the namespace name, identify an existing schema document,
7974 * either as a resource which is an XML document or a <schema> element
7975 * information item, in some local schema repository;
7976 *
7977 * 5 Attempt to resolve the namespace name to locate such a resource.
7978 *
7979 * NOTE: Those stategies are not supported, so we will skip.
7980 */
7981 return (0);
7982 }
7983 if (nsName == NULL)
7984 ns = XML_SCHEMAS_NO_NAMESPACE;
7985 else
7986 ns = nsName;
7987
7988 import = xmlHashLookup(schema->schemasImports, ns);
7989 if (import != NULL) {
7990 /*
7991 * There was a valid resource for the specified namespace already
7992 * defined, so skip.
7993 * TODO: This might be changed someday to allow import of
7994 * components from multiple documents for a single target namespace.
7995 */
7996 return (0);
7997 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007998
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007999 /*
8000 * Schema Document Location Strategy:
8001 *
8002 * 2 Based on the location URI, identify an existing schema document,
8003 * either as a resource which is an XML document or a <schema> element
8004 * information item, in some local schema repository;
8005 *
8006 * 4 Attempt to resolve the location URI, to locate a resource on the
8007 * web which is or contains or references a <schema> element;
8008 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8009 *
8010 */
8011 if ((absolute == 0) && (node != NULL)) {
8012 xmlChar *base, *URI;
8013
8014 base = xmlNodeGetBase(node->doc, node);
8015 if (base == NULL) {
8016 URI = xmlBuildURI(location, node->doc->URL);
8017 } else {
8018 URI = xmlBuildURI(location, base);
8019 xmlFree(base);
8020 }
8021 if (URI != NULL) {
8022 location = xmlDictLookup(ctxt->dict, URI, -1);
8023 xmlFree(URI);
8024 }
8025 }
8026 parserCtxt = xmlNewParserCtxt();
8027 if (parserCtxt == NULL) {
8028 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8029 "allocating a parser context", NULL);
8030 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008031 }
8032
8033 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
8034 xmlDictFree(parserCtxt->dict);
8035 parserCtxt->dict = ctxt->dict;
8036 xmlDictReference(parserCtxt->dict);
8037 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008038
8039 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
8040 NULL, SCHEMAS_PARSE_OPTIONS);
8041
8042 /*
8043 * 2.1 The referent is (a fragment of) a resource which is an
8044 * XML document (see clause 1.1), which in turn corresponds to
8045 * a <schema> element information item in a well-formed information
8046 * set, which in turn corresponds to a valid schema.
8047 * TODO: What to do with the "fragment" stuff?
8048 *
8049 * 2.2 The referent is a <schema> element information item in
8050 * a well-formed information set, which in turn corresponds
8051 * to a valid schema.
8052 * NOTE: 2.2 won't apply, since only XML documents will be processed
8053 * here.
8054 */
8055 if (*doc == NULL) {
8056 xmlErrorPtr lerr;
8057 /*
8058 * It is *not* an error for the application schema reference
8059 * strategy to fail.
8060 *
8061 * If the doc is NULL and the parser error is an IO error we
8062 * will assume that the resource could not be located or accessed.
8063 *
8064 * TODO: Try to find specific error codes to react only on
8065 * localisation failures.
8066 *
8067 * TODO, FIXME: Check the spec: is a namespace added to the imported
8068 * namespaces, even if the schemaLocation did not provide
8069 * a resource? I guess so, since omitting the "schemaLocation"
8070 * attribute, imports a namespace as well.
8071 */
8072 lerr = xmlGetLastError();
8073 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
8074 xmlFreeParserCtxt(parserCtxt);
8075 return(0);
8076 }
8077
8078 xmlSchemaPCustomErr(ctxt,
8079 XML_SCHEMAP_SRC_IMPORT_2_1,
8080 NULL, NULL, node,
8081 "Failed to parse the resource '%s' for import",
8082 location);
8083 xmlFreeParserCtxt(parserCtxt);
8084 return(XML_SCHEMAP_SRC_IMPORT_2_1);
8085 }
8086 xmlFreeParserCtxt(parserCtxt);
8087
8088 root = xmlDocGetRootElement(*doc);
8089 if (root == NULL) {
8090 xmlSchemaPCustomErr(ctxt,
8091 XML_SCHEMAP_SRC_IMPORT_2_1,
8092 NULL, NULL, node,
8093 "The XML document '%s' to be imported has no document "
8094 "element", location);
8095 xmlFreeDoc(*doc);
8096 *doc = NULL;
8097 return (XML_SCHEMAP_SRC_IMPORT_2_1);
8098 }
8099
8100 xmlSchemaCleanupDoc(ctxt, root);
8101
8102 if (!IS_SCHEMA(root, "schema")) {
8103 xmlSchemaPCustomErr(ctxt,
8104 XML_SCHEMAP_SRC_IMPORT_2_1,
8105 NULL, NULL, node,
8106 "The XML document '%s' to be imported is not a XML schema document",
8107 location);
8108 xmlFreeDoc(*doc);
8109 *doc = NULL;
8110 return (XML_SCHEMAP_SRC_IMPORT_2_1);
8111 }
8112 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
8113 /*
8114 * Schema Representation Constraint: Import Constraints and Semantics
8115 */
8116 if (nsName == NULL) {
8117 if (*targetNamespace != NULL) {
8118 xmlSchemaPCustomErr(ctxt,
8119 XML_SCHEMAP_SRC_IMPORT_3_2,
8120 NULL, NULL, node,
8121 "The XML schema to be imported is not expected "
8122 "to have a target namespace; this differs from "
8123 "its target namespace of '%s'", *targetNamespace);
8124 xmlFreeDoc(*doc);
8125 *doc = NULL;
8126 return (XML_SCHEMAP_SRC_IMPORT_3_2);
8127 }
8128 } else {
8129 if (*targetNamespace == NULL) {
8130 xmlSchemaPCustomErr(ctxt,
8131 XML_SCHEMAP_SRC_IMPORT_3_1,
8132 NULL, NULL, node,
8133 "The XML schema to be imported is expected to have a target "
8134 "namespace of '%s'", nsName);
8135 xmlFreeDoc(*doc);
8136 *doc = NULL;
8137 return (XML_SCHEMAP_SRC_IMPORT_3_1);
8138 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
8139 xmlSchemaPCustomErrExt(ctxt,
8140 XML_SCHEMAP_SRC_IMPORT_3_1,
8141 NULL, NULL, node,
8142 "The XML schema to be imported is expected to have a "
8143 "target namespace of '%s'; this differs from "
8144 "its target namespace of '%s'",
8145 nsName, *targetNamespace, NULL);
8146 xmlFreeDoc(*doc);
8147 *doc = NULL;
8148 return (XML_SCHEMAP_SRC_IMPORT_3_1);
8149 }
8150 }
8151
8152 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
8153 if (import == NULL) {
8154 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
8155 NULL, NULL, NULL,
8156 "Internal error: xmlSchemaAcquireSchemaDoc, "
8157 "failed to build import table", NULL);
8158 xmlFreeDoc(*doc);
8159 *doc = NULL;
8160 return (-1);
8161 }
8162 import->schemaLocation = location;
8163 import->doc = *doc;
8164 return (0);
8165}
William M. Brack2f2a6632004-08-20 23:09:47 +00008166
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008167static void
8168xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
8169 xmlSchemaPtr schema,
8170 const xmlChar *targetNamespace,
8171 xmlNodePtr node)
8172{
8173 const xmlChar *oldURL, **oldLocImps, *oldTNS;
8174 int oldFlags, oldNumLocImps, oldSizeLocImps;
8175
8176 /*
8177 * Save and reset the context & schema.
8178 */
8179 oldURL = pctxt->URL;
8180 /* TODO: Is using the doc->URL here correct? */
8181 pctxt->URL = node->doc->URL;
8182 oldLocImps = pctxt->localImports;
8183 pctxt->localImports = NULL;
8184 oldNumLocImps = pctxt->nbLocalImports;
8185 pctxt->nbLocalImports = 0;
8186 oldSizeLocImps = pctxt->sizeLocalImports;
8187 pctxt->sizeLocalImports = 0;
8188 oldFlags = schema->flags;
8189 xmlSchemaClearSchemaDefaults(schema);
8190 oldTNS = schema->targetNamespace;
8191 schema->targetNamespace = targetNamespace;
8192 /*
8193 * Parse the schema.
8194 */
8195 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
8196 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
8197 /*
8198 * Restore the context & schema.
8199 */
8200 schema->flags = oldFlags;
8201 schema->targetNamespace = oldTNS;
8202 if (pctxt->localImports != NULL)
8203 xmlFree((xmlChar *) pctxt->localImports);
8204 pctxt->localImports = oldLocImps;
8205 pctxt->nbLocalImports = oldNumLocImps;
8206 pctxt->sizeLocalImports = oldSizeLocImps;
8207 pctxt->URL = oldURL;
8208}
8209
William M. Brack2f2a6632004-08-20 23:09:47 +00008210/**
8211 * xmlSchemaParseImport:
8212 * @ctxt: a schema validation context
8213 * @schema: the schema being built
8214 * @node: a subtree containing XML Schema informations
8215 *
8216 * parse a XML schema Import definition
8217 * *WARNING* this interface is highly subject to change
8218 *
8219 * Returns 0 in case of success, a positive error code if
8220 * not valid and -1 in case of an internal error.
8221 */
8222static int
8223xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8224 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008225{
8226 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008227 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008228 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008229 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00008230 xmlAttrPtr attr;
8231 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008232 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00008233
8234 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8235 return (-1);
8236
8237 /*
8238 * Check for illegal attributes.
8239 */
8240 attr = node->properties;
8241 while (attr != NULL) {
8242 if (attr->ns == NULL) {
8243 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8244 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
8245 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
8246 xmlSchemaPIllegalAttrErr(ctxt,
8247 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8248 NULL, NULL, attr);
8249 }
8250 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8251 xmlSchemaPIllegalAttrErr(ctxt,
8252 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8253 NULL, NULL, attr);
8254 }
8255 attr = attr->next;
8256 }
8257 /*
8258 * Extract and validate attributes.
8259 */
8260 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
8261 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008262 &namespaceName) != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008263 xmlSchemaPSimpleTypeErr(ctxt,
8264 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
8265 NULL, NULL, node,
8266 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008267 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00008268 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
8269 }
8270
8271 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
8272 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
8273 &schemaLocation) != 0) {
8274 xmlSchemaPSimpleTypeErr(ctxt,
8275 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
8276 NULL, NULL, node,
8277 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008278 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00008279 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
8280 }
8281 /*
8282 * And now for the children...
8283 */
8284 child = node->children;
8285 if (IS_SCHEMA(child, "annotation")) {
8286 /*
8287 * the annotation here is simply discarded ...
8288 */
8289 child = child->next;
8290 }
8291 if (child != NULL) {
8292 xmlSchemaPContentErr(ctxt,
8293 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
8294 NULL, NULL, node, child, NULL,
8295 "(annotation?)");
8296 }
8297 /*
8298 * Apply additional constraints.
8299 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008300 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008301 /*
8302 * 1.1 If the namespace [attribute] is present, then its ·actual value·
8303 * must not match the ·actual value· of the enclosing <schema>'s
8304 * targetNamespace [attribute].
8305 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008306 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008307 xmlSchemaPCustomErr(ctxt,
8308 XML_SCHEMAP_SRC_IMPORT_1_1,
8309 NULL, NULL, node,
8310 "The value of the attribute 'namespace' must not match "
8311 "the target namespace '%s' of the importing schema",
8312 schema->targetNamespace);
8313 return (XML_SCHEMAP_SRC_IMPORT_1_1);
8314 }
8315 } else {
8316 /*
8317 * 1.2 If the namespace [attribute] is not present, then the enclosing
8318 * <schema> must have a targetNamespace [attribute].
8319 */
8320 if (schema->targetNamespace == NULL) {
8321 xmlSchemaPCustomErr(ctxt,
8322 XML_SCHEMAP_SRC_IMPORT_1_2,
8323 NULL, NULL, node,
8324 "The attribute 'namespace' must be existent if "
8325 "the importing schema has no target namespace",
8326 NULL);
8327 return (XML_SCHEMAP_SRC_IMPORT_1_2);
8328 }
8329 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008330 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008331 * Add the namespace to the list of locally imported namespace.
8332 */
8333 if (ctxt->localImports == NULL) {
8334 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
8335 sizeof(const xmlChar*));
8336 ctxt->sizeLocalImports = 10;
8337 ctxt->nbLocalImports = 0;
8338 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
8339 ctxt->sizeLocalImports *= 2;
8340 ctxt->localImports = (const xmlChar **) xmlRealloc(
8341 (xmlChar **) ctxt->localImports,
8342 ctxt->sizeLocalImports * sizeof(const xmlChar*));
8343 }
8344 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
8345 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008346 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00008347 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008348 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008349 schemaLocation, &doc, &targetNamespace, 0);
8350 if (ret != 0) {
8351 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00008352 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008353 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008354 } else if (doc != NULL) {
8355 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
8356 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00008357 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008358
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008359 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008360}
8361
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008362/**
8363 * xmlSchemaParseInclude:
8364 * @ctxt: a schema validation context
8365 * @schema: the schema being built
8366 * @node: a subtree containing XML Schema informations
8367 *
8368 * parse a XML schema Include definition
8369 *
William M. Bracke7091952004-05-11 15:09:58 +00008370 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008371 * 1 in case of success.
8372 */
8373static int
8374xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8375 xmlNodePtr node)
8376{
8377 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008378 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008379 xmlDocPtr doc = NULL;
8380 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00008381 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008382 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00008383 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008384 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008385
8386
8387 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8388 return (-1);
8389
8390 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00008391 * Check for illegal attributes.
8392 */
8393 attr = node->properties;
8394 while (attr != NULL) {
8395 if (attr->ns == NULL) {
8396 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8397 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
8398 xmlSchemaPIllegalAttrErr(ctxt,
8399 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8400 NULL, NULL, attr);
8401 }
8402 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8403 xmlSchemaPIllegalAttrErr(ctxt,
8404 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8405 NULL, NULL, attr);
8406 }
8407 attr = attr->next;
8408 }
8409 /*
8410 * Extract and validate attributes.
8411 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008412 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008413 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008414 * Preliminary step, extract the URI-Reference for the include and
8415 * make an URI from the base.
8416 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008417 attr = xmlSchemaGetPropNode(node, "schemaLocation");
8418 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008419 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008420 xmlChar *uri = NULL;
8421
8422 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8423 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008424 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008425 base = xmlNodeGetBase(node->doc, node);
8426 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008427 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008428 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00008429 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008430 xmlFree(base);
8431 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008432 if (uri == NULL) {
8433 xmlSchemaPErr(ctxt,
8434 node,
8435 XML_SCHEMAP_INTERNAL,
8436 "Internal error: xmlSchemaParseInclude, "
8437 "could not build an URI from the schemaLocation.\n",
8438 NULL, NULL);
8439 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008440 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008441 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
8442 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008443 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00008444 xmlSchemaPMissingAttrErr(ctxt,
8445 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
8446 NULL, NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008447 goto exit_invalid;
8448 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008449 /*
8450 * And now for the children...
8451 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008452 child = node->children;
8453 while (IS_SCHEMA(child, "annotation")) {
8454 /*
8455 * the annotations here are simply discarded ...
8456 */
8457 child = child->next;
8458 }
8459 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008460 xmlSchemaPContentErr(ctxt,
8461 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
8462 NULL, NULL, node, child, NULL,
8463 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008464 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008465 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008466 * Report self-inclusion.
8467 */
8468 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
8469 xmlSchemaPCustomErr(ctxt,
8470 XML_SCHEMAP_SRC_INCLUDE,
8471 NULL, NULL, node,
8472 "The schema document '%s' cannot include itself.",
8473 schemaLocation);
8474 return (XML_SCHEMAP_SRC_INCLUDE);
8475 }
8476 /*
8477 * Check if this one was already processed to avoid incorrect
8478 * duplicate component errors and infinite circular inclusion.
8479 */
8480 include = schema->includes;
8481 while (include != NULL) {
8482 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
8483 targetNamespace = include->origTargetNamespace;
8484 if (targetNamespace == NULL) {
8485 /*
8486 * Chameleon include: skip only if it was build for
8487 * the targetNamespace of the including schema.
8488 */
8489 if (xmlStrEqual(schema->targetNamespace,
8490 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008491 goto check_targetNamespace;
8492 }
8493 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008494 goto check_targetNamespace;
8495 }
8496 }
8497 include = include->next;
8498 }
8499 /*
8500 * First step is to parse the input document into an DOM/Infoset
8501 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008502 */
8503 parserCtxt = xmlNewParserCtxt();
8504 if (parserCtxt == NULL) {
8505 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
8506 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008507 goto exit_failure;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008508 }
8509
8510 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
8511 xmlDictFree(parserCtxt->dict);
8512 parserCtxt->dict = ctxt->dict;
8513 xmlDictReference(parserCtxt->dict);
8514 }
8515
8516 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
8517 NULL, SCHEMAS_PARSE_OPTIONS);
8518 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008519 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008520 /*
8521 * TODO: It is not an error for the ·actual value· of the
8522 * schemaLocation [attribute] to fail to resolve it all, in which
8523 * case no corresponding inclusion is performed.
8524 * So do we need a warning report here?
8525 */
8526 xmlSchemaPCustomErr(ctxt,
8527 XML_SCHEMAP_FAILED_LOAD,
8528 NULL, NULL, node,
8529 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008530 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008531 }
8532
8533 /*
8534 * Then extract the root of the schema
8535 */
8536 root = xmlDocGetRootElement(doc);
8537 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008538 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008539 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00008540 NULL, NULL, node,
8541 "The included document '%s' has no document "
8542 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008543 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008544 }
8545
8546 /*
8547 * Remove all the blank text nodes
8548 */
8549 xmlSchemaCleanupDoc(ctxt, root);
8550
8551 /*
8552 * Check the schemas top level element
8553 */
8554 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008555 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008556 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00008557 NULL, NULL, node,
8558 "The document '%s' to be included is not a schema document",
8559 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008560 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008561 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008562
William M. Brack2f2a6632004-08-20 23:09:47 +00008563 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008564 /*
8565 * 2.1 SII has a targetNamespace [attribute], and its ·actual
8566 * value· is identical to the ·actual value· of the targetNamespace
8567 * [attribute] of SIIÂ’ (which must have such an [attribute]).
8568 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008569check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00008570 if (targetNamespace != NULL) {
8571 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008572 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008573 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008574 NULL, NULL, node,
8575 "The target namespace of the included schema "
8576 "'%s' has to be absent, since the including schema "
8577 "has no target namespace",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008578 schemaLocation);
8579 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00008580 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
8581 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008582 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008583 NULL, NULL, node,
8584 "The target namespace '%s' of the included schema '%s' "
8585 "differs from '%s' of the including schema",
8586 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008587 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008588 }
8589 } else if (schema->targetNamespace != NULL) {
8590 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
8591 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
8592 } else
8593 wasConvertingNs = 1;
8594 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008595
8596 if (include != NULL)
8597 goto exit;
8598
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008599 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008600 * URGENT TODO: If the schema is a chameleon-include then copy the
8601 * components into the including schema and modify the targetNamespace
8602 * of those components, do nothing otherwise.
8603 * NOTE: This is currently worked-around by compiling the chameleon
8604 * for every destinct including targetNamespace; thus not performant at
8605 * the moment.
8606 * TODO: Check when the namespace in wildcards for chameleons needs
8607 * to be converted: before we built wildcard intersections or after.
8608 */
8609 /*
8610 * Register the include.
8611 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008612 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
8613 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008614 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
8615 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008616 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008617 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008618 include->next = schema->includes;
8619 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008620 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008621 * TODO: Use the resolved URI for the this location, since it might
8622 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008623 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008624 include->schemaLocation = schemaLocation;
8625 include->doc = doc;
8626 /*
8627 * In case of chameleons, the original target namespace will differ
8628 * from the resulting namespace.
8629 */
8630 include->origTargetNamespace = targetNamespace;
8631 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00008632#ifdef DEBUG_INCLUDES
8633 if (targetNamespace != schema->targetNamespace)
8634 xmlGenericError(xmlGenericErrorContext,
8635 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
8636 " into TNS '%s'\n", schemaLocation,
8637 targetNamespace, schema->targetNamespace);
8638 else
8639 xmlGenericError(xmlGenericErrorContext,
8640 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
8641 targetNamespace);
8642#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008643 /*
8644 * Compile the included schema.
8645 */
8646 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
8647
8648exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00008649 /*
8650 * Remove the converting flag.
8651 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008652 if ((wasConvertingNs == 0) &&
8653 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00008654 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008655 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008656
8657exit_invalid:
8658 if (doc != NULL) {
8659 if (include != NULL)
8660 include->doc = NULL;
8661 xmlFreeDoc(doc);
8662 }
8663 return (ctxt->err);
8664
8665exit_failure:
8666 if (doc != NULL) {
8667 if (include != NULL)
8668 include->doc = NULL;
8669 xmlFreeDoc(doc);
8670 }
8671 return (-1);
8672
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008673}
8674
8675/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008676 * xmlSchemaParseChoice:
8677 * @ctxt: a schema validation context
8678 * @schema: the schema being built
8679 * @node: a subtree containing XML Schema informations
8680 *
8681 * parse a XML schema Choice definition
8682 * *WARNING* this interface is highly subject to change
8683 *
William M. Bracke7091952004-05-11 15:09:58 +00008684 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008685 * 1 in case of success.
8686 */
8687static xmlSchemaTypePtr
8688xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008689 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008690{
8691 xmlSchemaTypePtr type, subtype, last = NULL;
8692 xmlNodePtr child = NULL;
8693 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008694 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008695 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008696
8697 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8698 return (NULL);
8699
8700
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008701 snprintf((char *) name, 30, "#ch%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008702 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008703 if (type == NULL)
8704 return (NULL);
8705 type->node = node;
8706 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008707 /*
8708 * Check for illegal attributes.
8709 */
8710 attr = node->properties;
8711 while (attr != NULL) {
8712 if (attr->ns == NULL) {
8713 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8714 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8715 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8716 xmlSchemaPIllegalAttrErr(ctxt,
8717 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8718 NULL, type, attr);
8719 }
8720 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8721 xmlSchemaPIllegalAttrErr(ctxt,
8722 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8723 NULL, type, attr);
8724 }
8725 attr = attr->next;
8726 }
8727 /*
8728 * Extract and validate attributes.
8729 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008730 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008731 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8732 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8733 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008734 /*
8735 * And now for the children...
8736 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008737 oldcontainer = ctxt->container;
8738 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008739 child = node->children;
8740 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008741 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8742 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008743 }
8744 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008745 (IS_SCHEMA(child, "group")) ||
8746 (IS_SCHEMA(child, "any")) ||
8747 (IS_SCHEMA(child, "choice")) ||
8748 (IS_SCHEMA(child, "sequence"))) {
8749 subtype = NULL;
8750 if (IS_SCHEMA(child, "element")) {
8751 subtype = (xmlSchemaTypePtr)
8752 xmlSchemaParseElement(ctxt, schema, child, 0);
8753 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008754 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008755 } else if (IS_SCHEMA(child, "any")) {
8756 subtype = xmlSchemaParseAny(ctxt, schema, child);
8757 } else if (IS_SCHEMA(child, "sequence")) {
8758 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8759 } else if (IS_SCHEMA(child, "choice")) {
8760 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8761 }
8762 if (subtype != NULL) {
8763 if (last == NULL) {
8764 type->subtypes = subtype;
8765 last = subtype;
8766 } else {
8767 last->next = subtype;
8768 last = subtype;
8769 }
8770 last->next = NULL;
8771 }
8772 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008773 }
8774 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008775 /* TODO: error code. */
8776 xmlSchemaPContentErr(ctxt,
8777 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
8778 NULL, type, node, child, NULL,
8779 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008780 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008781 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008782 return (type);
8783}
8784
8785/**
8786 * xmlSchemaParseSequence:
8787 * @ctxt: a schema validation context
8788 * @schema: the schema being built
8789 * @node: a subtree containing XML Schema informations
8790 *
8791 * parse a XML schema Sequence definition
8792 * *WARNING* this interface is highly subject to change
8793 *
William M. Bracke7091952004-05-11 15:09:58 +00008794 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008795 * 1 in case of success.
8796 */
8797static xmlSchemaTypePtr
8798xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008799 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008800{
8801 xmlSchemaTypePtr type, subtype, last = NULL;
8802 xmlNodePtr child = NULL;
8803 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008804 xmlAttrPtr attr;
8805 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008806
8807 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8808 return (NULL);
8809
William M. Brack2f2a6632004-08-20 23:09:47 +00008810 oldcontainer = ctxt->container;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008811 snprintf((char *) name, 30, "#seq%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008812 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008813 if (type == NULL)
8814 return (NULL);
8815 type->node = node;
8816 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008817 /*
8818 * Check for illegal attributes.
8819 */
8820 attr = node->properties;
8821 while (attr != NULL) {
8822 if (attr->ns == NULL) {
8823 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8824 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8825 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8826 xmlSchemaPIllegalAttrErr(ctxt,
8827 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8828 NULL, type, attr);
8829 }
8830 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8831 xmlSchemaPIllegalAttrErr(ctxt,
8832 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8833 NULL, type, attr);
8834 }
8835 attr = attr->next;
8836 }
8837 /*
8838 * Extract and validate attributes.
8839 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008840 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008841 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8842 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8843 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008844 /*
8845 * And now for the children...
8846 */
8847 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008848 child = node->children;
8849 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008850 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8851 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008852 }
8853 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008854 (IS_SCHEMA(child, "group")) ||
8855 (IS_SCHEMA(child, "any")) ||
8856 (IS_SCHEMA(child, "choice")) ||
8857 (IS_SCHEMA(child, "sequence"))) {
8858 subtype = NULL;
8859 if (IS_SCHEMA(child, "element")) {
8860 subtype = (xmlSchemaTypePtr)
8861 xmlSchemaParseElement(ctxt, schema, child, 0);
8862 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008863 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008864 } else if (IS_SCHEMA(child, "any")) {
8865 subtype = xmlSchemaParseAny(ctxt, schema, child);
8866 } else if (IS_SCHEMA(child, "choice")) {
8867 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8868 } else if (IS_SCHEMA(child, "sequence")) {
8869 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8870 }
8871 if (subtype != NULL) {
8872 if (last == NULL) {
8873 type->subtypes = subtype;
8874 last = subtype;
8875 } else {
8876 last->next = subtype;
8877 last = subtype;
8878 }
8879 last->next = NULL;
8880 }
8881 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008882 }
8883 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008884 xmlSchemaPContentErr(ctxt,
8885 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
8886 NULL, type, node, child, NULL,
8887 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008888 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008889 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008890
8891 return (type);
8892}
8893
8894/**
8895 * xmlSchemaParseRestriction:
8896 * @ctxt: a schema validation context
8897 * @schema: the schema being built
8898 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00008899 *
8900 * parse a XML schema Restriction definition
8901 * *WARNING* this interface is highly subject to change
8902 *
8903 * Returns the type definition or NULL in case of error
8904 */
8905static xmlSchemaTypePtr
8906xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008907 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008908{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008909 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00008910 xmlNodePtr child = NULL;
8911 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008912 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00008913 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008914
8915 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8916 return (NULL);
8917
8918 oldcontainer = ctxt->container;
8919
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008920 snprintf((char *) name, 30, "#restr%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008921 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008922 if (type == NULL)
8923 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008924 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008925 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00008926 /*
8927 * Check for illegal attributes.
8928 */
8929 attr = node->properties;
8930 while (attr != NULL) {
8931 if (attr->ns == NULL) {
8932 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8933 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
8934 xmlSchemaPIllegalAttrErr(ctxt,
8935 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8936 NULL, type, attr);
8937 }
8938 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8939 xmlSchemaPIllegalAttrErr(ctxt,
8940 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8941 NULL, type, attr);
8942 }
8943 attr = attr->next;
8944 }
8945 /*
8946 * Extract and validate attributes.
8947 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008948 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008949 /*
8950 * Attribute "base".
8951 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00008952 if ((xmlSchemaPValAttrQName(ctxt, schema,
8953 NULL, NULL, node, "base", &(type->baseNs), NULL, &(type->base)) == 0) &&
8954 (type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00008955 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8956 /* TODO: Think about the error code. */
8957 xmlSchemaPMissingAttrErr(ctxt,
8958 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
8959 NULL, type, node, "base", NULL);
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00008960 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008961 /*
8962 * And now for the children...
8963 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008964 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008965 child = node->children;
8966 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008967 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8968 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008969 }
8970 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008971 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8972 if (IS_SCHEMA(child, "all")) {
8973 subtype = (xmlSchemaTypePtr)
8974 xmlSchemaParseAll(ctxt, schema, child);
8975 child = child->next;
8976 type->subtypes = subtype;
8977 } else if (IS_SCHEMA(child, "choice")) {
8978 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8979 child = child->next;
8980 type->subtypes = subtype;
8981 } else if (IS_SCHEMA(child, "sequence")) {
8982 subtype = (xmlSchemaTypePtr)
8983 xmlSchemaParseSequence(ctxt, schema, child);
8984 child = child->next;
8985 type->subtypes = subtype;
8986 } else if (IS_SCHEMA(child, "group")) {
8987 subtype = (xmlSchemaTypePtr)
8988 xmlSchemaParseGroup(ctxt, schema, child, 0);
8989 child = child->next;
8990 type->subtypes = subtype;
8991 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008992 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
8993 if (IS_SCHEMA(child, "simpleType")) {
8994 if (type->base != NULL) {
8995 /*
8996 * src-restriction-base-or-simpleType
8997 * Either the base [attribute] or the simpleType [child] of the
8998 * <restriction> element must be present, but not both.
8999 */
9000 xmlSchemaPContentErr(ctxt,
9001 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9002 NULL, NULL, type->node, child,
9003 "The attribute 'base' and the <simpleType> child are "
9004 "mutually exclusive", NULL);
9005 } else {
9006 subtype = (xmlSchemaTypePtr)
9007 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9008 type->baseType = subtype;
9009 }
9010 child = child->next;
9011 }
9012 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009013 if (IS_SCHEMA(child, "simpleType")) {
9014 subtype = (xmlSchemaTypePtr)
9015 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009016 type->subtypes = subtype;
9017 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009018 }
9019 }
9020 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
9021 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
9022 xmlSchemaFacetPtr facet, lastfacet = NULL;
9023
Daniel Veillard01fa6152004-06-29 17:04:39 +00009024 /*
9025 * Add the facets to the parent simpleType/complexType.
9026 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009027 /*
9028 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9029 * Simple Type Definition Schema Representation Constraint:
9030 * *Single Facet Value*
9031 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009032 while ((IS_SCHEMA(child, "minInclusive")) ||
9033 (IS_SCHEMA(child, "minExclusive")) ||
9034 (IS_SCHEMA(child, "maxInclusive")) ||
9035 (IS_SCHEMA(child, "maxExclusive")) ||
9036 (IS_SCHEMA(child, "totalDigits")) ||
9037 (IS_SCHEMA(child, "fractionDigits")) ||
9038 (IS_SCHEMA(child, "pattern")) ||
9039 (IS_SCHEMA(child, "enumeration")) ||
9040 (IS_SCHEMA(child, "whiteSpace")) ||
9041 (IS_SCHEMA(child, "length")) ||
9042 (IS_SCHEMA(child, "maxLength")) ||
9043 (IS_SCHEMA(child, "minLength"))) {
9044 facet = xmlSchemaParseFacet(ctxt, schema, child);
9045 if (facet != NULL) {
9046 if (lastfacet == NULL)
9047 ctxt->ctxtType->facets = facet;
9048 else
9049 lastfacet->next = facet;
9050 lastfacet = facet;
9051 lastfacet->next = NULL;
9052 }
9053 child = child->next;
9054 }
9055 /*
9056 * Create links for derivation and validation.
9057 */
9058 if (lastfacet != NULL) {
9059 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
9060
9061 facet = ctxt->ctxtType->facets;
9062 do {
9063 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
9064 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009065 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009066 xmlFree(facetLink);
9067 return (NULL);
9068 }
9069 facetLink->facet = facet;
9070 facetLink->next = NULL;
9071 if (lastFacetLink == NULL)
9072 ctxt->ctxtType->facetSet = facetLink;
9073 else
9074 lastFacetLink->next = facetLink;
9075 lastFacetLink = facetLink;
9076 facet = facet->next;
9077 } while (facet != NULL);
9078 }
9079 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009080 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
9081 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
9082 if (IS_SCHEMA(child, "anyAttribute")) {
9083 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
9084 child = child->next;
9085 }
9086 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009087 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009088 /* TODO: Think about the error code. */
9089 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9090 xmlSchemaPContentErr(ctxt,
9091 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
9092 NULL, type, node, child, NULL,
9093 "annotation?, (group | all | choice | sequence)?, "
9094 "((attribute | attributeGroup)*, anyAttribute?))");
9095 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
9096 xmlSchemaPContentErr(ctxt,
9097 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
9098 NULL, type, node, child, NULL,
9099 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
9100 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
9101 "length | minLength | maxLength | enumeration | whiteSpace | "
9102 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
9103 } else {
9104 /* Simple type */
9105 xmlSchemaPContentErr(ctxt,
9106 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
9107 NULL, type, node, child, NULL,
9108 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
9109 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
9110 "length | minLength | maxLength | enumeration | whiteSpace | "
9111 "pattern)*))");
9112 }
9113 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009114 ctxt->container = oldcontainer;
9115 return (type);
9116}
9117
9118/**
9119 * xmlSchemaParseExtension:
9120 * @ctxt: a schema validation context
9121 * @schema: the schema being built
9122 * @node: a subtree containing XML Schema informations
9123 *
9124 * parse a XML schema Extension definition
9125 * *WARNING* this interface is highly subject to change
9126 *
9127 * Returns the type definition or NULL in case of error
9128 */
9129static xmlSchemaTypePtr
9130xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009131 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009132{
9133 xmlSchemaTypePtr type, subtype;
9134 xmlNodePtr child = NULL;
9135 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009136 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00009137
9138 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9139 return (NULL);
9140
9141 oldcontainer = ctxt->container;
9142
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009143 snprintf((char *) name, 30, "#ext%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009144 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00009145 if (type == NULL)
9146 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00009147 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00009148 type->node = node;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009149
9150 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
9151
Daniel Veillard4255d502002-04-16 15:50:10 +00009152 ctxt->container = name;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009153 /*
9154 * Attribute "base".
9155 */
9156 if ((xmlSchemaPValAttrQName(ctxt, schema,
9157 NULL, NULL, node, "base", &(type->baseNs), NULL, &(type->base)) == 0) &&
9158 (type->base == NULL) &&
9159 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
9160 /* TODO: Think about the error code. */
9161 xmlSchemaPMissingAttrErr(ctxt,
9162 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
9163 NULL, type, node, "base", NULL);
9164 }
9165
Daniel Veillard4255d502002-04-16 15:50:10 +00009166 child = node->children;
9167 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009168 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9169 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009170 }
9171 subtype = NULL;
9172
9173 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009174 subtype = xmlSchemaParseAll(ctxt, schema, child);
9175 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009176 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009177 subtype = xmlSchemaParseChoice(ctxt, schema, child);
9178 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009179 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009180 subtype = xmlSchemaParseSequence(ctxt, schema, child);
9181 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009182 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009183 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009184 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009185 }
9186 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009187 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009188 if ((ctxt->ctxtType != NULL) &&
9189 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
9190 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
9191 if (IS_SCHEMA(child, "anyAttribute")) {
9192 ctxt->ctxtType->attributeWildcard =
9193 xmlSchemaParseAnyAttribute(ctxt, schema, child);
9194 child = child->next;
9195 }
9196 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009197 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009198 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009199 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
9200 "<extension> has unexpected content.\n", type->name,
9201 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009202 }
9203 ctxt->container = oldcontainer;
9204 return (type);
9205}
9206
9207/**
9208 * xmlSchemaParseSimpleContent:
9209 * @ctxt: a schema validation context
9210 * @schema: the schema being built
9211 * @node: a subtree containing XML Schema informations
9212 *
9213 * parse a XML schema SimpleContent definition
9214 * *WARNING* this interface is highly subject to change
9215 *
9216 * Returns the type definition or NULL in case of error
9217 */
9218static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009219xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
9220 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009221{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009222 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00009223 xmlNodePtr child = NULL;
9224 xmlChar name[30];
9225
9226 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9227 return (NULL);
9228
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009229 snprintf((char *) name, 30, "#SC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009230 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00009231 if (type == NULL)
9232 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00009233 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00009234 type->node = node;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009235
9236 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00009237
9238 child = node->children;
9239 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009240 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9241 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009242 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009243 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009244 ctxt->parentItem = type;
9245 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009246 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009247 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009248 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009249 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009250 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009251 subtype = (xmlSchemaTypePtr)
9252 xmlSchemaParseExtension(ctxt, schema, child);
9253 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009254 }
9255 type->subtypes = subtype;
9256 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009257 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009258 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
9259 "<simpleContent> has unexpected content.\n",
9260 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009261 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009262 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00009263 return (type);
9264}
9265
9266/**
9267 * xmlSchemaParseComplexContent:
9268 * @ctxt: a schema validation context
9269 * @schema: the schema being built
9270 * @node: a subtree containing XML Schema informations
9271 *
9272 * parse a XML schema ComplexContent definition
9273 * *WARNING* this interface is highly subject to change
9274 *
9275 * Returns the type definition or NULL in case of error
9276 */
9277static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009278xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
9279 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009280{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009281 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00009282 xmlNodePtr child = NULL;
9283 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009284 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009285
9286 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9287 return (NULL);
9288
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009289 snprintf((char *) name, 30, "#CC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009290 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00009291 if (type == NULL)
9292 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00009293 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009294 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009295 /*
9296 * Check for illegal attributes.
9297 */
9298 attr = node->properties;
9299 while (attr != NULL) {
9300 if (attr->ns == NULL) {
9301 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9302 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
9303 {
9304 xmlSchemaPIllegalAttrErr(ctxt,
9305 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9306 NULL, NULL, attr);
9307 }
9308 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9309 xmlSchemaPIllegalAttrErr(ctxt,
9310 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9311 NULL, NULL, attr);
9312 }
9313 attr = attr->next;
9314 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009315
9316 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
9317
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009318 /*
9319 * Handle attribute 'mixed'.
9320 */
9321 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
9322 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
9323 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
9324 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009325 child = node->children;
9326 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009327 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9328 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009329 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009330 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009331 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009332 subtype = NULL;
9333 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009334 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009335 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009336 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009337 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009338 subtype = (xmlSchemaTypePtr)
9339 xmlSchemaParseExtension(ctxt, schema, child);
9340 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009341 }
9342 type->subtypes = subtype;
9343 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009344 xmlSchemaPContentErr(ctxt,
9345 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9346 NULL, NULL, node, child,
9347 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009348 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009349 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00009350 return (type);
9351}
9352
9353/**
9354 * xmlSchemaParseComplexType:
9355 * @ctxt: a schema validation context
9356 * @schema: the schema being built
9357 * @node: a subtree containing XML Schema informations
9358 *
9359 * parse a XML schema Complex Type definition
9360 * *WARNING* this interface is highly subject to change
9361 *
9362 * Returns the type definition or NULL in case of error
9363 */
9364static xmlSchemaTypePtr
9365xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00009366 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00009367{
Daniel Veillard01fa6152004-06-29 17:04:39 +00009368 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009369 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009370 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00009371 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009372 xmlAttrPtr attr;
9373 const xmlChar *attrValue;
9374 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00009375 char buf[40];
9376
Daniel Veillard4255d502002-04-16 15:50:10 +00009377
9378 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9379 return (NULL);
9380
Daniel Veillard01fa6152004-06-29 17:04:39 +00009381 ctxtType = ctxt->ctxtType;
9382
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009383 if (topLevel) {
9384 attr = xmlSchemaGetPropNode(node, "name");
9385 if (attr == NULL) {
9386 xmlSchemaPMissingAttrErr(ctxt,
9387 XML_SCHEMAP_S4S_ATTR_MISSING,
9388 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
9389 "name", NULL);
9390 return (NULL);
9391 } else if (xmlSchemaPValAttrNode(ctxt,
9392 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
9393 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9394 return (NULL);
9395 }
9396 }
9397
9398 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009399 /*
9400 * Parse as local complex type definition.
9401 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009402 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009403 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
9404 if (type == NULL)
9405 return (NULL);
9406 name = (const xmlChar *) buf;
9407 type->node = node;
9408 type->type = XML_SCHEMA_TYPE_COMPLEX;
9409 /*
9410 * TODO: We need the target namespace.
9411 */
9412 } else {
9413 /*
9414 * Parse as global complex type definition.
9415 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009416 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009417 if (type == NULL)
9418 return (NULL);
9419 type->node = node;
9420 type->type = XML_SCHEMA_TYPE_COMPLEX;
9421 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9422 /*
9423 * Set defaults.
9424 */
9425 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
9426 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00009427 }
9428 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009429 /*
9430 * Handle attributes.
9431 */
9432 attr = node->properties;
9433 while (attr != NULL) {
9434 if (attr->ns == NULL) {
9435 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
9436 /*
9437 * Attribute "id".
9438 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009439 xmlSchemaPValAttrID(ctxt, NULL, type, node,
9440 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009441 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
9442 /*
9443 * Attribute "mixed".
9444 */
9445 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
9446 (xmlNodePtr) attr))
9447 type->flags |= XML_SCHEMAS_TYPE_MIXED;
9448 } else if (topLevel) {
9449 /*
9450 * Attributes of global complex type definitions.
9451 */
9452 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
9453 /* Pass. */
9454 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
9455 /*
9456 * Attribute "abstract".
9457 */
9458 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
9459 (xmlNodePtr) attr))
9460 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
9461 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
9462 /*
9463 * Attribute "final".
9464 */
9465 attrValue = xmlSchemaGetNodeContent(ctxt,
9466 (xmlNodePtr) attr);
9467 if (xmlSchemaPValAttrBlockFinal(attrValue,
9468 &(type->flags),
9469 -1,
9470 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
9471 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
9472 -1, -1, -1) != 0)
9473 {
9474 xmlSchemaPSimpleTypeErr(ctxt,
9475 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9476 &des, type, (xmlNodePtr) attr,
9477 NULL,
9478 "(#all | List of (extension | restriction))",
9479 attrValue, NULL, NULL, NULL);
9480 }
9481 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
9482 /*
9483 * Attribute "block".
9484 */
9485 attrValue = xmlSchemaGetNodeContent(ctxt,
9486 (xmlNodePtr) attr);
9487 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9488 -1,
9489 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
9490 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
9491 -1, -1, -1) != 0) {
9492 xmlSchemaPSimpleTypeErr(ctxt,
9493 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9494 &des, type, (xmlNodePtr) attr,
9495 NULL,
9496 "(#all | List of (extension | restriction)) ",
9497 attrValue, NULL, NULL, NULL);
9498 }
9499 } else {
9500 xmlSchemaPIllegalAttrErr(ctxt,
9501 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9502 &des, type, attr);
9503 }
9504 } else {
9505 xmlSchemaPIllegalAttrErr(ctxt,
9506 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9507 &des, type, attr);
9508 }
9509 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9510 xmlSchemaPIllegalAttrErr(ctxt,
9511 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9512 &des, type, attr);
9513 }
9514 attr = attr->next;
9515 }
9516 /*
9517 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009518 * This will be only changed if a complex type
9519 * inherits an attribute wildcard from a base type.
9520 */
9521 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009522 /*
9523 * And now for the children...
9524 */
9525 oldcontainer = ctxt->container;
9526 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009527 child = node->children;
9528 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009529 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9530 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009531 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009532 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009533 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009534 /*
9535 * 3.4.3 : 2.2
9536 * Specifying mixed='true' when the <simpleContent>
9537 * alternative is chosen has no effect
9538 */
William M. Bracke7091952004-05-11 15:09:58 +00009539 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
9540 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009541 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
9542 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009543 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009544 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
9545 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009546 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009547 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009548 /*
9549 * Parse model groups.
9550 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009551 if (IS_SCHEMA(child, "all")) {
9552 subtype = xmlSchemaParseAll(ctxt, schema, child);
9553 child = child->next;
9554 } else if (IS_SCHEMA(child, "choice")) {
9555 subtype = xmlSchemaParseChoice(ctxt, schema, child);
9556 child = child->next;
9557 } else if (IS_SCHEMA(child, "sequence")) {
9558 subtype = xmlSchemaParseSequence(ctxt, schema, child);
9559 child = child->next;
9560 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009561 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009562 child = child->next;
9563 }
9564 if (subtype != NULL)
9565 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009566 /*
9567 * Parse attribute decls/refs.
9568 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009569 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009570 /*
9571 * Parse attribute wildcard.
9572 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009573 if (IS_SCHEMA(child, "anyAttribute")) {
9574 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
9575 child = child->next;
9576 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009577 }
9578 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009579 xmlSchemaPContentErr(ctxt,
9580 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9581 &des, type, node, child,
9582 NULL, "(annotation?, (simpleContent | complexContent | "
9583 "((group | all | choice | sequence)?, ((attribute | "
9584 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009585 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009586 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00009587 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009588 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009589 return (type);
9590}
9591
Daniel Veillard4255d502002-04-16 15:50:10 +00009592/**
9593 * xmlSchemaParseSchema:
9594 * @ctxt: a schema validation context
9595 * @node: a subtree containing XML Schema informations
9596 *
9597 * parse a XML schema definition from a node set
9598 * *WARNING* this interface is highly subject to change
9599 *
9600 * Returns the internal XML Schema structure built from the resource or
9601 * NULL in case of error
9602 */
9603static xmlSchemaPtr
9604xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
9605{
9606 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009607 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009608 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009609 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009610
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009611 /*
9612 * This one is called by xmlSchemaParse only and is used if
9613 * the schema to be parsed was specified via the API; i.e. not
9614 * automatically by the validated instance document.
9615 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009616 if ((ctxt == NULL) || (node == NULL))
9617 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009618 nberrors = ctxt->nberrors;
9619 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009620 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009621 xmlSchemaImportPtr import;
9622
Daniel Veillard4255d502002-04-16 15:50:10 +00009623 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009624 if (schema == NULL)
9625 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009626 /*
9627 * Disable build of list of items.
9628 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009629 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9630 if (attr != NULL) {
9631 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9632 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
9633 /*
9634 * TODO: Should we proceed with an invalid target namespace?
9635 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009636 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
9637 } else {
9638 schema->targetNamespace = NULL;
9639 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009640 /*
9641 * Add the current ns name and location to the import table;
9642 * this is needed to have a consistent mechanism, regardless
9643 * if all schemata are constructed dynamically fired by the
9644 * instance or if the schema to be used was specified via
9645 * the API.
9646 */
9647 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
9648 schema->targetNamespace);
9649 if (import == NULL) {
9650 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
9651 NULL, NULL, (xmlNodePtr) ctxt->doc,
9652 "Internal error: xmlSchemaParseSchema, "
9653 "failed to add an import entry", NULL);
9654 xmlSchemaFree(schema);
9655 schema = NULL;
9656 return (NULL);
9657 }
9658 import->schemaLocation = ctxt->URL;
9659 /*
9660 * NOTE: We won't set the doc here, otherwise it will be freed
9661 * if the import struct is freed.
9662 * import->doc = ctxt->doc;
9663 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009664 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009665 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
9666 } else {
9667 xmlDocPtr doc;
9668
9669 doc = node->doc;
9670
9671 if ((doc != NULL) && (doc->URL != NULL)) {
9672 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9673 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009674 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009675 } else {
9676 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9677 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009678 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009679 }
9680 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009681 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009682 if (ctxt->nberrors != 0) {
9683 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009684 xmlSchemaFree(schema);
9685 schema = NULL;
9686 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009687 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009688 if (schema != NULL)
9689 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009690 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00009691#ifdef DEBUG
9692 if (schema == NULL)
9693 xmlGenericError(xmlGenericErrorContext,
9694 "xmlSchemaParse() failed\n");
9695#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009696 return (schema);
9697}
9698
9699/************************************************************************
9700 * *
9701 * Validating using Schemas *
9702 * *
9703 ************************************************************************/
9704
9705/************************************************************************
9706 * *
9707 * Reading/Writing Schemas *
9708 * *
9709 ************************************************************************/
9710
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009711#if 0 /* Will be enabled if it is clear what options are needed. */
9712/**
9713 * xmlSchemaParserCtxtSetOptions:
9714 * @ctxt: a schema parser context
9715 * @options: a combination of xmlSchemaParserOption
9716 *
9717 * Sets the options to be used during the parse.
9718 *
9719 * Returns 0 in case of success, -1 in case of an
9720 * API error.
9721 */
9722static int
9723xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
9724 int options)
9725
9726{
9727 int i;
9728
9729 if (ctxt == NULL)
9730 return (-1);
9731 /*
9732 * WARNING: Change the start value if adding to the
9733 * xmlSchemaParseOption.
9734 */
9735 for (i = 1; i < (int) sizeof(int) * 8; i++) {
9736 if (options & 1<<i) {
9737 return (-1);
9738 }
9739 }
9740 ctxt->options = options;
9741 return (0);
9742}
9743
9744/**
9745 * xmlSchemaValidCtxtGetOptions:
9746 * @ctxt: a schema parser context
9747 *
9748 * Returns the option combination of the parser context.
9749 */
9750static int
9751xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
9752
9753{
9754 if (ctxt == NULL)
9755 return (-1);
9756 else
9757 return (ctxt->options);
9758}
9759
9760 void *curItems; /* used for dynamic addition of schemata */
9761 int nbCurItems; /* used for dynamic addition of schemata */
9762 int sizeCurItems; /* used for dynamic addition of schemata */
9763
9764#endif
9765
Daniel Veillard4255d502002-04-16 15:50:10 +00009766/**
9767 * xmlSchemaNewParserCtxt:
9768 * @URL: the location of the schema
9769 *
9770 * Create an XML Schemas parse context for that file/resource expected
9771 * to contain an XML Schemas file.
9772 *
9773 * Returns the parser context or NULL in case of error
9774 */
9775xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009776xmlSchemaNewParserCtxt(const char *URL)
9777{
Daniel Veillard4255d502002-04-16 15:50:10 +00009778 xmlSchemaParserCtxtPtr ret;
9779
9780 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009781 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009782
9783 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9784 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009785 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009786 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009787 return (NULL);
9788 }
9789 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009790 ret->dict = xmlDictCreate();
9791 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00009792 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009793 return (ret);
9794}
9795
9796/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009797 * xmlSchemaNewParserCtxtUseDict:
9798 * @URL: the location of the schema
9799 * @dict: the dictionary to be used
9800 *
9801 * Create an XML Schemas parse context for that file/resource expected
9802 * to contain an XML Schemas file.
9803 *
9804 * Returns the parser context or NULL in case of error
9805 */
9806static xmlSchemaParserCtxtPtr
9807xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9808{
9809 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009810 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009811 if (URL == NULL)
9812 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009813 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009814
9815 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9816 if (ret == NULL) {
9817 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9818 NULL);
9819 return (NULL);
9820 }
9821 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9822 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009823 xmlDictReference(dict);
9824 if (URL != NULL)
9825 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009826 ret->includes = 0;
9827 return (ret);
9828}
9829
9830
9831/**
Daniel Veillard6045c902002-10-09 21:13:59 +00009832 * xmlSchemaNewMemParserCtxt:
9833 * @buffer: a pointer to a char array containing the schemas
9834 * @size: the size of the array
9835 *
9836 * Create an XML Schemas parse context for that memory buffer expected
9837 * to contain an XML Schemas file.
9838 *
9839 * Returns the parser context or NULL in case of error
9840 */
9841xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009842xmlSchemaNewMemParserCtxt(const char *buffer, int size)
9843{
Daniel Veillard6045c902002-10-09 21:13:59 +00009844 xmlSchemaParserCtxtPtr ret;
9845
9846 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009847 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009848
9849 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9850 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009851 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009852 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009853 return (NULL);
9854 }
9855 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9856 ret->buffer = buffer;
9857 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009858 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00009859 return (ret);
9860}
9861
9862/**
Daniel Veillard9d751502003-10-29 13:21:47 +00009863 * xmlSchemaNewDocParserCtxt:
9864 * @doc: a preparsed document tree
9865 *
9866 * Create an XML Schemas parse context for that document.
9867 * NB. The document may be modified during the parsing process.
9868 *
9869 * Returns the parser context or NULL in case of error
9870 */
9871xmlSchemaParserCtxtPtr
9872xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
9873{
9874 xmlSchemaParserCtxtPtr ret;
9875
9876 if (doc == NULL)
9877 return (NULL);
9878
9879 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9880 if (ret == NULL) {
9881 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9882 NULL);
9883 return (NULL);
9884 }
9885 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9886 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009887 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00009888 /* The application has responsibility for the document */
9889 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00009890
9891 return (ret);
9892}
9893
9894/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009895 * xmlSchemaFreeParserCtxt:
9896 * @ctxt: the schema parser context
9897 *
9898 * Free the resources associated to the schema parser context
9899 */
9900void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009901xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
9902{
Daniel Veillard4255d502002-04-16 15:50:10 +00009903 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009904 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00009905 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009906 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009907 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009908 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009909 xmlFree(ctxt->assemble);
9910 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009911 if (ctxt->vctxt != NULL) {
9912 xmlSchemaFreeValidCtxt(ctxt->vctxt);
9913 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009914 if (ctxt->localImports != NULL)
9915 xmlFree((xmlChar *) ctxt->localImports);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009916 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00009917 xmlFree(ctxt);
9918}
9919
9920/************************************************************************
9921 * *
9922 * Building the content models *
9923 * *
9924 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009925
Daniel Veillard4255d502002-04-16 15:50:10 +00009926/**
9927 * xmlSchemaBuildAContentModel:
9928 * @type: the schema type definition
9929 * @ctxt: the schema parser context
9930 * @name: the element name whose content is being built
9931 *
9932 * Generate the automata sequence needed for that type
9933 */
9934static void
9935xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009936 xmlSchemaParserCtxtPtr ctxt,
9937 const xmlChar * name)
9938{
Daniel Veillard4255d502002-04-16 15:50:10 +00009939 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009940 xmlGenericError(xmlGenericErrorContext,
9941 "Found unexpected type = NULL in %s content model\n",
9942 name);
9943 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009944 }
9945 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009946 case XML_SCHEMA_TYPE_ANY: {
9947 xmlAutomataStatePtr start, end;
9948 xmlSchemaWildcardPtr wild;
9949 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00009950
Daniel Veillardc0826a72004-08-10 14:17:33 +00009951 wild = type->attributeWildcard;
9952
9953 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009954 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009955 "Internal error: xmlSchemaBuildAContentModel, "
9956 "no wildcard on xsd:any.\n", NULL, NULL);
9957 return;
9958 }
9959
9960 start = ctxt->state;
9961 end = xmlAutomataNewState(ctxt->am);
9962
9963 if (type->maxOccurs == 1) {
9964 if (wild->any == 1) {
9965 /*
9966 * We need to add both transitions:
9967 *
9968 * 1. the {"*", "*"} for elements in a namespace.
9969 */
9970 ctxt->state =
9971 xmlAutomataNewTransition2(ctxt->am,
9972 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9973 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9974 /*
9975 * 2. the {"*"} for elements in no namespace.
9976 */
9977 ctxt->state =
9978 xmlAutomataNewTransition2(ctxt->am,
9979 start, NULL, BAD_CAST "*", NULL, type);
9980 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9981
9982 } else if (wild->nsSet != NULL) {
9983 ns = wild->nsSet;
9984 do {
9985 ctxt->state = start;
9986 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9987 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
9988 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9989 ns = ns->next;
9990 } while (ns != NULL);
9991
9992 } else if (wild->negNsSet != NULL) {
9993 xmlAutomataStatePtr deadEnd;
9994
9995 deadEnd = xmlAutomataNewState(ctxt->am);
9996 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9997 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9998 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9999 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
10000 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10001 }
10002 } else {
10003 int counter;
10004 xmlAutomataStatePtr hop;
10005 int maxOccurs =
10006 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
10007 int minOccurs =
10008 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
10009
10010 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
10011 hop = xmlAutomataNewState(ctxt->am);
10012 if (wild->any == 1) {
10013 ctxt->state =
10014 xmlAutomataNewTransition2(ctxt->am,
10015 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
10016 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10017 ctxt->state =
10018 xmlAutomataNewTransition2(ctxt->am,
10019 start, NULL, BAD_CAST "*", NULL, type);
10020 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10021 } else if (wild->nsSet != NULL) {
10022 ns = wild->nsSet;
10023 do {
10024 ctxt->state =
10025 xmlAutomataNewTransition2(ctxt->am,
10026 start, NULL, BAD_CAST "*", ns->value, type);
10027 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10028 ns = ns->next;
10029 } while (ns != NULL);
10030
10031 } else if (wild->negNsSet != NULL) {
10032 xmlAutomataStatePtr deadEnd;
10033
10034 deadEnd = xmlAutomataNewState(ctxt->am);
10035 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
10036 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
10037 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
10038 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
10039 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10040 }
10041 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
10042 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
10043 }
10044 if (type->minOccurs == 0) {
10045 xmlAutomataNewEpsilon(ctxt->am, start, end);
10046 }
10047 ctxt->state = end;
10048 break;
10049 }
10050 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010051 xmlAutomataStatePtr oldstate;
10052 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +000010053
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010054 /*
10055 * IMPORTANT: This puts element declarations
10056 * (and never element decl. references) into the
10057 * automaton. This is crucial and should not be changed,
10058 * since validating functions rely now on it.
10059 */
10060 particle = (xmlSchemaElementPtr) type;
10061 if (particle->ref != NULL) {
10062 if (particle->refDecl == NULL) {
10063 /*
10064 * Skip content model creation if the reference
10065 * did not resolve to a declaration.
10066 */
10067 break;
10068 } else {
10069 /*
10070 * Referenced global element declaration.
10071 */
10072 elemDecl = particle->refDecl;
10073 }
10074 } else {
10075 /*
10076 * Anonymous element declaration.
10077 */
10078 elemDecl = particle;
10079 }
10080
10081 oldstate = ctxt->state;
10082
10083 if (particle->maxOccurs >= UNBOUNDED) {
10084 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010085 xmlAutomataStatePtr tmp;
10086 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +000010087
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010088 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010089 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010090 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010091 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010092 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000010093 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010094 xmlAutomataNewTransition2(ctxt->am,
10095 ctxt->state, NULL,
10096 elemDecl->name,
10097 elemDecl->targetNamespace,
10098 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010099 tmp = ctxt->state;
10100 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010101 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010102 ctxt->state =
10103 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010104 counter);
Daniel Veillard32370232002-10-16 14:08:14 +000010105
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010106 } else {
10107 ctxt->state =
10108 xmlAutomataNewTransition2(ctxt->am,
10109 ctxt->state, NULL,
10110 elemDecl->name,
10111 elemDecl->targetNamespace,
10112 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010113 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
10114 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010115 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010116 /* basically an elem* */
10117 xmlAutomataNewEpsilon(ctxt->am, oldstate,
10118 ctxt->state);
10119 }
10120 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010121 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010122 xmlAutomataStatePtr tmp;
10123 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +000010124
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010125 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
10126 oldstate, NULL);
10127 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010128 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010129 particle->minOccurs - 1,
10130 particle->maxOccurs - 1);
10131 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
10132 ctxt->state,
10133 NULL,
10134 elemDecl->name,
10135 elemDecl->targetNamespace,
10136 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010137 tmp = ctxt->state;
10138 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010139 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010140 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010141 NULL, counter);
10142 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010143 /* basically an elem? */
10144 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010145 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010146 }
Daniel Veillardb39bc392002-10-26 19:29:51 +000010147
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010148 } else {
10149 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
10150 ctxt->state,
10151 NULL,
10152 elemDecl->name,
10153 elemDecl->targetNamespace,
10154 (xmlSchemaTypePtr) elemDecl);
10155 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010156 /* basically an elem? */
10157 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010158 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010159 }
10160 }
10161 break;
10162 }
10163 case XML_SCHEMA_TYPE_SEQUENCE:{
10164 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010165
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010166 /*
10167 * If max and min occurances are default (1) then
10168 * simply iterate over the subtypes
10169 */
10170 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
10171 subtypes = type->subtypes;
10172 while (subtypes != NULL) {
10173 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10174 subtypes = subtypes->next;
10175 }
10176 } else {
10177 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010178
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010179 if (type->maxOccurs >= UNBOUNDED) {
10180 if (type->minOccurs > 1) {
10181 xmlAutomataStatePtr tmp;
10182 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010183
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010184 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
10185 oldstate,
10186 NULL);
10187 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010188
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010189 counter = xmlAutomataNewCounter(ctxt->am,
10190 type->
10191 minOccurs - 1,
10192 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000010193
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010194 subtypes = type->subtypes;
10195 while (subtypes != NULL) {
10196 xmlSchemaBuildAContentModel(subtypes, ctxt,
10197 name);
10198 subtypes = subtypes->next;
10199 }
10200 tmp = ctxt->state;
10201 xmlAutomataNewCountedTrans(ctxt->am, tmp,
10202 oldstate, counter);
10203 ctxt->state =
10204 xmlAutomataNewCounterTrans(ctxt->am, tmp,
10205 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000010206
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010207 } else {
10208 subtypes = type->subtypes;
10209 while (subtypes != NULL) {
10210 xmlSchemaBuildAContentModel(subtypes, ctxt,
10211 name);
10212 subtypes = subtypes->next;
10213 }
10214 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
10215 oldstate);
10216 if (type->minOccurs == 0) {
10217 xmlAutomataNewEpsilon(ctxt->am, oldstate,
10218 ctxt->state);
10219 }
10220 }
10221 } else if ((type->maxOccurs > 1)
10222 || (type->minOccurs > 1)) {
10223 xmlAutomataStatePtr tmp;
10224 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010225
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010226 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
10227 oldstate,
10228 NULL);
10229 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000010230
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010231 counter = xmlAutomataNewCounter(ctxt->am,
10232 type->minOccurs -
10233 1,
10234 type->maxOccurs -
10235 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000010236
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010237 subtypes = type->subtypes;
10238 while (subtypes != NULL) {
10239 xmlSchemaBuildAContentModel(subtypes, ctxt,
10240 name);
10241 subtypes = subtypes->next;
10242 }
10243 tmp = ctxt->state;
10244 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
10245 counter);
10246 ctxt->state =
10247 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
10248 counter);
10249 if (type->minOccurs == 0) {
10250 xmlAutomataNewEpsilon(ctxt->am, oldstate,
10251 ctxt->state);
10252 }
Daniel Veillardb509f152002-04-17 16:28:10 +000010253
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010254 } else {
10255 subtypes = type->subtypes;
10256 while (subtypes != NULL) {
10257 xmlSchemaBuildAContentModel(subtypes, ctxt,
10258 name);
10259 subtypes = subtypes->next;
10260 }
10261 if (type->minOccurs == 0) {
10262 xmlAutomataNewEpsilon(ctxt->am, oldstate,
10263 ctxt->state);
10264 }
10265 }
10266 }
10267 break;
10268 }
10269 case XML_SCHEMA_TYPE_CHOICE:{
10270 xmlSchemaTypePtr subtypes;
10271 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000010272
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010273 start = ctxt->state;
10274 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000010275
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010276 /*
10277 * iterate over the subtypes and remerge the end with an
10278 * epsilon transition
10279 */
10280 if (type->maxOccurs == 1) {
10281 subtypes = type->subtypes;
10282 while (subtypes != NULL) {
10283 ctxt->state = start;
10284 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10285 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10286 subtypes = subtypes->next;
10287 }
10288 } else {
10289 int counter;
10290 xmlAutomataStatePtr hop;
10291 int maxOccurs = type->maxOccurs == UNBOUNDED ?
10292 UNBOUNDED : type->maxOccurs - 1;
10293 int minOccurs =
10294 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000010295
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010296 /*
10297 * use a counter to keep track of the number of transtions
10298 * which went through the choice.
10299 */
10300 counter =
10301 xmlAutomataNewCounter(ctxt->am, minOccurs,
10302 maxOccurs);
10303 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000010304
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010305 subtypes = type->subtypes;
10306 while (subtypes != NULL) {
10307 ctxt->state = start;
10308 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10309 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10310 subtypes = subtypes->next;
10311 }
10312 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
10313 counter);
10314 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
10315 counter);
10316 }
10317 if (type->minOccurs == 0) {
10318 xmlAutomataNewEpsilon(ctxt->am, start, end);
10319 }
10320 ctxt->state = end;
10321 break;
10322 }
10323 case XML_SCHEMA_TYPE_ALL:{
10324 xmlAutomataStatePtr start;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010325 xmlSchemaElementPtr elemDecl, particle;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010326 int lax;
10327
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010328 particle = (xmlSchemaElementPtr) type->subtypes;
10329 if (particle == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010330 break;
10331 start = ctxt->state;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010332 while (particle != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010333 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +000010334 /*
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010335 * Changed to put the element declaration and
10336 * never the element decl. reference into the
10337 * automaton. This fixes bug 139897 and bug 167754.
William M. Brack9989c7d2004-05-12 14:39:38 +000010338 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010339 if (particle->ref != NULL) {
10340 if (particle->refDecl == NULL) {
10341 /*
10342 * TODO: Note that we break on missing
10343 * sub-components.
10344 */
10345 break;
10346 } else
10347 elemDecl = particle->refDecl;
10348 } else
10349 elemDecl = particle;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010350 /*
10351 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010352 * {particles} of the group must be 0 or 1; this is
10353 * already ensured during the parse of the content of
10354 * <all>.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010355 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010356 if ((particle->minOccurs == 1) &&
10357 (particle->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010358 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
10359 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010360 elemDecl->name,
10361 elemDecl->targetNamespace,
10362 1, 1, elemDecl);
10363 } else if ((particle->minOccurs == 0) &&
10364 (particle->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010365
10366 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
10367 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010368 elemDecl->name,
10369 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010370 0,
10371 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010372 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010373 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010374 particle = (xmlSchemaElementPtr) particle->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010375 }
10376 lax = type->minOccurs == 0;
10377 ctxt->state =
10378 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
10379 lax);
10380 break;
10381 }
10382 case XML_SCHEMA_TYPE_RESTRICTION:
10383 if (type->subtypes != NULL)
10384 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10385 break;
10386 case XML_SCHEMA_TYPE_EXTENSION:
10387 if (type->baseType != NULL) {
10388 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010389
10390 /*
10391 * TODO: Circular definitions will be checked at the
10392 * constraint level. So remove this when the complex type
10393 * constraints are implemented.
10394 */
Daniel Veillardf7627552004-04-22 07:15:40 +000010395 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010396 /* TODO: Change the error code. */
10397 xmlSchemaPCustomErr(ctxt,
10398 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
10399 NULL, type, type->node,
10400 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +000010401 return;
10402 }
10403 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010404 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +000010405 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010406 subtypes = type->subtypes;
10407 while (subtypes != NULL) {
10408 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10409 subtypes = subtypes->next;
10410 }
10411 } else if (type->subtypes != NULL)
10412 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10413 break;
10414 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010415 /*
10416 * Handle model group definition references.
10417 * NOTE: type->subtypes is the referenced model grop definition;
10418 * and type->subtypes->subtypes is the model group (i.e. <all> or
10419 * <choice> or <sequence>).
10420 */
10421 if ((type->ref != NULL) && (type->subtypes != NULL) &&
10422 (type->subtypes->subtypes != NULL)) {
10423 xmlSchemaTypePtr modelGr;
10424 xmlAutomataStatePtr start, end;
10425
10426 modelGr = type->subtypes->subtypes;
10427 start = ctxt->state;
10428 end = xmlAutomataNewState(ctxt->am);
10429 if (type->maxOccurs == 1) {
10430 ctxt->state = start;
10431 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
10432 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10433 } else {
10434 int counter;
10435 xmlAutomataStatePtr hop;
10436 int maxOccurs = type->maxOccurs == UNBOUNDED ?
10437 UNBOUNDED : type->maxOccurs - 1;
10438 int minOccurs =
10439 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
10440
10441 counter =
10442 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
10443 hop = xmlAutomataNewState(ctxt->am);
10444 ctxt->state = start;
10445 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
10446 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10447 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
10448 counter);
10449 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
10450 counter);
10451 }
10452 if (type->minOccurs == 0) {
10453 xmlAutomataNewEpsilon(ctxt->am, start, end);
10454 }
10455 ctxt->state = end;
10456 break;
10457 }
10458 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010459 case XML_SCHEMA_TYPE_COMPLEX:
10460 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
10461 if (type->subtypes != NULL)
10462 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10463 break;
William M. Brack2f2a6632004-08-20 23:09:47 +000010464 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
10465 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010466 default:
10467 xmlGenericError(xmlGenericErrorContext,
10468 "Found unexpected type %d in %s content model\n",
10469 type->type, name);
10470 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010471 }
10472}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010473
Daniel Veillard4255d502002-04-16 15:50:10 +000010474/**
10475 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010476 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +000010477 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +000010478 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000010479 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010480 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000010481 */
10482static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010483xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010484 xmlSchemaParserCtxtPtr ctxt,
10485 const xmlChar * name)
10486{
Daniel Veillard4255d502002-04-16 15:50:10 +000010487 xmlAutomataStatePtr start;
10488
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010489 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
10490 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
10491 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
10492 (type->contModel != NULL))
10493 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010494
10495#ifdef DEBUG_CONTENT
10496 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010497 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010498#endif
10499
Daniel Veillard4255d502002-04-16 15:50:10 +000010500 ctxt->am = xmlNewAutomata();
10501 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010502 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010503 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010504 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010505 }
10506 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010507 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000010508 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010509 type->contModel = xmlAutomataCompile(ctxt->am);
10510 if (type->contModel == NULL) {
10511 xmlSchemaPCustomErr(ctxt,
10512 XML_SCHEMAP_INTERNAL,
10513 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010514 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010515 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010516 xmlSchemaPCustomErr(ctxt,
10517 XML_SCHEMAP_NOT_DETERMINISTIC,
10518 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010519 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010520 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000010521 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000010522#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010523 xmlGenericError(xmlGenericErrorContext,
10524 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010525 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000010526#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000010527 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000010528 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000010529 xmlFreeAutomata(ctxt->am);
10530 ctxt->am = NULL;
10531}
10532
10533/**
10534 * xmlSchemaRefFixupCallback:
10535 * @elem: the schema element context
10536 * @ctxt: the schema parser context
10537 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000010538 * Resolves the references of an element declaration
10539 * or particle, which has an element declaration as it's
10540 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000010541 */
10542static void
10543xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010544 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010545 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010546 const xmlChar * context ATTRIBUTE_UNUSED,
10547 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000010548{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010549 if ((ctxt == NULL) || (elem == NULL) ||
10550 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010551 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010552 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000010553 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010554 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +000010555
Daniel Veillardc0826a72004-08-10 14:17:33 +000010556 /*
10557 * TODO: Evaluate, what errors could occur if the declaration is not
10558 * found. It might be possible that the "typefixup" might crash if
10559 * no ref declaration was found.
10560 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010561 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010562 if (elemDecl == NULL) {
10563 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010564 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010565 NULL, (xmlSchemaTypePtr) elem, elem->node,
10566 "ref", elem->ref, elem->refNs,
10567 XML_SCHEMA_TYPE_ELEMENT, NULL);
10568 } else
10569 elem->refDecl = elemDecl;
10570 } else {
10571 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
10572 xmlSchemaTypePtr type;
10573
10574 /* (type definition) ... otherwise the type definition ·resolved·
10575 * to by the ·actual value· of the type [attribute] ...
10576 */
10577 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
10578 elem->namedTypeNs);
10579 if (type == NULL) {
10580 xmlSchemaPResCompAttrErr(ctxt,
10581 XML_SCHEMAP_SRC_RESOLVE,
10582 NULL, (xmlSchemaTypePtr) elem, elem->node,
10583 "type", elem->namedType, elem->namedTypeNs,
10584 XML_SCHEMA_TYPE_BASIC, "type definition");
10585 } else
10586 elem->subtypes = type;
10587 }
10588 if (elem->substGroup != NULL) {
10589 xmlSchemaElementPtr substHead;
10590
10591 /*
10592 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
10593 * substitutionGroup?
10594 */
10595 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010596 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010597 if (substHead == NULL) {
10598 xmlSchemaPResCompAttrErr(ctxt,
10599 XML_SCHEMAP_SRC_RESOLVE,
10600 NULL, (xmlSchemaTypePtr) elem, NULL,
10601 "substitutionGroup", elem->substGroup, elem->substGroupNs,
10602 XML_SCHEMA_TYPE_ELEMENT, NULL);
10603 } else {
10604 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
10605 /*
10606 * (type definition)...otherwise the {type definition} of the
10607 * element declaration ·resolved· to by the ·actual value· of
10608 * the substitutionGroup [attribute], if present
10609 */
10610 if (elem->subtypes == NULL)
10611 elem->subtypes = substHead->subtypes;
10612 }
10613 }
10614 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
10615 (elem->substGroup == NULL))
10616 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10617 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010618}
10619
William M. Bracke7091952004-05-11 15:09:58 +000010620/**
10621 * xmlSchemaParseListRefFixup:
10622 * @type: the schema type definition
10623 * @ctxt: the schema parser context
10624 *
10625 * Fixup of the itemType reference of the list type.
10626 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010627static void
William M. Bracke7091952004-05-11 15:09:58 +000010628xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010629{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010630
Daniel Veillard01fa6152004-06-29 17:04:39 +000010631 if (((type->base == NULL) &&
10632 (type->subtypes == NULL)) ||
10633 ((type->base != NULL) &&
10634 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010635 /*
10636 * src-list-itemType-or-simpleType
10637 * Either the itemType [attribute] or the <simpleType> [child] of
10638 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010639 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010640 /*
10641 * TODO: Move this to the parse function.
10642 */
10643 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010644 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010645 NULL, type, type->node,
10646 "The attribute 'itemType' and the <simpleType> child "
10647 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010648 } else if (type->base!= NULL) {
10649 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
10650 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010651 xmlSchemaPResCompAttrErr(ctxt,
10652 XML_SCHEMAP_SRC_RESOLVE,
10653 NULL, type, type->node,
10654 "itemType", type->base, type->baseNs,
10655 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010656 }
10657 }
10658 if ((type->subtypes != NULL) &&
10659 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
10660 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +000010661}
10662
10663/**
10664 * xmlSchemaParseUnionRefCheck:
10665 * @typeDecl: the schema type definition
10666 * @ctxt: the schema parser context
10667 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000010668 * Checks and builds the memberTypes of the union type.
10669 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000010670 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010671static int
William M. Bracke7091952004-05-11 15:09:58 +000010672xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +000010673 xmlSchemaParserCtxtPtr ctxt)
10674{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010675
Daniel Veillard01fa6152004-06-29 17:04:39 +000010676 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
10677 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000010678
Daniel Veillard01fa6152004-06-29 17:04:39 +000010679 /* 1 If the <union> alternative is chosen, then [Definition:]
10680 * define the explicit members as the type definitions ·resolved·
10681 * to by the items in the ·actual value· of the memberTypes [attribute],
10682 * if any, followed by the type definitions corresponding to the
10683 * <simpleType>s among the [children] of <union>, if any.
10684 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010685
Daniel Veillard01fa6152004-06-29 17:04:39 +000010686 if (type->type != XML_SCHEMA_TYPE_UNION)
10687 return (-1);
10688 if (ctxt->ctxtType == NULL) {
10689 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010690 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010691 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
10692 "available", NULL, NULL);
10693 return (-1);
10694 }
10695 /*
10696 * src-union-memberTypes-or-simpleTypes
10697 * Either the memberTypes [attribute] of the <union> element must
10698 * be non-empty or there must be at least one simpleType [child].
10699 */
10700 if ((type->base == NULL) &&
10701 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010702 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010703 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010704 NULL, NULL, type->node,
10705 "Either the attribute 'memberTypes' must be non-empty "
10706 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010707 }
10708
10709 ctxtType = ctxt->ctxtType;
10710 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010711 xmlAttrPtr attr;
10712 const xmlChar *cur, *end;
10713 xmlChar *tmp;
10714 const xmlChar *localName, *uri;
10715
10716 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010717 cur = type->base;
10718 do {
10719 while (IS_BLANK_CH(*cur))
10720 cur++;
10721 end = cur;
10722 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
10723 end++;
10724 if (end == cur)
10725 break;
10726 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010727 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
10728 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
10729 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010730 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010731 xmlSchemaPResCompAttrErr(ctxt,
10732 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
10733 NULL, NULL, type->node, "memberTypes", localName, uri,
10734 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010735 } else {
10736 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10737 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10738 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10739 if (link == NULL) {
10740 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10741 return (-1);
10742 }
10743 link->type = memberType;
10744 link->next = NULL;
10745 if (lastLink == NULL)
10746 ctxtType->memberTypes = link;
10747 else
10748 lastLink->next = link;
10749 lastLink = link;
10750 }
10751 xmlFree(tmp);
10752 cur = end;
10753 } while (*cur != 0);
10754 }
10755 /*
10756 * Add local simple types,
10757 */
10758 memberType = type->subtypes;
10759 while (memberType != NULL) {
10760 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10761 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10762 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10763 if (link == NULL) {
10764 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10765 return (-1);
10766 }
10767 link->type = memberType;
10768 link->next = NULL;
10769 if (lastLink == NULL)
10770 ctxtType->memberTypes = link;
10771 else
10772 lastLink->next = link;
10773 lastLink = link;
10774 memberType = memberType->next;
10775 }
10776 /*
10777 * The actual value is then formed by replacing any union type
10778 * definition in the ·explicit members· with the members of their
10779 * {member type definitions}, in order.
10780 */
10781 link = ctxtType->memberTypes;
10782 while (link != NULL) {
10783 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10784 subLink = link->type->memberTypes;
10785 if (subLink != NULL) {
10786 link->type = subLink->type;
10787 if (subLink->next != NULL) {
10788 lastLink = link->next;
10789 subLink = subLink->next;
10790 prevLink = link;
10791 while (subLink != NULL) {
10792 newLink = (xmlSchemaTypeLinkPtr)
10793 xmlMalloc(sizeof(xmlSchemaTypeLink));
10794 if (newLink == NULL) {
10795 xmlSchemaPErrMemory(ctxt, "allocating a type link",
10796 NULL);
10797 return (-1);
10798 }
10799 newLink->type = memberType;
10800 prevLink->next = newLink;
10801 prevLink = newLink;
10802 newLink->next = lastLink;
10803
10804 subLink = subLink->next;
10805 }
10806 }
10807 }
10808 }
10809 link = link->next;
10810 }
10811
10812 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000010813}
10814
Daniel Veillard4255d502002-04-16 15:50:10 +000010815/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010816 * xmlSchemaIsDerivedFromBuiltInType:
10817 * @ctxt: the schema parser context
10818 * @type: the type definition
10819 * @valType: the value type
10820 *
10821 *
10822 * Returns 1 if the type has the given value type, or
10823 * is derived from such a type.
10824 */
William M. Brack803812b2004-06-03 02:11:24 +000010825static int
Daniel Veillard3646d642004-06-02 19:19:14 +000010826xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
10827 xmlSchemaTypePtr type, int valType)
10828{
10829 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010830 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000010831 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010832 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000010833 return(1);
10834 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
10835 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
10836 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
10837 ((xmlSchemaAttributePtr) type)->subtypes, valType));
10838 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
10839 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
10840 if (type->baseType != NULL)
10841 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
10842 valType));
10843 } else if ((type->subtypes != NULL) &&
10844 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
10845 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10846 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
10847 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
10848 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
10849 valType));
10850 }
10851
10852 return (0);
10853}
10854
10855/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010856 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000010857 * @type: the simpleType definition
10858 *
10859 * Returns the primitive type of the given type or
10860 * NULL in case of error.
10861 */
10862static xmlSchemaTypePtr
10863xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
10864{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010865
Daniel Veillard01fa6152004-06-29 17:04:39 +000010866 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010867 /*
10868 * Note that anySimpleType is actually not a primitive type
10869 * but we need that here.
10870 */
10871 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
10872 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000010873 return (type);
10874 type = type->baseType;
10875 }
10876
10877 return (NULL);
10878}
10879
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010880#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010881/**
10882 * xmlSchemaGetBuiltInTypeAncestor:
10883 * @type: the simpleType definition
10884 *
10885 * Returns the primitive type of the given type or
10886 * NULL in case of error.
10887 */
10888static xmlSchemaTypePtr
10889xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
10890{
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000010891 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
10892 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))
10893 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010894 while (type != NULL) {
10895 if (type->type == XML_SCHEMA_TYPE_BASIC)
10896 return (type);
10897 type = type->baseType;
10898 }
10899
10900 return (NULL);
10901}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010902#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010903
Daniel Veillard01fa6152004-06-29 17:04:39 +000010904/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010905 * xmlSchemaBuildAttributeUsesOwned:
10906 * @ctxt: the schema parser context
10907 * @type: the complex type definition
10908 * @cur: the attribute declaration list
10909 * @lastUse: the top of the attribute use list
10910 *
10911 * Builds the attribute uses list on the given complex type.
10912 * This one is supposed to be called by
10913 * xmlSchemaBuildAttributeValidation only.
10914 */
10915static int
10916xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
10917 xmlSchemaAttributePtr cur,
10918 xmlSchemaAttributeLinkPtr *uses,
10919 xmlSchemaAttributeLinkPtr *lastUse)
10920{
10921 xmlSchemaAttributeLinkPtr tmp;
10922 while (cur != NULL) {
10923 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10924 /*
10925 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
10926 * to by the ·actual value·s of the ref [attribute] of the
10927 * <attributeGroup> [children], if any."
10928 */
10929 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
10930 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
10931 lastUse) == -1) {
10932 return (-1);
10933 }
10934 } else {
10935 /* W3C: "1 The set of attribute uses corresponding to the
10936 * <attribute> [children], if any."
10937 */
10938 tmp = (xmlSchemaAttributeLinkPtr)
10939 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10940 if (tmp == NULL) {
10941 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
10942 return (-1);
10943 }
10944 tmp->attr = cur;
10945 tmp->next = NULL;
10946 if (*uses == NULL)
10947 *uses = tmp;
10948 else
10949 (*lastUse)->next = tmp;
10950 *lastUse = tmp;
10951 }
10952 cur = cur->next;
10953 }
10954 return (0);
10955}
10956
Daniel Veillard50355f02004-06-08 17:52:16 +000010957/**
10958 * xmlSchemaCloneWildcardNsConstraints:
10959 * @ctxt: the schema parser context
10960 * @dest: the destination wildcard
10961 * @source: the source wildcard
10962 *
10963 * Clones the namespace constraints of source
10964 * and assignes them to dest.
10965 * Returns -1 on internal error, 0 otherwise.
10966 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010967static int
10968xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
10969 xmlSchemaWildcardPtr *dest,
10970 xmlSchemaWildcardPtr source)
10971{
10972 xmlSchemaWildcardNsPtr cur, tmp, last;
10973
10974 if ((source == NULL) || (*dest == NULL))
10975 return(-1);
10976 (*dest)->any = source->any;
10977 cur = source->nsSet;
10978 last = NULL;
10979 while (cur != NULL) {
10980 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10981 if (tmp == NULL)
10982 return(-1);
10983 tmp->value = cur->value;
10984 if (last == NULL)
10985 (*dest)->nsSet = tmp;
10986 else
10987 last->next = tmp;
10988 last = tmp;
10989 cur = cur->next;
10990 }
10991 if ((*dest)->negNsSet != NULL)
10992 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
10993 if (source->negNsSet != NULL) {
10994 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10995 if ((*dest)->negNsSet == NULL)
10996 return(-1);
10997 (*dest)->negNsSet->value = source->negNsSet->value;
10998 } else
10999 (*dest)->negNsSet = NULL;
11000 return(0);
11001}
11002
Daniel Veillard50355f02004-06-08 17:52:16 +000011003/**
11004 * xmlSchemaUnionWildcards:
11005 * @ctxt: the schema parser context
11006 * @completeWild: the first wildcard
11007 * @curWild: the second wildcard
11008 *
11009 * Unions the namespace constraints of the given wildcards.
11010 * @completeWild will hold the resulting union.
11011 * Returns a positive error code on failure, -1 in case of an
11012 * internal error, 0 otherwise.
11013 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011014static int
11015xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
11016 xmlSchemaWildcardPtr completeWild,
11017 xmlSchemaWildcardPtr curWild)
11018{
11019 xmlSchemaWildcardNsPtr cur, curB, tmp;
11020
11021 /*
11022 * 1 If O1 and O2 are the same value, then that value must be the
11023 * value.
11024 */
11025 if ((completeWild->any == curWild->any) &&
11026 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11027 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
11028
11029 if ((completeWild->negNsSet == NULL) ||
11030 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
11031
11032 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011033 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011034
11035 /*
11036 * Check equality of sets.
11037 */
11038 cur = completeWild->nsSet;
11039 while (cur != NULL) {
11040 found = 0;
11041 curB = curWild->nsSet;
11042 while (curB != NULL) {
11043 if (cur->value == curB->value) {
11044 found = 1;
11045 break;
11046 }
11047 curB = curB->next;
11048 }
11049 if (!found)
11050 break;
11051 cur = cur->next;
11052 }
11053 if (found)
11054 return(0);
11055 } else
11056 return(0);
11057 }
11058 }
11059 /*
11060 * 2 If either O1 or O2 is any, then any must be the value
11061 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011062 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011063 if (completeWild->any == 0) {
11064 completeWild->any = 1;
11065 if (completeWild->nsSet != NULL) {
11066 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11067 completeWild->nsSet = NULL;
11068 }
11069 if (completeWild->negNsSet != NULL) {
11070 xmlFree(completeWild->negNsSet);
11071 completeWild->negNsSet = NULL;
11072 }
11073 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011074 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011075 }
11076 /*
11077 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
11078 * then the union of those sets must be the value.
11079 */
11080 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
11081 int found;
11082 xmlSchemaWildcardNsPtr start;
11083
11084 cur = curWild->nsSet;
11085 start = completeWild->nsSet;
11086 while (cur != NULL) {
11087 found = 0;
11088 curB = start;
11089 while (curB != NULL) {
11090 if (cur->value == curB->value) {
11091 found = 1;
11092 break;
11093 }
11094 curB = curB->next;
11095 }
11096 if (!found) {
11097 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11098 if (tmp == NULL)
11099 return (-1);
11100 tmp->value = cur->value;
11101 tmp->next = completeWild->nsSet;
11102 completeWild->nsSet = tmp;
11103 }
11104 cur = cur->next;
11105 }
11106
11107 return(0);
11108 }
11109 /*
11110 * 4 If the two are negations of different values (namespace names
11111 * or ·absent·), then a pair of not and ·absent· must be the value.
11112 */
11113 if ((completeWild->negNsSet != NULL) &&
11114 (curWild->negNsSet != NULL) &&
11115 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11116 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011117
11118 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011119 }
11120 /*
11121 * 5.
11122 */
11123 if (((completeWild->negNsSet != NULL) &&
11124 (completeWild->negNsSet->value != NULL) &&
11125 (curWild->nsSet != NULL)) ||
11126 ((curWild->negNsSet != NULL) &&
11127 (curWild->negNsSet->value != NULL) &&
11128 (completeWild->nsSet != NULL))) {
11129
11130 int nsFound, absentFound = 0;
11131
11132 if (completeWild->nsSet != NULL) {
11133 cur = completeWild->nsSet;
11134 curB = curWild->negNsSet;
11135 } else {
11136 cur = curWild->nsSet;
11137 curB = completeWild->negNsSet;
11138 }
11139 nsFound = 0;
11140 while (cur != NULL) {
11141 if (cur->value == NULL)
11142 absentFound = 1;
11143 else if (cur->value == curB->value)
11144 nsFound = 1;
11145 if (nsFound && absentFound)
11146 break;
11147 cur = cur->next;
11148 }
11149
11150 if (nsFound && absentFound) {
11151 /*
11152 * 5.1 If the set S includes both the negated namespace
11153 * name and ·absent·, then any must be the value.
11154 */
11155 completeWild->any = 1;
11156 if (completeWild->nsSet != NULL) {
11157 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11158 completeWild->nsSet = NULL;
11159 }
11160 if (completeWild->negNsSet != NULL) {
11161 xmlFree(completeWild->negNsSet);
11162 completeWild->negNsSet = NULL;
11163 }
11164 } else if (nsFound && (!absentFound)) {
11165 /*
11166 * 5.2 If the set S includes the negated namespace name
11167 * but not ·absent·, then a pair of not and ·absent· must
11168 * be the value.
11169 */
11170 if (completeWild->nsSet != NULL) {
11171 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11172 completeWild->nsSet = NULL;
11173 }
11174 if (completeWild->negNsSet == NULL) {
11175 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11176 if (completeWild->negNsSet == NULL)
11177 return (-1);
11178 }
11179 completeWild->negNsSet->value = NULL;
11180 } else if ((!nsFound) && absentFound) {
11181 /*
11182 * 5.3 If the set S includes ·absent· but not the negated
11183 * namespace name, then the union is not expressible.
11184 */
11185 xmlSchemaPErr(ctxt, completeWild->node,
11186 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011187 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011188 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011189 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011190 } else if ((!nsFound) && (!absentFound)) {
11191 /*
11192 * 5.4 If the set S does not include either the negated namespace
11193 * name or ·absent·, then whichever of O1 or O2 is a pair of not
11194 * and a namespace name must be the value.
11195 */
11196 if (completeWild->negNsSet == NULL) {
11197 if (completeWild->nsSet != NULL) {
11198 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11199 completeWild->nsSet = NULL;
11200 }
11201 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11202 if (completeWild->negNsSet == NULL)
11203 return (-1);
11204 completeWild->negNsSet->value = curWild->negNsSet->value;
11205 }
11206 }
11207 return (0);
11208 }
11209 /*
11210 * 6.
11211 */
11212 if (((completeWild->negNsSet != NULL) &&
11213 (completeWild->negNsSet->value == NULL) &&
11214 (curWild->nsSet != NULL)) ||
11215 ((curWild->negNsSet != NULL) &&
11216 (curWild->negNsSet->value == NULL) &&
11217 (completeWild->nsSet != NULL))) {
11218
11219 if (completeWild->nsSet != NULL) {
11220 cur = completeWild->nsSet;
11221 } else {
11222 cur = curWild->nsSet;
11223 }
11224 while (cur != NULL) {
11225 if (cur->value == NULL) {
11226 /*
11227 * 6.1 If the set S includes ·absent·, then any must be the
11228 * value.
11229 */
11230 completeWild->any = 1;
11231 if (completeWild->nsSet != NULL) {
11232 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11233 completeWild->nsSet = NULL;
11234 }
11235 if (completeWild->negNsSet != NULL) {
11236 xmlFree(completeWild->negNsSet);
11237 completeWild->negNsSet = NULL;
11238 }
11239 return (0);
11240 }
11241 cur = cur->next;
11242 }
11243 if (completeWild->negNsSet == NULL) {
11244 /*
11245 * 6.2 If the set S does not include ·absent·, then a pair of not
11246 * and ·absent· must be the value.
11247 */
11248 if (completeWild->nsSet != NULL) {
11249 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11250 completeWild->nsSet = NULL;
11251 }
11252 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11253 if (completeWild->negNsSet == NULL)
11254 return (-1);
11255 completeWild->negNsSet->value = NULL;
11256 }
11257 return (0);
11258 }
11259 return (0);
11260
11261}
11262
Daniel Veillard50355f02004-06-08 17:52:16 +000011263/**
11264 * xmlSchemaIntersectWildcards:
11265 * @ctxt: the schema parser context
11266 * @completeWild: the first wildcard
11267 * @curWild: the second wildcard
11268 *
11269 * Intersects the namespace constraints of the given wildcards.
11270 * @completeWild will hold the resulting intersection.
11271 * Returns a positive error code on failure, -1 in case of an
11272 * internal error, 0 otherwise.
11273 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011274static int
11275xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
11276 xmlSchemaWildcardPtr completeWild,
11277 xmlSchemaWildcardPtr curWild)
11278{
William M. Brack803812b2004-06-03 02:11:24 +000011279 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011280
11281 /*
11282 * 1 If O1 and O2 are the same value, then that value must be the
11283 * value.
11284 */
11285 if ((completeWild->any == curWild->any) &&
11286 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11287 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
11288
11289 if ((completeWild->negNsSet == NULL) ||
11290 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
11291
11292 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011293 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011294
11295 /*
11296 * Check equality of sets.
11297 */
11298 cur = completeWild->nsSet;
11299 while (cur != NULL) {
11300 found = 0;
11301 curB = curWild->nsSet;
11302 while (curB != NULL) {
11303 if (cur->value == curB->value) {
11304 found = 1;
11305 break;
11306 }
11307 curB = curB->next;
11308 }
11309 if (!found)
11310 break;
11311 cur = cur->next;
11312 }
11313 if (found)
11314 return(0);
11315 } else
11316 return(0);
11317 }
11318 }
11319 /*
11320 * 2 If either O1 or O2 is any, then the other must be the value.
11321 */
11322 if ((completeWild->any != curWild->any) && (completeWild->any)) {
11323 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
11324 return(-1);
11325 return(0);
11326 }
11327 /*
11328 * 3 If either O1 or O2 is a pair of not and a value (a namespace
11329 * name or ·absent·) and the other is a set of (namespace names or
11330 * ·absent·), then that set, minus the negated value if it was in
11331 * the set, minus ·absent· if it was in the set, must be the value.
11332 */
11333 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
11334 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
11335 const xmlChar *neg;
11336
11337 if (completeWild->nsSet == NULL) {
11338 neg = completeWild->negNsSet->value;
11339 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
11340 return(-1);
11341 } else
11342 neg = curWild->negNsSet->value;
11343 /*
11344 * Remove absent and negated.
11345 */
11346 prev = NULL;
11347 cur = completeWild->nsSet;
11348 while (cur != NULL) {
11349 if (cur->value == NULL) {
11350 if (prev == NULL)
11351 completeWild->nsSet = cur->next;
11352 else
11353 prev->next = cur->next;
11354 xmlFree(cur);
11355 break;
11356 }
11357 prev = cur;
11358 cur = cur->next;
11359 }
11360 if (neg != NULL) {
11361 prev = NULL;
11362 cur = completeWild->nsSet;
11363 while (cur != NULL) {
11364 if (cur->value == neg) {
11365 if (prev == NULL)
11366 completeWild->nsSet = cur->next;
11367 else
11368 prev->next = cur->next;
11369 xmlFree(cur);
11370 break;
11371 }
11372 prev = cur;
11373 cur = cur->next;
11374 }
11375 }
11376
11377 return(0);
11378 }
11379 /*
11380 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
11381 * then the intersection of those sets must be the value.
11382 */
11383 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
11384 int found;
11385
11386 cur = completeWild->nsSet;
11387 prev = NULL;
11388 while (cur != NULL) {
11389 found = 0;
11390 curB = curWild->nsSet;
11391 while (curB != NULL) {
11392 if (cur->value == curB->value) {
11393 found = 1;
11394 break;
11395 }
11396 curB = curB->next;
11397 }
11398 if (!found) {
11399 if (prev == NULL)
11400 completeWild->nsSet = cur->next;
11401 else
11402 prev->next = cur->next;
11403 tmp = cur->next;
11404 xmlFree(cur);
11405 cur = tmp;
11406 continue;
11407 }
11408 prev = cur;
11409 cur = cur->next;
11410 }
11411
11412 return(0);
11413 }
11414 /* 5 If the two are negations of different namespace names,
11415 * then the intersection is not expressible
11416 */
11417 if ((completeWild->negNsSet != NULL) &&
11418 (curWild->negNsSet != NULL) &&
11419 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
11420 (completeWild->negNsSet->value != NULL) &&
11421 (curWild->negNsSet->value != NULL)) {
11422
11423 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011424 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011425 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011426 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011427 }
11428 /*
11429 * 6 If the one is a negation of a namespace name and the other
11430 * is a negation of ·absent·, then the one which is the negation
11431 * of a namespace name must be the value.
11432 */
11433 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
11434 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
11435 (completeWild->negNsSet->value == NULL)) {
11436 completeWild->negNsSet->value = curWild->negNsSet->value;
11437 }
11438 return(0);
11439}
11440
Daniel Veillard50355f02004-06-08 17:52:16 +000011441/**
11442 * xmlSchemaIsWildcardNsConstraintSubset:
11443 * @ctxt: the schema parser context
11444 * @wildA: the first wildcard
11445 * @wildB: the second wildcard
11446 *
11447 * Returns 1 if the namespace constraint of @wildA is an intensional
11448 * subset of @wildB, 0 otherwise.
11449 */
11450static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000011451xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
11452 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000011453{
Daniel Veillard3646d642004-06-02 19:19:14 +000011454
Daniel Veillard50355f02004-06-08 17:52:16 +000011455 /*
11456 * Schema Component Constraint: Wildcard Subset
11457 */
11458 /*
11459 * 1 super must be any.
11460 */
11461 if (wildB->any)
11462 return (1);
11463 /*
11464 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
11465 * 2.2 super must be a pair of not and the same value.
11466 */
11467 if ((wildA->negNsSet != NULL) &&
11468 (wildB->negNsSet != NULL) &&
11469 (wildA->negNsSet->value == wildA->negNsSet->value))
11470 return (1);
11471 /*
11472 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
11473 */
11474 if (wildA->nsSet != NULL) {
11475 /*
11476 * 3.2.1 super must be the same set or a superset thereof.
11477 */
11478 if (wildB->nsSet != NULL) {
11479 xmlSchemaWildcardNsPtr cur, curB;
11480 int found = 0;
11481
11482 cur = wildA->nsSet;
11483 while (cur != NULL) {
11484 found = 0;
11485 curB = wildB->nsSet;
11486 while (curB != NULL) {
11487 if (cur->value == curB->value) {
11488 found = 1;
11489 break;
11490 }
11491 curB = curB->next;
11492 }
11493 if (!found)
11494 return (0);
11495 cur = cur->next;
11496 }
11497 if (found)
11498 return (1);
11499 } else if (wildB->negNsSet != NULL) {
11500 xmlSchemaWildcardNsPtr cur;
11501 /*
11502 * 3.2.2 super must be a pair of not and a namespace name or
11503 * ·absent· and that value must not be in sub's set.
11504 */
11505 cur = wildA->nsSet;
11506 while (cur != NULL) {
11507 if (cur->value == wildB->negNsSet->value)
11508 return (0);
11509 cur = cur->next;
11510 }
11511 return (1);
11512 }
11513 }
11514 return (0);
11515}
11516
11517/**
11518 * xmlSchemaBuildCompleteAttributeWildcard:
11519 * @ctxt: the schema parser context
11520 * @attrs: the attribute list
11521 * @completeWild: the resulting complete wildcard
11522 *
11523 * Returns -1 in case of an internal error, 0 otherwise.
11524 */
11525static int
11526xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
11527 xmlSchemaAttributePtr attrs,
11528 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000011529{
11530 while (attrs != NULL) {
11531 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
11532 xmlSchemaAttributeGroupPtr group;
11533
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011534 group = (xmlSchemaAttributeGroupPtr) attrs;
11535 /*
11536 * Handle attribute group references.
11537 */
11538 if (group->ref != NULL) {
11539 if (group->refItem == NULL) {
11540 /*
11541 * TODO: Should we raise a warning here?
11542 */
11543 /*
11544 * The referenced attribute group definition could not
11545 * be resolved beforehand, so skip.
11546 */
11547 attrs = attrs->next;
11548 continue;
11549 } else
11550 group = group->refItem;
11551 }
11552 /*
11553 * For every attribute group definition, an intersected wildcard
11554 * will be created (assumed that a wildcard exists on the
11555 * particular attr. gr. def. or on any contained attr. gr. def
11556 * at all).
11557 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
11558 * that the intersection will be performed only once.
11559 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011560 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
11561 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000011562 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11563 group->attributes, &group->attributeWildcard) == -1)
11564 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011565 }
11566 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
11567 }
11568 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000011569 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011570 /*
11571 * Copy the first encountered wildcard as context, except for the annotation.
11572 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011573 *completeWild = xmlSchemaAddWildcard(ctxt);
11574 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
11575 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
11576 completeWild, group->attributeWildcard) == -1)
11577 return (-1);
11578 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000011579 /*
11580 * Although the complete wildcard might not correspond to any
11581 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011582 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000011583 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011584 (*completeWild)->node = group->attributeWildcard->node;
11585
11586 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
11587 xmlSchemaFreeWildcard(*completeWild);
11588 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011589 }
11590 }
11591 }
11592 attrs = attrs->next;
11593 }
11594
Daniel Veillard50355f02004-06-08 17:52:16 +000011595 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011596}
11597
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011598static int
11599xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
11600 int *fixed,
11601 const xmlChar **value,
11602 xmlSchemaValPtr *val)
11603{
11604 *fixed = 0;
11605 *value = NULL;
11606 if (val != 0)
11607 *val = NULL;
11608
11609 if (item->defValue == NULL)
11610 item = item->refDecl;
11611
11612 if (item == NULL)
11613 return (0);
11614
11615 if (item->defValue != NULL) {
11616 *value = item->defValue;
11617 if (val != 0)
11618 *val = item->defVal;
11619 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
11620 *fixed = 1;
11621 return (1);
11622 }
11623 return (0);
11624}
Daniel Veillard3646d642004-06-02 19:19:14 +000011625/**
11626 * xmlSchemaMatchesWildcardNs:
11627 * @wild: the wildcard
11628 * @ns: the namespace
11629 *
11630 *
11631 * Returns 1 if the given namespace matches the wildcard,
11632 * 0 otherwise.
11633 */
11634static int
11635xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
11636{
11637 if (wild == NULL)
11638 return(0);
11639
11640 if (wild->any)
11641 return(1);
11642 else if (wild->nsSet != NULL) {
11643 xmlSchemaWildcardNsPtr cur;
11644
11645 cur = wild->nsSet;
11646 while (cur != NULL) {
11647 if (xmlStrEqual(cur->value, ns))
11648 return(1);
11649 cur = cur->next;
11650 }
11651 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
11652 (!xmlStrEqual(wild->negNsSet->value, ns)))
11653 return(1);
11654
11655 return(0);
11656}
11657
11658/**
11659 * xmlSchemaBuildAttributeValidation:
11660 * @ctxt: the schema parser context
11661 * @type: the complex type definition
11662 *
11663 *
11664 * Builds the wildcard and the attribute uses on the given complex type.
11665 * Returns -1 if an internal error occurs, 0 otherwise.
11666 */
11667static int
11668xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
11669{
11670 xmlSchemaTypePtr baseType = NULL;
11671 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000011672 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000011673 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011674 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000011675 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011676 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011677 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011678
Daniel Veillard01fa6152004-06-29 17:04:39 +000011679 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011680 /*
11681 * Complex Type Definition with complex content Schema Component.
11682 *
11683 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011684 * TODO: Add checks for absent referenced attribute declarations and
11685 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000011686 */
11687 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011688 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011689 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000011690 "attribute uses already builded.\n",
11691 NULL, NULL);
11692 return (-1);
11693 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011694 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011695 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011696 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011697 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011698 type->name, NULL);
11699 return (-1);
11700 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011701 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011702 if (baseType == anyType)
11703 baseIsAnyType = 1;
11704 /*
11705 * Inherit the attribute uses of the base type.
11706 */
11707 /*
11708 * NOTE: It is allowed to "extend" the anyType complex type.
11709 */
11710 if (!baseIsAnyType) {
11711 if (baseType != NULL) {
11712 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
11713 tmp = (xmlSchemaAttributeLinkPtr)
11714 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11715 if (tmp == NULL) {
11716 xmlSchemaPErrMemory(ctxt,
11717 "building attribute uses of complexType", NULL);
11718 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011719 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011720 tmp->attr = cur->attr;
11721 tmp->next = NULL;
11722 if (type->attributeUses == NULL) {
11723 type->attributeUses = tmp;
11724 } else
11725 lastBaseUse->next = tmp;
11726 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011727 }
11728 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011729 }
11730 if ((type->subtypes != NULL) &&
11731 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11732 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011733 /*
11734 * type --> (<simpleContent>|<complexContent>)
11735 * --> (<restriction>|<extension>) --> attributes
11736 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011737 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011738 } else {
11739 /* Short hand form of the complexType. */
11740 attrs = type->attributes;
11741 }
11742 /*
11743 * Handle attribute wildcards.
11744 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011745 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11746 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011747 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011748 * NOTE: During the parse time, the wildcard is created on the complexType
11749 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011750 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011751 if (err == -1) {
11752 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
11753 "Internal error: xmlSchemaBuildAttributeValidation: "
11754 "failed to build an intersected attribute wildcard.\n",
11755 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011756 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011757 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011758
11759 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
11760 ((baseIsAnyType) ||
11761 ((baseType != NULL) &&
11762 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11763 (baseType->attributeWildcard != NULL)))) {
11764 if (type->attributeWildcard != NULL) {
11765 /*
11766 * Union the complete wildcard with the base wildcard.
11767 */
11768 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
11769 baseType->attributeWildcard) == -1)
11770 return (-1);
11771 } else {
11772 /*
11773 * Just inherit the wildcard.
11774 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011775 /*
11776 * NOTE: This is the only case where an attribute
11777 * wildcard is shared.
11778 */
11779 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
11780 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011781 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000011782 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011783 }
11784
11785 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11786 if (type->attributeWildcard != NULL) {
11787 /*
11788 * Derivation Valid (Restriction, Complex)
11789 * 4.1 The {base type definition} must also have one.
11790 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011791 if (baseType->attributeWildcard == NULL) {
11792 xmlSchemaPCustomErr(ctxt,
11793 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
11794 NULL, type, NULL,
11795 "The type has an attribute wildcard, "
11796 "but the base type %s does not have one",
11797 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11798 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011799 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011800 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011801 type->attributeWildcard, baseType->attributeWildcard) == 0) {
11802 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011803 xmlSchemaPCustomErr(ctxt,
11804 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
11805 NULL, type, NULL,
11806 "The attribute wildcard is not a valid "
11807 "subset of the wildcard in the base type %s",
11808 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11809 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011810 return (1);
11811 }
11812 /* 4.3 Unless the {base type definition} is the ·ur-type
11813 * definition·, the complex type definition's {attribute
11814 * wildcard}'s {process contents} must be identical to or
11815 * stronger than the {base type definition}'s {attribute
11816 * wildcard}'s {process contents}, where strict is stronger
11817 * than lax is stronger than skip.
11818 */
11819 if ((type->baseType != anyType) &&
11820 (type->attributeWildcard->processContents <
11821 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011822 xmlSchemaPCustomErr(ctxt,
11823 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
11824 NULL, type, NULL,
11825 "The 'process contents' of the attribute wildcard is weaker than "
11826 "the one in the base type %s",
11827 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11828 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011829 return (1);
11830 }
11831 }
11832 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11833 /*
11834 * Derivation Valid (Extension)
11835 * At this point the type and the base have both, either
11836 * no wildcard or a wildcard.
11837 */
11838 if ((baseType->attributeWildcard != NULL) &&
11839 (baseType->attributeWildcard != type->attributeWildcard)) {
11840 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011841 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011842 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011843 xmlSchemaPCustomErr(ctxt,
11844 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
11845 NULL, type, NULL,
11846 "The attribute wildcard is not a valid "
11847 "superset of the one in the base type %s",
11848 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11849 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011850 return (1);
11851 }
11852 }
11853 }
11854
Daniel Veillard3646d642004-06-02 19:19:14 +000011855 /*
11856 * Gather attribute uses defined by this type.
11857 */
11858 if (attrs != NULL) {
11859 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
11860 &uses, &lastUse) == -1) {
11861 return (-1);
11862 }
11863 }
11864 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
11865 * "Two distinct attribute declarations in the {attribute uses} must
11866 * not have identical {name}s and {target namespace}s."
11867 *
11868 * For "extension" this is done further down.
11869 */
11870 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
11871 cur = uses;
11872 while (cur != NULL) {
11873 tmp = cur->next;
11874 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011875 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11876 xmlSchemaGetAttrName(tmp->attr))) &&
11877 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11878 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
11879
11880 xmlSchemaPAttrUseErr(ctxt,
11881 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11882 NULL, type, NULL, cur->attr,
11883 "Duplicate attribute use %s specified",
11884 xmlSchemaFormatNsUriLocal(&str,
11885 xmlSchemaGetAttrTargetNsURI(tmp->attr),
11886 xmlSchemaGetAttrName(tmp->attr))
11887 );
11888 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011889 break;
11890 }
11891 tmp = tmp->next;
11892 }
11893 cur = cur->next;
11894 }
11895 }
11896 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11897 /*
11898 * Derive by restriction.
11899 */
11900 if (baseIsAnyType) {
11901 type->attributeUses = uses;
11902 } else {
11903 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011904 const xmlChar *bEffValue;
11905 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000011906
11907 cur = uses;
11908 while (cur != NULL) {
11909 found = 0;
11910 base = type->attributeUses;
11911 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011912 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11913 xmlSchemaGetAttrName(base->attr)) &&
11914 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
11915 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011916
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011917 found = 1;
11918
Daniel Veillard3646d642004-06-02 19:19:14 +000011919 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
11920 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11921 /*
11922 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000011923 */
11924 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011925 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011926 NULL, type, NULL, cur->attr,
11927 "The 'optional' use is inconsistent with a matching "
11928 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011929 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
11930 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11931 /*
11932 * derivation-ok-restriction 3
11933 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011934 xmlSchemaPCustomErr(ctxt,
11935 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
11936 NULL, type, NULL,
11937 "A matching attribute use for the 'required' "
11938 "attribute use %s of the base type is missing",
11939 xmlSchemaFormatNsUriLocal(&str,
11940 xmlSchemaGetAttrTargetNsURI(base->attr),
11941 xmlSchemaGetAttrName(base->attr)));
11942 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011943 } else {
11944 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011945 * 2.1.3 [Definition:] Let the effective value
11946 * constraint of an attribute use be its {value
11947 * constraint}, if present, otherwise its {attribute
11948 * declaration}'s {value constraint} .
11949 */
11950 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11951 &bEffValue, 0);
11952 /*
11953 * 2.1.3 ... one of the following must be true
11954 *
11955 * 2.1.3.1 B's ·effective value constraint· is
11956 * ·absent· or default.
11957 */
11958 if ((bEffValue != NULL) &&
11959 (effFixed == 1)) {
11960 const xmlChar *rEffValue = NULL;
11961
11962 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11963 &rEffValue, 0);
11964 /*
11965 * 2.1.3.2 R's ·effective value constraint· is
11966 * fixed with the same string as B's.
11967 */
11968 if ((effFixed == 0) ||
11969 (! xmlStrEqual(rEffValue, bEffValue))) {
11970 xmlSchemaPAttrUseErr(ctxt,
11971 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
11972 NULL, type, NULL, cur->attr,
11973 "The effective value constraint of the "
11974 "attribute use is inconsistent with "
11975 "its correspondent of the base type",
11976 NULL);
11977 }
11978 }
11979 /*
11980 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
11981 */
11982 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011983 * Override the attribute use.
11984 */
11985 base->attr = cur->attr;
11986 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011987
Daniel Veillard3646d642004-06-02 19:19:14 +000011988 break;
11989 }
11990 base = base->next;
11991 }
11992
11993 if (!found) {
11994 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11995 /*
11996 * derivation-ok-restriction 2.2
11997 */
11998 if ((type->attributeWildcard != NULL) &&
11999 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
12000 cur->attr->targetNamespace))
12001 found = 1;
12002
12003 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012004 xmlSchemaPAttrUseErr(ctxt,
12005 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12006 NULL, type, NULL, cur->attr,
12007 "Neither a matching attribute use, "
12008 "nor a matching wildcard in the base type does exist",
12009 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012010 } else {
12011 /*
12012 * Add the attribute use.
12013 *
12014 * Note that this may lead to funny derivation error reports, if
12015 * multiple equal attribute uses exist; but this is not
12016 * allowed anyway, and it will be reported beforehand.
12017 */
12018 tmp = cur;
12019 if (prev != NULL)
12020 prev->next = cur->next;
12021 else
12022 uses = cur->next;
12023 cur = cur->next;
12024 if (type->attributeUses == NULL) {
12025 type->attributeUses = tmp;
12026 } else
12027 lastBaseUse->next = tmp;
12028 lastBaseUse = tmp;
12029
12030 continue;
12031 }
12032 }
12033 }
12034 prev = cur;
12035 cur = cur->next;
12036 }
12037 if (uses != NULL)
12038 xmlSchemaFreeAttributeUseList(uses);
12039 }
12040 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12041 /*
12042 * The spec allows only appending, and not other kinds of extensions.
12043 *
12044 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
12045 */
12046 if (uses != NULL) {
12047 if (type->attributeUses == NULL) {
12048 type->attributeUses = uses;
12049 } else
12050 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012051 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012052 } else {
12053 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000012054 * Derive implicitely from the ur-type.
12055 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012056 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012057 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012058 /*
12059 * 3.4.6 -> Complex Type Definition Properties Correct
12060 */
12061 if (type->attributeUses != NULL) {
12062 cur = type->attributeUses;
12063 prev = NULL;
12064 while (cur != NULL) {
12065 /*
12066 * 4. Two distinct attribute declarations in the {attribute uses} must
12067 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012068 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012069 * Note that this was already done for "restriction" and types derived from
12070 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012071 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012072 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12073 tmp = cur->next;
12074 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012075 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12076 xmlSchemaGetAttrName(tmp->attr))) &&
12077 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
12078 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012079
Daniel Veillardc0826a72004-08-10 14:17:33 +000012080 xmlSchemaPAttrUseErr(ctxt,
12081 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12082 NULL, type, NULL, tmp->attr,
12083 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012084 break;
12085 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012086 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012087 }
12088 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012089 /*
12090 * 5. Two distinct attribute declarations in the {attribute uses} must
12091 * not have {type definition}s which are or are derived from ID.
12092 */
12093 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012094 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012095 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012096 xmlSchemaPAttrUseErr(ctxt,
12097 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12098 NULL, type, NULL, cur->attr,
12099 "There must not exist more than one attribute use, "
12100 "declared of type 'ID' or derived from it",
12101 NULL);
12102 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000012103 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012104 id = cur;
12105 }
12106 /*
12107 * Remove "prohibited" attribute uses. The reason this is done at this late
12108 * stage is to be able to catch dublicate attribute uses. So we had to keep
12109 * prohibited uses in the list as well.
12110 */
12111 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12112 tmp = cur;
12113 if (prev == NULL)
12114 type->attributeUses = cur->next;
12115 else
12116 prev->next = cur->next;
12117 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012118 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012119 } else {
12120 prev = cur;
12121 cur = cur->next;
12122 }
12123 }
12124 }
12125 /*
12126 * TODO: This check should be removed if we are 100% sure of
12127 * the base type attribute uses already being built.
12128 */
12129 if ((baseType != NULL) && (!baseIsAnyType) &&
12130 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12131 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012132 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012133 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012134 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000012135 baseType->name, NULL);
12136 }
12137 return (0);
12138}
12139
12140/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000012141 * xmlSchemaTypeFinalContains:
12142 * @schema: the schema
12143 * @type: the type definition
12144 * @final: the final
12145 *
12146 * Evaluates if a type definition contains the given "final".
12147 * This does take "finalDefault" into account as well.
12148 *
12149 * Returns 1 if the type does containt the given "final",
12150 * 0 otherwise.
12151 */
12152static int
12153xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
12154{
12155 int tfinal = final, tflags = type->flags;
12156
12157 if (type == NULL)
12158 return (0);
12159 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
12160 switch (final) {
12161 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
12162 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
12163 break;
12164 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
12165 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
12166 break;
12167 case XML_SCHEMAS_TYPE_FINAL_LIST:
12168 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
12169 break;
12170 case XML_SCHEMAS_TYPE_FINAL_UNION:
12171 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
12172 break;
12173 }
12174 tflags = schema->flags;
12175 }
12176 if (tflags & tfinal)
12177 return (1);
12178 else
12179 return (0);
12180
12181}
12182
12183/**
12184 * xmlSchemaGetUnionSimpleTypeMemberTypes:
12185 * @type: the Union Simple Type
12186 *
12187 * Returns a list of member types of @type if existing,
12188 * returns NULL otherwise.
12189 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012190static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000012191xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
12192{
12193 while (type != NULL) {
12194 if (type->memberTypes != NULL)
12195 return (type->memberTypes);
12196 else
12197 type = type->baseType;
12198 }
12199 return (NULL);
12200}
12201
12202/**
12203 * xmlSchemaGetListSimpleTypeItemType:
12204 * @type: the simple type definition
12205 *
12206 * Returns the item type definition of the list simple type.
12207 */
12208static xmlSchemaTypePtr
12209xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
12210{
12211 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
12212 return (NULL);
12213 /*
12214 * Note: In libxml2, the built-in types do not reflect
12215 * the datatype hierarchy (yet?) - we have to treat them
12216 * in a special way.
12217 */
12218 if (type->type == XML_SCHEMA_TYPE_BASIC)
12219 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
12220 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
12221 /* 1 If the <list> alternative is chosen, then the type
12222 * definition ·resolved· to by the ·actual value· of the
12223 * itemType [attribute] of <list>, if present, otherwise
12224 * the type definition corresponding to the <simpleType>
12225 * among the [children] of <list>.
12226 */
12227 return (type->subtypes->subtypes);
12228 else {
12229 /* 2 If the <restriction> option is chosen, then the
12230 * {item type definition} of the {base type definition}.
12231 */
12232 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
12233 }
12234}
12235
12236/**
12237 * xmlSchemaCheckCOSSTDerivedOK:
12238 * @type: the derived simple type definition
12239 * @baseType: the base type definition
12240 *
12241 * Checks wheter @type can be validly
12242 * derived from @baseType.
12243 *
12244 * Returns 0 on success, an positive error code otherwise.
12245 */
12246static int
12247xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
12248 xmlSchemaTypePtr type,
12249 xmlSchemaTypePtr baseType,
12250 int subset)
12251{
12252 /*
12253 * Schema Component Constraint: Type Derivation OK (Simple)
12254 *
12255 *
12256 * 1 They are the same type definition.
12257 * TODO: The identy check might have to be more complex than this.
12258 */
12259 if (type == baseType)
12260 return (0);
12261 /*
12262 * 2.1 restriction is not in the subset, or in the {final}
12263 * of its own {base type definition};
12264 */
12265 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
12266 (xmlSchemaTypeFinalContains(schema,
12267 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
12268 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
12269 }
12270 /* 2.2 */
12271 if (type->baseType == baseType) {
12272 /*
12273 * 2.2.1 D's ·base type definition· is B.
12274 */
12275 return (0);
12276 }
12277 /*
12278 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
12279 * and is validly derived from B given the subset, as defined by this
12280 * constraint.
12281 */
12282 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
12283 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
12284 return (0);
12285 }
12286 /*
12287 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
12288 * definition·.
12289 */
12290 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
12291 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
12292 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
12293 return (0);
12294 }
12295 /*
12296 * 2.2.4 B's {variety} is union and D is validly derived from a type
12297 * definition in B's {member type definitions} given the subset, as
12298 * defined by this constraint.
12299 *
12300 * NOTE: This seems not to involve built-in types, since there is no
12301 * built-in Union Simple Type.
12302 */
12303 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12304 xmlSchemaTypeLinkPtr cur;
12305
12306 cur = baseType->memberTypes;
12307 while (cur != NULL) {
12308 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
12309 cur->type, subset) == 0)
12310 return (0);
12311 cur = cur->next;
12312 }
12313 }
12314
12315 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
12316}
12317
12318
12319/**
12320 * xmlSchemaCheckSTPropsCorrect:
12321 * @ctxt: the schema parser context
12322 * @type: the simple type definition
12323 *
12324 * Checks st-props-correct.
12325 *
12326 * Returns 0 if the properties are correct,
12327 * if not, a positive error code and -1 on internal
12328 * errors.
12329 */
12330static int
12331xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
12332 xmlSchemaTypePtr type)
12333{
12334 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
12335 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012336 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012337
Daniel Veillardc0826a72004-08-10 14:17:33 +000012338 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012339 /*
12340 * Schema Component Constraint: Simple Type Definition Properties Correct
12341 *
12342 * NOTE: This is somehow redundant, since we actually built a simple type
12343 * to have all the needed information; this acts as an self test.
12344 */
12345 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12346 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12347 /*
12348 * TODO: 1 The values of the properties of a simple type definition must be as
12349 * described in the property tableau in Datatype definition, modulo the
12350 * impact of Missing Sub-components (§5.3).
12351 */
12352 /* Base type: If the datatype has been ·derived· by ·restriction·
12353 * then the Simple Type Definition component from which it is ·derived·,
12354 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
12355 */
12356 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012357 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012358 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012359 NULL, type, NULL,
12360 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012361 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12362 }
12363 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
12364 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
12365 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012366 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012367 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012368 NULL, type, NULL,
12369 "The base type %s is not a simple type",
12370 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12371 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012372 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12373 }
12374 if ((baseType != anySimpleType) &&
12375 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012376 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012377 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012378 NULL, type, NULL,
12379 "A type, derived by list or union, must have"
12380 "the simple ur-type definition as base type, not %s",
12381 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12382 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012383 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12384 }
12385 /*
12386 * Variety: One of {atomic, list, union}.
12387 */
12388 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12389 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
12390 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012391 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012392 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012393 NULL, type, NULL,
12394 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012395 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12396 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012397 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012398
12399 /*
12400 * 2 All simple type definitions must be derived ultimately from the ·simple
12401 * ur-type definition (so· circular definitions are disallowed). That is, it
12402 * must be possible to reach a built-in primitive datatype or the ·simple
12403 * ur-type definition· by repeatedly following the {base type definition}.
12404 */
12405 baseType = type->baseType;
12406 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
12407 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12408 xmlSchemaTypeFixup(baseType, ctxt, NULL);
12409 if (baseType == anySimpleType)
12410 break;
12411 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012412 xmlSchemaPCustomErr(ctxt,
12413 XML_SCHEMAP_ST_PROPS_CORRECT_2,
12414 NULL, type, NULL,
12415 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012416 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
12417 }
12418 baseType = baseType->baseType;
12419 }
12420 /*
12421 * 3 The {final} of the {base type definition} must not contain restriction.
12422 */
12423 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
12424 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012425 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012426 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012427 NULL, type, NULL,
12428 "The 'final' of its base type %s must not contain "
12429 "'restriction'",
12430 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12431 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012432 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
12433 }
12434 return (0);
12435}
12436
12437/**
12438 * xmlSchemaCheckDerivationValidSimpleRestriction:
12439 * @ctxt: the schema parser context
12440 * @type: the simple type definition
12441 *
12442 * Checks if the given @type (simpleType) is derived
12443 * validly by restriction.
12444 *
12445 * Returns -1 on internal errors, 0 if the type is validly derived,
12446 * a positive error code otherwise.
12447 */
12448static int
12449xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012450 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012451{
Daniel Veillardc0826a72004-08-10 14:17:33 +000012452 xmlChar *str = NULL;
12453
12454 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012455
12456 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
12457 xmlSchemaPErr(ctxt, type->node,
12458 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012459 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
12460 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012461 type->name, NULL);
12462 return (-1);
12463 }
12464
12465 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
12466 xmlSchemaTypePtr primitive;
12467 /*
12468 * 1.1 The {base type definition} must be an atomic simple
12469 * type definition or a built-in primitive datatype.
12470 */
12471 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012472 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012473 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012474 NULL, type, NULL,
12475 "The base type %s is not an atomic simple type",
12476 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12477 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012478 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
12479 }
12480 /* 1.2 The {final} of the {base type definition} must not contain
12481 * restriction.
12482 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012483 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012484 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12485 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012486 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012487 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012488 NULL, type, NULL,
12489 "The final of its base type %s must not contain 'restriction'",
12490 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12491 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012492 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
12493 }
12494
12495 /*
12496 * 1.3.1 DF must be an allowed constraining facet for the {primitive
12497 * type definition}, as specified in the appropriate subsection of 3.2
12498 * Primitive datatypes.
12499 */
12500 if (type->facets != NULL) {
12501 xmlSchemaFacetPtr facet;
12502 int ok = 1;
12503
12504 primitive = xmlSchemaGetPrimitiveType(type);
12505 if (primitive == NULL) {
12506 xmlSchemaPErr(ctxt, type->node,
12507 XML_ERR_INTERNAL_ERROR,
12508 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012509 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012510 type->name, NULL);
12511 return (-1);
12512 }
12513 facet = type->facets;
12514 do {
12515 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012516 ok = 0;
12517 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012518 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012519 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012520 }
12521 facet = facet->next;
12522 } while (facet != NULL);
12523 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000012524 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012525 }
12526 /*
12527 * TODO: 1.3.2 (facet derivation)
12528 */
12529 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12530 xmlSchemaTypePtr itemType = NULL;
12531
12532 itemType = xmlSchemaGetListSimpleTypeItemType(type);
12533 if (itemType == NULL) {
12534 xmlSchemaPErr(ctxt, type->node,
12535 XML_ERR_INTERNAL_ERROR,
12536 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012537 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012538 type->name, NULL);
12539 return (-1);
12540 }
12541 /*
12542 * 2.1 The {item type definition} must have a {variety} of atomic or
12543 * union (in which case all the {member type definitions}
12544 * must be atomic).
12545 */
12546 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12547 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012548 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012549 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012550 NULL, type, NULL,
12551 "The item type %s must have a variety of atomic or union",
12552 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
12553 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012554 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
12555 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12556 xmlSchemaTypeLinkPtr member;
12557
12558 member = itemType->memberTypes;
12559 while (member != NULL) {
12560 if ((member->type->flags &
12561 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012562 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012563 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012564 NULL, type, NULL,
12565 "The item type is a union type, but the "
12566 "member type %s of this item type is not atomic",
12567 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12568 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012569 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
12570 }
12571 member = member->next;
12572 }
12573 }
12574
12575 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12576 xmlSchemaFacetPtr facet;
12577 /*
12578 * This is the case if we have: <simpleType><list ..
12579 */
12580 /*
12581 * 2.3.1
12582 * 2.3.1.1 The {final} of the {item type definition} must not
12583 * contain list.
12584 */
12585 if (xmlSchemaTypeFinalContains(ctxt->schema,
12586 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012587 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012588 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012589 NULL, type, NULL,
12590 "The final of its item type %s must not contain 'list'",
12591 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
12592 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012593 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
12594 }
12595 /*
12596 * 2.3.1.2 The {facets} must only contain the whiteSpace
12597 * facet component.
12598 */
12599 if (type->facets != NULL) {
12600 facet = type->facets;
12601 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012602 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
12603 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012604 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012605 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012606 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
12607 }
12608 facet = facet->next;
12609 } while (facet != NULL);
12610 }
12611 /*
12612 * TODO: Datatypes states:
12613 * A ·list· datatype can be ·derived· from an ·atomic· datatype
12614 * whose ·lexical space· allows space (such as string or anyURI)or
12615 * a ·union· datatype any of whose {member type definitions}'s
12616 * ·lexical space· allows space.
12617 */
12618 } else {
12619 /*
12620 * This is the case if we have: <simpleType><restriction ...
12621 */
12622 /*
12623 * 2.3.2
12624 * 2.3.2.1 The {base type definition} must have a {variety} of list.
12625 */
12626 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012627 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012628 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012629 NULL, type, NULL,
12630 "The base type %s must be a list type",
12631 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12632 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012633 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
12634 }
12635 /*
12636 * 2.3.2.2 The {final} of the {base type definition} must not
12637 * contain restriction.
12638 */
12639 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12640 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012641 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012642 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012643 NULL, type, NULL,
12644 "The final of the base type %s must not contain 'restriction'",
12645 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12646 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012647 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
12648 }
12649 /*
12650 * 2.3.2.3 The {item type definition} must be validly derived
12651 * from the {base type definition}'s {item type definition} given
12652 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
12653 */
12654 {
12655 xmlSchemaTypePtr baseItemType;
12656
12657 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
12658 if (baseItemType == NULL) {
12659 xmlSchemaPErr(ctxt, type->node,
12660 XML_ERR_INTERNAL_ERROR,
12661 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012662 "List simple type '%s': Failed to "
12663 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012664 type->name, type->baseType->name);
12665 return (-1);
12666 }
12667 if ((itemType != baseItemType) &&
12668 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
12669 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012670 xmlChar *strBIT = NULL, *strBT = NULL;
12671 xmlSchemaPCustomErrExt(ctxt,
12672 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
12673 NULL, type, NULL,
12674 "The item type %s is not validly derived from the "
12675 "item type %s of the base type %s",
12676 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
12677 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
12678 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12679
12680 FREE_AND_NULL(str)
12681 FREE_AND_NULL(strBIT)
12682 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012683 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
12684 }
12685 }
12686
12687 if (type->facets != NULL) {
12688 xmlSchemaFacetPtr facet;
12689 int ok = 1;
12690 /*
12691 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
12692 * and enumeration facet components are allowed among the {facets}.
12693 */
12694 facet = type->facets;
12695 do {
12696 switch (facet->type) {
12697 case XML_SCHEMA_FACET_LENGTH:
12698 case XML_SCHEMA_FACET_MINLENGTH:
12699 case XML_SCHEMA_FACET_MAXLENGTH:
12700 case XML_SCHEMA_FACET_WHITESPACE:
12701 /*
12702 * TODO: 2.5.1.2 List datatypes
12703 * The value of ·whiteSpace· is fixed to the value collapse.
12704 */
12705 case XML_SCHEMA_FACET_PATTERN:
12706 case XML_SCHEMA_FACET_ENUMERATION:
12707 break;
12708 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012709 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012710 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012711 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012712 /*
12713 * We could return, but it's nicer to report all
12714 * invalid facets.
12715 */
12716 ok = 0;
12717 }
12718 }
12719 facet = facet->next;
12720 } while (facet != NULL);
12721 if (ok == 0)
12722 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
12723 /*
12724 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
12725 * is a facet of the same kind in the {facets} of the {base type
12726 * definition} (call this BF),then the DF's {value} must be a valid
12727 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
12728 */
12729 }
12730
12731
12732 }
12733 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12734 /*
12735 * 3.1 The {member type definitions} must all have {variety} of
12736 * atomic or list.
12737 */
12738 xmlSchemaTypeLinkPtr member;
12739
12740 member = type->memberTypes;
12741 while (member != NULL) {
12742 if (((member->type->flags &
12743 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12744 ((member->type->flags &
12745 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012746 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012747 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012748 NULL, type, NULL,
12749 "The member type %s is neither an atomic, nor a list type",
12750 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12751 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012752 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
12753 }
12754 member = member->next;
12755 }
12756 /*
12757 * 3.3.1 If the {base type definition} is the ·simple ur-type
12758 * definition·
12759 */
12760 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12761 /*
12762 * 3.3.1.1 All of the {member type definitions} must have a
12763 * {final} which does not contain union.
12764 */
12765 member = type->memberTypes;
12766 while (member != NULL) {
12767 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
12768 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012769 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012770 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012771 NULL, type, NULL,
12772 "The final of member type %s contains 'union'",
12773 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12774 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012775 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
12776 }
12777 member = member->next;
12778 }
12779 /*
12780 * 3.3.1.2 The {facets} must be empty.
12781 */
12782 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012783 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012784 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012785 NULL, type, NULL,
12786 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012787 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
12788 }
12789 } else {
12790 /*
12791 * 3.3.2.1 The {base type definition} must have a {variety} of union.
12792 */
12793 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012794 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012795 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012796 NULL, type, NULL,
12797 "The base type %s is not a union type",
12798 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12799 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012800 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
12801 }
12802 /*
12803 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
12804 */
12805 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12806 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012807 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012808 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012809 NULL, type, NULL,
12810 "The final of its base type %s must not contain 'restriction'",
12811 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12812 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012813 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
12814 }
12815 /*
12816 * 3.3.2.3 The {member type definitions}, in order, must be validly
12817 * derived from the corresponding type definitions in the {base
12818 * type definition}'s {member type definitions} given the empty set,
12819 * as defined in Type Derivation OK (Simple) (§3.14.6).
12820 */
12821 {
12822 xmlSchemaTypeLinkPtr baseMember;
12823
12824 /*
12825 * OPTIMIZE: if the type is restricting, it has no local defined
12826 * member types and inherits the member types of the base type;
12827 * thus a check for equality can be skipped.
12828 */
12829 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012830 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000012831 * union simple type can have other member types as the member
12832 * types of it's base type. This check seems not necessary with
12833 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012834 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012835 */
12836 if (type->memberTypes != NULL) {
12837 member = type->memberTypes;
12838 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
12839 if ((member == NULL) && (baseMember != NULL)) {
12840 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012841 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012842 "Internal error: "
12843 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012844 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012845 "of member types in the base type\n",
12846 type->name, NULL);
12847 }
12848 while (member != NULL) {
12849 if (baseMember == NULL) {
12850 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012851 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012852 "Internal error: "
12853 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012854 "(3.3.2.3), union simple type '%s', unequal number "
12855 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012856 type->name, NULL);
12857 }
12858 if ((member->type != baseMember->type) &&
12859 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
12860 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012861 xmlChar *strBMT = NULL, *strBT = NULL;
12862
12863 xmlSchemaPCustomErrExt(ctxt,
12864 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
12865 NULL, type, NULL,
12866 "The member type %s is not validly derived from its "
12867 "corresponding member type %s of the base type %s",
12868 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
12869 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
12870 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12871 FREE_AND_NULL(str)
12872 FREE_AND_NULL(strBMT)
12873 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012874 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
12875 }
12876 member = member->next;
12877 baseMember = baseMember->next;
12878 }
12879 }
12880 }
12881 /*
12882 * 3.3.2.4 Only pattern and enumeration facet components are
12883 * allowed among the {facets}.
12884 */
12885 if (type->facets != NULL) {
12886 xmlSchemaFacetPtr facet;
12887 int ok = 1;
12888
12889 facet = type->facets;
12890 do {
12891 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
12892 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012893 xmlSchemaPIllegalFacetListUnionErr(ctxt,
12894 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
12895 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012896 ok = 0;
12897 }
12898 facet = facet->next;
12899 } while (facet != NULL);
12900 if (ok == 0)
12901 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
12902
12903 }
12904 /*
12905 * TODO: 3.3.2.5 (facet derivation)
12906 */
12907 }
12908 }
12909
12910 return (0);
12911}
12912
12913/**
12914 * xmlSchemaCheckSRCSimpleType:
12915 * @ctxt: the schema parser context
12916 * @type: the simple type definition
12917 *
12918 * Checks crc-simple-type constraints.
12919 *
12920 * Returns 0 if the constraints are satisfied,
12921 * if not a positive error code and -1 on internal
12922 * errors.
12923 */
12924static int
12925xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
12926 xmlSchemaTypePtr type)
12927{
12928 /*
12929 * NOTE: src-simple-type 2-4 are redundant, since the checks
12930 * were are done for the corresponding <restriction>, <list> and <union>
12931 * elements, but W3C wants a <simpleType> error as well, so it gets one.
12932 * Maby this can be skipped in the future, if we get sure it's not needed.
12933 */
12934 if (type->subtypes == NULL) {
12935 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012936 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012937 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012938 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012939 type->name, NULL);
12940 return (-1);
12941 }
12942 /*
12943 * src-simple-type.1 The corresponding simple type definition, if any,
12944 * must satisfy the conditions set out in Constraints on Simple Type
12945 * Definition Schema Components (§3.14.6).
12946 */
12947 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
12948 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
12949 /*
12950 * TODO: Removed this, since it got annoying to get an
12951 * extra error report, if anything failed until now.
12952 * Enable this if needed.
12953 */
12954 /*
12955 xmlSchemaPErr(ctxt, type->node,
12956 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012957 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012958 "on simple type definitions.\n",
12959 type->name, NULL);
12960 */
12961 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
12962 }
12963
12964 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
12965 /*
12966 * src-simple-type.2 If the <restriction> alternative is chosen,
12967 * either it must have a base [attribute] or a <simpleType> among its
12968 * [children], but not both.
12969 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012970 /*
12971 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
12972 * NOTE: This was removed, since this will be already handled
12973 * in the parse function for <restriction>.
12974 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012975 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
12976 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
12977 * an itemType [attribute] or a <simpleType> among its [children],
12978 * but not both.
12979 * NOTE: baseType is set to the local simple type definiton,
12980 * if existent, at parse time. This is a hack and not nice.
12981 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012982 /*
12983 * TODO: Remove this, and add the check to the parse function of <list>.
12984 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012985 if (((type->subtypes->base == NULL) &&
12986 (type->baseType == NULL)) ||
12987 ((type->subtypes->base != NULL) &&
12988 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012989 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012990 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012991 NULL, type, NULL,
12992 "Either the attribute 'itemType' or the <simpleType> child "
12993 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012994 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
12995 }
12996
12997
12998 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
12999 xmlSchemaTypeLinkPtr member;
13000 xmlSchemaTypePtr ancestor, anySimpleType;
13001
13002 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13003
13004 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
13005 * the <union> alternative is chosen, there must not be any entries
13006 * in the memberTypes [attribute] at any depth which resolve to the
13007 * component corresponding to the <simpleType>.
13008 */
13009 member = type->memberTypes;
13010 while (member != NULL) {
13011 ancestor = member->type;
13012 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
13013 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
13014 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
13015 if (ancestor == anySimpleType)
13016 break;
13017 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013018 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013019 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013020 NULL, type, NULL,
13021 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013022 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
13023 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
13024 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013025 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000013026 * type as item type, which in turn has a list ST as member
13027 * type, we will assume this here as well, since this check
13028 * was not yet performed.
13029 */
13030
13031 }
13032 ancestor = ancestor->baseType;
13033 }
13034 member = member->next;
13035 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013036 }
13037
13038 return (0);
13039}
13040
William M. Brack2f2a6632004-08-20 23:09:47 +000013041#if 0 /* Not yet used code for CT schema validation */
13042static int
13043xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
13044 const xmlChar * value,
13045 xmlSchemaTypePtr type,
13046 int fireErrors)
13047{
13048 int ret;
13049 /*
13050 * 3.14.4 Simple Type Definition Validation Rules
13051 * Validation Rule: String Valid
13052 */
13053 /*
13054 * 1 It is schema-valid with respect to that definition as defined
13055 * by Datatype Valid in [XML Schemas: Datatypes].
13056 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013057 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
13058 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000013059 return (ret);
13060 /*
13061 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
13062 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
13063 * the string must be a ·declared entity name·.
13064 */
13065 /*
13066 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
13067 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
13068 * then every whitespace-delimited substring of the string must be a ·declared
13069 * entity name·.
13070 */
13071 /*
13072 * 2.3 otherwise no further condition applies.
13073 */
13074
13075 return (0);
13076}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013077#endif
13078
William M. Brack2f2a6632004-08-20 23:09:47 +000013079
13080static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013081xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
13082{
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000013083 if (vctxt->pctxt == NULL) {
13084 if (vctxt->schema != NULL)
13085 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
13086 else
13087 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013088 if (vctxt->pctxt == NULL) {
13089 xmlSchemaVErr(vctxt, NULL,
13090 XML_SCHEMAV_INTERNAL,
13091 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
13092 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000013093 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013094 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013095 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013096 /* TODO: Pass user data. */
13097 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
13098 }
13099 return (0);
13100}
13101
13102static int
13103xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
13104{
13105 if (ctxt->vctxt == NULL) {
13106 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
13107 if (ctxt->vctxt == NULL) {
13108 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013109 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013110 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
13111 "failed to create a temp. validation context.\n",
13112 NULL, NULL);
13113 return (-1);
13114 }
13115 /* TODO: Pass user data. */
13116 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
13117 }
13118 return (0);
13119}
13120
13121/**
13122 * xmlSchemaCheckCOSValidDefault:
13123 * @ctxt: the schema parser context
13124 * @type: the simple type definition
13125 * @value: the default value
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000013126 * @val: the precomputed value to be returned
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013127 * @node: an optional node (the holder of the value)
13128 *
13129 * Checks the "cos-valid-default" constraints.
13130 *
13131 * Returns 0 if the constraints are satisfied,
13132 * if not, a positive error code and -1 on internal
13133 * errors.
13134 */
13135static int
13136xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
13137 xmlSchemaValidCtxtPtr vctxt,
13138 xmlSchemaTypePtr type,
13139 const xmlChar *value,
13140 xmlNodePtr node)
13141{
13142 int ret = 0;
13143
13144 /*
13145 * cos-valid-default:
13146 * Schema Component Constraint: Element Default Valid (Immediate)
13147 * For a string to be a valid default with respect to a type
13148 * definition the appropriate case among the following must be true:
13149 */
13150 /*
13151 * NOTE: This has to work without a given node (the holder of the
13152 * value), since it should work on the component, i.e. an underlying
13153 * DOM must not be mandatory.
13154 */
13155 if ((pctxt == NULL) || (vctxt == NULL)) {
13156 xmlSchemaPErr(pctxt, node,
13157 XML_SCHEMAP_INTERNAL,
13158 "Internal error: xmlSchemaCheckCOSValidDefault, "
13159 "bad arguments: the parser and/or validation context is "
13160 "missing.\n",
13161 NULL, NULL);
13162 return (-1);
13163 }
13164 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013165 /*
13166 * Complex type.
13167 *
13168 * 2.1 its {content type} must be a simple type definition or mixed.
13169 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013170 /*
13171 * TODO: Adjust this when the content type will be computed
13172 * correctly.
13173 */
13174 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
13175 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
13176 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
13177 xmlSchemaPSimpleTypeErr(pctxt,
13178 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
13179 NULL, NULL, node,
13180 type, NULL, NULL,
13181 "If the type of a constraint value is complex, its content "
13182 "type must be mixed or a simple type",
13183 NULL, NULL);
13184 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
13185 }
13186 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013187 /*
13188 * 2.2.2 If the {content type} is mixed, then the {content type}'s
13189 * particle must be ·emptiable· as defined by Particle Emptiable
13190 * (§3.9.6).
13191 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013192
William M. Brack2f2a6632004-08-20 23:09:47 +000013193 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013194 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000013195 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013196 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000013197 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013198 }
13199 /*
13200 * 1 If the type definition is a simple type definition, then the string
13201 * must be ·valid· with respect to that definition as defined by String
13202 * Valid (§3.14.4).
13203 *
13204 * AND
13205 *
13206 * 2.2.1 If the {content type} is a simple type definition, then the
13207 * string must be ·valid· with respect to that simple type definition
13208 * as defined by String Valid (§3.14.4).
13209 */
13210 vctxt->node = node;
13211 vctxt->cur = NULL;
13212 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
13213 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
13214 if (ret < 0) {
13215 xmlSchemaPErr(pctxt, node,
13216 /* NOTNICE: error code: This function will be used during
13217 * schema construction and xsi:type validation.
13218 */
13219 XML_SCHEMAP_INTERNAL,
13220 "Internal error: xmlSchemaCheckCOSValidDefault, "
13221 "while validating a value constaint value.\n",
13222 NULL, NULL);
13223
13224 }
13225 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000013226}
13227
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013228#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000013229/**
13230 * xmlSchemaGetSTContentOfCT:
13231 * @ctxt: the schema parser context
13232 * @type: the complex type definition
13233 *
13234 *
13235 * Returns the corresponding simple type for the content of
13236 * the complex type.
13237 */
13238static xmlSchemaTypePtr
13239xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
13240 xmlSchemaTypePtr type)
13241{
13242 xmlSchemaTypePtr orig = type, anyType;
13243
13244 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13245 while ((type != NULL) && (type != anyType) &&
13246 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
13247 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
13248 return(type);
13249 type = type->baseType;
13250 }
13251 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013252 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000013253 NULL, orig, NULL,
13254 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
13255 "no simple type for the content of complex type '%s' could be "
13256 "computed", orig->name);
13257 return (NULL);
13258}
13259
13260
William M. Brack2f2a6632004-08-20 23:09:47 +000013261
William M. Brack2f2a6632004-08-20 23:09:47 +000013262
13263/**
13264 * xmlSchemaCheckCOSCTExtends:
13265 * @ctxt: the schema parser context
13266 * @type: the complex type definition
13267 *
13268 * Schema Component Constraint: Derivation Valid (Extension)
13269 *
13270 * Returns 0 if the constraints are satisfied, a positive
13271 * error code if not and -1 if an internal error occured.
13272 */
13273static int
13274xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
13275 xmlSchemaTypePtr type)
13276{
13277 xmlSchemaTypePtr base;
13278 /*
13279 * 1 If the {base type definition} is a complex type definition,
13280 * then all of the following must be true:
13281 */
13282 base = type->baseType;
13283 if (base == NULL) {
13284 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013285 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000013286 NULL, type, NULL,
13287 "Internal error: xmlSchemaCheckCOSCTExtends, "
13288 "the complex type '%s' has no base type", type->name);
13289 return (-1);
13290 }
13291 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
13292 /*
13293 * 1.1 The {final} of the {base type definition} must not
13294 * contain extension.
13295 */
13296 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
13297 xmlSchemaPCustomErr(ctxt,
13298 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
13299 NULL, type, NULL,
13300 "The 'final' of the base type definition "
13301 "contains extension", NULL);
13302 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
13303 }
13304 /*
13305 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
13306 * of the complex type definition itself, that is, for every attribute
13307 * use in the {attribute uses} of the {base type definition}, there
13308 * must be an attribute use in the {attribute uses} of the complex
13309 * type definition itself whose {attribute declaration} has the same
13310 * {name}, {target namespace} and {type definition} as its attribute
13311 * declaration
13312 *
13313 * NOTE: This will be already satisfied by the way the attribute uses
13314 * are extended in xmlSchemaBuildAttributeValidation; thus this check
13315 * is not needed.
13316 */
13317
13318 /*
13319 * 1.3 If it has an {attribute wildcard}, the complex type definition
13320 * must also have one, and the base type definition's {attribute
13321 * wildcard}'s {namespace constraint} must be a subset of the complex
13322 * type definition's {attribute wildcard}'s {namespace constraint},
13323 * as defined by Wildcard Subset (§3.10.6).
13324 *
13325 * This is already checked in xmlSchemaBuildAttributeValidation; thus
13326 * this check is not needed.
13327 */
13328
13329 /*
13330 * 1.4 One of the following must be true:
13331 *
13332 * 1.4.1 The {content type} of the {base type definition} and the
13333 * {content type} of the complex type definition itself must be the same
13334 * simple type definition
13335 */
13336
13337
13338
13339 } else {
13340 /*
13341 * 2 If the {base type definition} is a simple type definition,
13342 * then all of the following must be true:
13343 */
13344 /*
13345 * 2.1 The {content type} must be the same simple type definition.
13346 */
13347 /*
13348 * 2.2 The {final} of the {base type definition} must not contain
13349 * extension
13350 */
13351 }
13352
13353}
13354
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013355static int
13356xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
13357 xmlSchemaTypePtr type)
13358{
13359 xmlSchemaTypePtr base, content;
13360 int OK = 0;
13361
13362 /*
13363 * TODO: Adjust the error codes here, as I used
13364 * XML_SCHEMAP_SRC_CT_1 only yet.
13365 */
13366 /*
13367 * Schema Representation Constraint:
13368 * Complex Type Definition Representation OK
13369 */
13370 base = type->baseType;
13371 if (base == NULL) {
13372 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
13373 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
13374 type->name);
13375 return (-1);
13376 }
13377
13378 if (type->subtypes != NULL) {
13379 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
13380 if IS_COMPLEX_TYPE(base) {
13381 /*
13382 * 1 If the <complexContent> alternative is chosen, the type definition
13383 * ·resolved· to by the ·actual value· of the base [attribute]
13384 * must be a complex type definition;
13385 */
13386 xmlSchemaPCustomErr(ctxt,
13387 XML_SCHEMAP_SRC_CT_1,
13388 NULL, type, NULL,
13389 "The base type is not a complex type", NULL);
13390 return (XML_SCHEMAP_SRC_CT_1);
13391 }
13392 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
13393
13394 if IS_SIMPLE_TYPE(base) {
13395 if (type->flags &
13396 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
13397 /*
13398 * 2.1.3 only if the <extension> alternative is also
13399 * chosen, a simple type definition.
13400 */
13401 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
13402 xmlSchemaPCustomErr(ctxt,
13403 XML_SCHEMAP_SRC_CT_1,
13404 NULL, type, NULL,
13405 "A complex type (simple content) cannot restrict "
13406 "an other simple type",
13407 NULL);
13408 return (XML_SCHEMAP_SRC_CT_1);
13409 }
13410 OK = 1;
13411
13412 } else { /* if IS_SIMPLE_TYPE(base) */
Daniel Veillardbc69d4f2005-03-17 10:04:46 +000013413 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013414 /*
13415 * 2.1.2 only if the <restriction> alternative is also
13416 * chosen, a complex type definition whose {content type}
13417 * is mixed and a particle emptyable.
13418 */
13419 /*
13420 * FIXME TODO: Check for *empiable particle* is missing.
13421 */
13422 if ((type->flags &
13423 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
13424 xmlSchemaPCustomErr(ctxt,
13425 XML_SCHEMAP_SRC_CT_1,
13426 NULL, type, NULL,
13427 "A complex type (simple content) cannot "
13428 "extend an other complex type which has a "
13429 "content type of: 'mixed' and emptiable particle",
13430 NULL);
13431 return (XML_SCHEMAP_SRC_CT_1);
13432 }
13433 /*
13434 * NOTE: This will be fired as well, if the base type
13435 * is *'anyType'*.
13436 * NOTE: type->subtypes->subtypes will be the
13437 * <restriction> item.
13438 */
13439 if (type->subtypes->subtypes == NULL) {
13440 /* Yes, this is paranoid programming. */
13441 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13442 NULL, type, NULL,
13443 "Internal error: xmlSchemaCheckSRCCT, "
13444 "'%s', <simpleContent> has no <restriction>",
13445 type->name);
13446 return (-1);
13447 }
13448 /*
13449 * 2.2 If clause 2.1.2 above is satisfied, then there
13450 * must be a <simpleType> among the [children] of
13451 * <restriction>.
13452 */
13453 if (type->subtypes->subtypes->type !=
13454 XML_SCHEMA_TYPE_SIMPLE) {
13455 /* TODO: Change error code to ..._SRC_CT_2_2. */
13456 xmlSchemaPCustomErr(ctxt,
13457 XML_SCHEMAP_SRC_CT_1,
13458 NULL, type, NULL,
13459 "A <simpleType> is expected among the children "
13460 "of <restriction>", NULL);
13461 return (XML_SCHEMAP_SRC_CT_1);
13462 }
13463 OK = 1;
Daniel Veillardbc69d4f2005-03-17 10:04:46 +000013464 } else { /* if (base->contentType == XML_SCHEMA_CONTENT_MIXED)*/
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013465 /*
13466 * 2.1.1 a complex type definition whose {content type} is a
13467 * simple type definition;
13468 */
13469 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
13470 xmlSchemaPCustomErr(ctxt,
13471 XML_SCHEMAP_SRC_CT_1,
13472 NULL, type, NULL,
13473 "A complex type (simple content) cannot "
13474 "be derived from the complex type '%s'",
13475 base->name);
13476 return (XML_SCHEMAP_SRC_CT_1);
13477 }
13478 content = base->contentTypeDef;
13479 if (content == NULL) {
13480 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13481 NULL, type, NULL,
13482 "Internal error: xmlSchemaCheckSRCCT, "
13483 "'%s', base type has no content type",
13484 type->name);
13485 return (-1);
13486 }
13487 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
13488 xmlSchemaPCustomErr(ctxt,
13489 XML_SCHEMAP_SRC_CT_1,
13490 NULL, type, NULL,
13491 "A complex type (simple content) cannot "
13492 "be derived from the complex type '%s'",
13493 base->name);
13494 return (XML_SCHEMAP_SRC_CT_1);
13495 }
13496 }
13497 }
13498 }
13499 }
13500 /*
13501 * TODO: 3 The corresponding complex type definition component must
13502 * satisfy the conditions set out in Constraints on Complex Type
13503 * Definition Schema Components (§3.4.6);
13504 *
13505 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
13506 * above for {attribute wildcard} is satisfied, the intensional
13507 * intersection must be expressible, as defined in Attribute Wildcard
13508 * Intersection (§3.10.6).
13509 */
13510
13511}
William M. Brack2f2a6632004-08-20 23:09:47 +000013512#endif
13513
Daniel Veillard01fa6152004-06-29 17:04:39 +000013514/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013515 * xmlSchemaGroupDefFixup:
13516 * @typeDecl: the schema model group definition
13517 * @ctxt: the schema parser context
13518 *
13519 * Fixes model group definitions.
13520 */
13521static void
13522xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
13523 xmlSchemaParserCtxtPtr ctxt,
13524 const xmlChar * name ATTRIBUTE_UNUSED)
13525{
13526 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
13527 if ((group->ref != NULL) && (group->subtypes == NULL)) {
13528 xmlSchemaTypePtr groupDef;
13529 /*
13530 * Resolve the reference.
13531 */
13532 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
13533 group->refNs);
13534 if (groupDef == NULL) {
13535 xmlSchemaPResCompAttrErr(ctxt,
13536 XML_SCHEMAP_SRC_RESOLVE,
13537 NULL, group, NULL,
13538 "ref", group->ref, group->refNs,
13539 XML_SCHEMA_TYPE_GROUP, NULL);
13540 return;
13541 }
13542 group->subtypes = groupDef;
13543 }
13544}
13545
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013546#if 0 /* Enable when the content type will be computed. */
13547static int
13548xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
13549 xmlSchemaTypePtr type)
13550{
13551 xmlSchemaTypePtr base, res = NULL;
13552
13553 base = type->baseType;
13554 if (base == NULL) {
13555 xmlSchemaPCustomErr(ctxt,
13556 XML_SCHEMAP_INTERNAL,
13557 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013558 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013559 "the complex type '%s' has no base type", type->name);
13560 return (-1);
13561 }
13562 if (IS_ANYTYPE(base) || (type->subtypes->type ==
13563 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
13564 xmlSchemaTypePtr start;
13565 /*
13566 * Effective 'mixed'.
13567 */
13568 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
13569 type->contentType = XML_SCHEMA_CONTENT_MIXED;
13570 /*
13571 * Effective content.
13572 */
13573 if (IS_ANYTYPE(base))
13574 start = type;
13575 else
13576 start = type->subtypes;
13577
13578 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
13579 xmlSchemaTypePtr baseContentItem;
13580
13581 /*
13582 * Complex type with simple content.
13583 */
13584 if IS_COMPLEX_TYPE(base) {
13585 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
13586 /*
13587 * Summary: a complex type (simple content) can *restrict*
13588 * a complex type with the following content type:
13589 * 1. 'mixed' and an emptiable particle
13590 * 2. simple type
13591 */
13592 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
13593 /*
13594 * 2 if the {content type} of the base type is mixed and a
13595 * particle which is ·emptiable·,
13596 * [...]
13597 * then starting from the simple type definition
13598 * corresponding to the <simpleType> among the [children]
13599 * of <restriction> (**which must be present**)
13600 *
13601 * FIXME TODO: Handle "emptiable particle".
13602 */
13603 res = type->subtypes->subtypes;
13604 if (res == NULL) {
13605 xmlSchemaPCustomErr(ctxt,
13606 XML_SCHEMAP_INTERNAL,
13607 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013608 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013609 "CT '%s' (restricting): <simpleContent> has no "
13610 "<restriction>",
13611 type->name);
13612 return (-1);
13613 }
13614
13615 res->subtypes;
13616 if (res == NULL) {
13617 xmlSchemaPCustomErr(ctxt,
13618 XML_SCHEMAP_INTERNAL,
13619 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013620 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013621 "CT '%s' (restricting): <restriction> has no "
13622 "mandatory <simpleType>",
13623 type->name);
13624 return (-1);
13625 }
13626 } else {
13627 baseContentItem = base->contentTypeDef;
13628 if (baseContentItem == NULL) {
13629 xmlSchemaPCustomErr(ctxt,
13630 XML_SCHEMAP_INTERNAL,
13631 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013632 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013633 "CT '%s' (restricting), the base type has no "
13634 "content type", type->name);
13635 return (-1);
13636 }
13637 if IS_SIMPLE_TYPE(baseContentItem) {
13638 /*
13639 * 1 If the base type is a complex type whose own
13640 * {content type} is a simple type and the <restriction>
13641 * alternative is chosen
13642 */
13643 /* type->subtypes->subtypes will be the restriction item.*/
13644 res = type->subtypes->subtypes;
13645 if (res == NULL) {
13646 xmlSchemaPCustomErr(ctxt,
13647 XML_SCHEMAP_INTERNAL,
13648 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013649 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013650 "CT '%s' (restricting): <simpleType> has no "
13651 "<restriction>", type->name);
13652 return (-1);
13653 }
13654 /*
13655 * 1.1 the simple type definition corresponding to the
13656 * <simpleType> among the [children] of <restriction>if
13657 * there is one;
13658 */
13659 res = res->subtypes;
13660 if (res == NULL) {
13661 /*
13662 * 1.2 otherwise the {content type}
13663 * of the base type .
13664 */
13665 res = baseContentItem;
13666 }
13667 }
13668 }
13669 /*
13670 * SPECIAL TODO: If *restricting* the spec wants us to
13671 * create an *additional* simple type which restricts the
13672 * located simple type; we won't do this yet, and look how
13673 * far we get with it.
13674 */
13675 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
13676 /*
13677 * Summary: a complex type (simple content) can *extend*
13678 * only a complex base with a simple type as content.
13679 */
13680 /*
13681 * 3 If the type definition ·resolved· to by the ·actual
13682 * value· of the base [attribute] is a complex type
13683 * definition (whose own {content type} *must be* a simple
13684 * type definition, see below) and the *<extension>*
13685 * alternative is chosen, then the {content type} of that
13686 * complex type definition;
13687 */
13688 res = base->contentTypeDef;
13689 if (res == NULL) {
13690 xmlSchemaPCustomErr(ctxt,
13691 XML_SCHEMAP_INTERNAL,
13692 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013693 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013694 "CT '%s' (extending), the base type has no content "
13695 "type", type->name);
13696 return (-1);
13697 }
13698 if (! IS_SIMPLE_TYPE(res)) {
13699 xmlSchemaPCustomErr(ctxt,
13700 XML_SCHEMAP_INTERNAL,
13701 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013702 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013703 "CT '%s' (extending), the content type of the "
13704 "base is not a simple type", type->name);
13705 return (-1);
13706 }
13707 }
13708 } else /* if IS_COMPLEX_TYPE(base) */
13709 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
13710 /*
13711 * 4 otherwise (the type definition ·resolved· to by the
13712 * ·actual value· of the base [attribute] is a simple type
13713 * definition and the <extension> alternative is chosen),
13714 * then that simple type definition.
13715 */
13716 res = base;
13717 }
13718 type->contentTypeDef = res;
13719 if (res == NULL) {
13720 xmlSchemaPCustomErr(ctxt,
13721 XML_SCHEMAP_INTERNAL,
13722 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013723 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013724 "'%s', the content type could not be determined",
13725 type->name);
13726 return (-1);
13727 }
13728
13729 }
13730
13731}
13732#endif
13733
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013734/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013735 * xmlSchemaTypeFixup:
13736 * @typeDecl: the schema type definition
13737 * @ctxt: the schema parser context
13738 *
13739 * Fixes the content model of the type.
13740 */
13741static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013742xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013743 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013744{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013745 xmlSchemaTypePtr ctxtType;
13746
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013747 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013748 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013749 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000013750 * Do not fixup built-in types.
13751 */
13752 if (item->type == XML_SCHEMA_TYPE_BASIC)
13753 return;
13754 /*
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013755 * Do not allow the following types to be typefixed, prior to
13756 * the corresponding simple/complex types.
13757 */
13758 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013759 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013760 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13761 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13762 case XML_SCHEMA_TYPE_UNION:
13763 case XML_SCHEMA_TYPE_RESTRICTION:
13764 case XML_SCHEMA_TYPE_EXTENSION:
13765 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013766 default:
13767 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013768 }
13769 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013770 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013771 name = item->name;
13772 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
13773 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013774 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013775 if (item->subtypes != NULL) {
13776 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013777 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013778 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013779 NULL);
13780 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013781 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013782 XML_SCHEMA_CONTENT_SIMPLE;
13783 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013784 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013785 break;
13786 }
13787 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013788 xmlSchemaTypePtr base = NULL;
13789
13790 ctxt->ctxtType->flags |=
13791 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013792 if (item->baseType != NULL)
13793 base = item->baseType;
13794 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013795 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013796 xmlSchemaGetType(ctxt->schema, item->base,
13797 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013798 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013799 xmlSchemaPResCompAttrErr(ctxt,
13800 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000013801 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013802 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
13803 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013804 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013805 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000013806 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013807 xmlSchemaTypeFixup(base, ctxt, NULL);
13808 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013809 }
13810 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013811 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
13812 /*
13813 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000013814 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013815 /*
13816 * Content type.
13817 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013818 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013819 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013820 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13821 else if ((item->subtypes->subtypes == NULL) &&
13822 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013823 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013824 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013825 XML_SCHEMA_TYPE_SEQUENCE)))
13826 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013827 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13828 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013829 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013830 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013831 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013832 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013833 else {
13834 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013835 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013836 XML_SCHEMA_CONTENT_ELEMENTS;
13837 }
13838 } else {
13839 /*
13840 * SimpleType restriction.
13841 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013842 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013843 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013844 break;
13845 }
13846 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013847 xmlSchemaTypePtr base = NULL;
13848 xmlSchemaContentType explicitContentType;
13849
13850 /*
13851 * An extension does exist on a complexType only.
13852 */
13853 ctxt->ctxtType->flags |=
13854 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013855 if (item->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013856 xmlSchemaPCustomErr(ctxt,
13857 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013858 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013859 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000013860 return;
13861 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013862 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013863 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013864 xmlSchemaGetType(ctxt->schema, item->base,
13865 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013866 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013867 xmlSchemaPResCompAttrErr(ctxt,
13868 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013869 NULL, item, item->node,
13870 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013871 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013872 } else if (base->contentType ==
13873 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013874 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013875 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013876 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013877 }
13878 /*
13879 * The type definition ·resolved· to by the ·actual
13880 * value· of the base [attribute]
13881 */
13882 ctxt->ctxtType->baseType = base;
13883 /*
13884 * TODO: This one is still needed for computation of
13885 * the content model by xmlSchemaBuildAContentModel.
13886 * Try to get rid of it.
13887 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013888 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013889 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013890 if ((item->subtypes != NULL) &&
13891 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
13892 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013893
13894 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013895 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013896 /* 1.1.1 */
13897 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013898 else if ((item->subtypes->subtypes == NULL) &&
13899 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013900 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013901 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013902 XML_SCHEMA_TYPE_SEQUENCE)))
13903 /* 1.1.2 */
13904 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013905 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013906 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013907 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013908 /* 1.1.3 */
13909 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
13910 if (base != NULL) {
13911 /* It will be reported later, if the base is missing. */
13912 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
13913 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013914 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013915 } else if (base->contentType ==
13916 XML_SCHEMA_CONTENT_EMPTY) {
13917 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013918 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013919 XML_SCHEMA_CONTENT_ELEMENTS;
13920 } else {
13921 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013922 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013923 XML_SCHEMA_CONTENT_ELEMENTS;
13924 }
13925 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013926 break;
13927 }
13928 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013929 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013930 ctxt->ctxtType = item;
13931 /*
13932 * Start with an empty content-type type.
13933 */
13934 if (item->subtypes == NULL)
13935 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13936
13937 if ((item->subtypes == NULL) ||
13938 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013939 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013940 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013941 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
13942 /*
13943 * This case is understood as shorthand for complex
13944 * content restricting the ur-type definition, and
13945 * the details of the mappings should be modified as
13946 * necessary.
13947 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013948 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13949 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013950 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013951 /*
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000013952 * NOTE that if restricting, the content type of the
13953 * base type is not inherited.
13954 * REMOVED: item->contentType = item->baseType->contentType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013955 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013956 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013957 /*
13958 * Fixup the sub components.
13959 */
13960 if ((item->subtypes != NULL) &&
13961 (item->subtypes->contentType ==
13962 XML_SCHEMA_CONTENT_UNKNOWN)) {
13963 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013964 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013965 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13966 item->contentType = XML_SCHEMA_CONTENT_MIXED;
13967 } else if (item->subtypes != NULL) {
13968 /*
13969 * Use the content-type type of the model groups
13970 * defined, if 'mixed' is not set. If 'mixed' is set
13971 * it will expand the content-type by allowing character
13972 * content to appear.
13973 */
13974 item->contentType =
13975 item->subtypes->contentType;
13976 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013977
13978 /*
13979 * Some optimization for validation:
13980 * If there are no facets beside the "whitespace" facet,
13981 * then a value needs not to checked against against a
13982 * facet, thus no computed value is needed.
13983 * TODO URGENT: This is just a workaround, we need to
13984 * introduce the correct usage of contentType to store the
13985 * facets in!
13986 */
Daniel Veillardd3210bc2005-01-28 17:56:39 +000013987 if ((item->baseType != NULL) &&
13988 (item->baseType->flags &
13989 XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013990 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13991 else {
13992 xmlSchemaFacetLinkPtr cur;
13993
13994 for (cur = item->facetSet; cur != NULL;
13995 cur = cur->next) {
13996 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13997 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13998 break;
13999 }
14000 }
14001 }
14002
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014003 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014004 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000014005 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014006 break;
14007 }
14008 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014009 if (item->subtypes == NULL) {
14010 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
14011 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
14012 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000014013 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014014 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014015 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
14016 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014017 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000014018 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014019 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014020 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014021 if (item->subtypes != NULL)
14022 item->contentType =
14023 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014024 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014025 /*
14026 * Removed due to implementation of the build of attribute uses.
14027 */
14028 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014029 if (item->attributes == NULL)
14030 item->attributes =
14031 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000014032 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014033 }
14034 break;
14035 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014036 case XML_SCHEMA_TYPE_SIMPLE:
14037 /*
14038 * Simple Type Definition Schema Component
14039 *
14040 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000014041 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014042 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
14043 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000014044 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014045 ctxt->ctxtType = item;
14046 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014047 }
14048 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014049 if ((item->baseType != NULL) &&
14050 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000014051 XML_SCHEMA_CONTENT_UNKNOWN)) {
14052 /* OPTIMIZE: Actually this one will never by hit, since
14053 * the base type is already type-fixed in <restriction>.
14054 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014055 ctxt->ctxtType = item;
14056 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014057 }
14058 /* Base type:
14059 * 2 If the <list> or <union> alternative is chosen,
14060 * then the ·simple ur-type definition·.
14061 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014062 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000014063 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014064 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14065 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
14066 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000014067 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014068 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14069 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
14070 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000014071 XML_SCHEMA_TYPE_RESTRICTION) {
14072 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
14073
14074 /*
14075 * Variety
14076 * If the <restriction> alternative is chosen, then the
14077 * {variety} of the {base type definition}.
14078 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014079 if (item->baseType != NULL) {
14080 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000014081 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014082 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
14083 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000014084 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014085 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
14086 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000014087 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014088 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014089 /*
14090 * Schema Component Constraint: Simple Type Restriction
14091 * (Facets)
14092 * NOTE: Satisfaction of 1 and 2 arise from the fixup
14093 * applied beforehand.
14094 *
14095 * 3 The {facets} of R are the union of S and the {facets}
14096 * of B, eliminating duplicates. To eliminate duplicates,
14097 * when a facet of the same kind occurs in both S and the
14098 * {facets} of B, the one in the {facets} of B is not
14099 * included, with the exception of enumeration and pattern
14100 * facets, for which multiple occurrences with distinct values
14101 * are allowed.
14102 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014103 if (item->baseType->facetSet != NULL) {
14104 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014105 if (last != NULL)
14106 while (last->next != NULL)
14107 last = last->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014108 cur = item->baseType->facetSet;
14109 for (; cur != NULL; cur = cur->next) {
14110 /*
14111 * Base patterns won't be add here:
14112 * they are ORed in a type and
14113 * ANDed in derived types. This will
14114 * happed at validation level by
14115 * walking the base axis of the type.
14116 */
14117 if (cur->facet->type ==
14118 XML_SCHEMA_FACET_PATTERN)
14119 continue;
14120 facet = NULL;
14121 if ((item->facetSet != NULL) &&
14122 /* REMOVED: a check for
14123 * XML_SCHEMA_FACET_PATTERN was already
14124 * performed above.
14125
14126 * (cur->facet->type !=
14127 * XML_SCHEMA_FACET_PATTERN) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000014128 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014129 (cur->facet->type !=
14130 XML_SCHEMA_FACET_ENUMERATION)) {
14131 facet = item->facetSet;
14132 do {
14133 if (cur->facet->type ==
14134 facet->facet->type)
14135 break;
14136 facet = facet->next;
14137 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014138 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014139 if (facet == NULL) {
14140 facet = (xmlSchemaFacetLinkPtr)
14141 xmlMalloc(sizeof(xmlSchemaFacetLink));
14142 if (facet == NULL) {
14143 xmlSchemaPErrMemory(ctxt,
14144 "fixing simpleType", NULL);
14145 return;
14146 }
14147 /*
14148 * The facets are not copied but referenced
14149 * via the facet link.
14150 */
14151 facet->facet = cur->facet;
14152 facet->next = NULL;
14153 if (last == NULL)
14154 item->facetSet = facet;
14155 else
14156 last->next = facet;
14157 last = facet;
14158 }
14159 }
14160 }
14161 /*
14162 * Some optimization for validation:
14163 * If there are no facets beside the "whitespace" facet,
14164 * then a value needs not to checked against against a
14165 * facet, thus no computed value is needed.
14166 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000014167 if (item->baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014168 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
14169 else {
14170 for (cur = item->facetSet; cur != NULL;
14171 cur = cur->next) {
14172 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
14173 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
14174 break;
14175 }
14176 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014177 }
14178 }
14179 }
14180 /*
14181 * Check constraints.
14182 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014183 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014184 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000014185 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014186 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014187 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014188 case XML_SCHEMA_TYPE_ALL:
14189 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014190 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014191 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014192 case XML_SCHEMA_TYPE_GROUP:
14193 /*
14194 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
14195 */
14196 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014197 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014198 xmlSchemaParseListRefFixup(item, ctxt);
14199 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014200 break;
14201 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014202 xmlSchemaParseUnionRefCheck(item, ctxt);
14203 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014204 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014205 case XML_SCHEMA_TYPE_BASIC:
14206 case XML_SCHEMA_TYPE_ANY:
14207 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014208 case XML_SCHEMA_TYPE_UR:
14209 case XML_SCHEMA_TYPE_ELEMENT:
14210 case XML_SCHEMA_TYPE_ATTRIBUTE:
14211 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000014212 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014213 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014214 case XML_SCHEMA_FACET_MININCLUSIVE:
14215 case XML_SCHEMA_FACET_MINEXCLUSIVE:
14216 case XML_SCHEMA_FACET_MAXINCLUSIVE:
14217 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
14218 case XML_SCHEMA_FACET_TOTALDIGITS:
14219 case XML_SCHEMA_FACET_FRACTIONDIGITS:
14220 case XML_SCHEMA_FACET_PATTERN:
14221 case XML_SCHEMA_FACET_ENUMERATION:
14222 case XML_SCHEMA_FACET_WHITESPACE:
14223 case XML_SCHEMA_FACET_LENGTH:
14224 case XML_SCHEMA_FACET_MAXLENGTH:
14225 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014226 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
14227 if (item->subtypes != NULL)
14228 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014229 break;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000014230 case XML_SCHEMA_TYPE_IDC_UNIQUE:
14231 case XML_SCHEMA_TYPE_IDC_KEY:
14232 case XML_SCHEMA_TYPE_IDC_KEYREF:
14233 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014234 }
14235 }
Daniel Veillard8651f532002-04-17 09:06:27 +000014236#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014237 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014238 xmlGenericError(xmlGenericErrorContext,
14239 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014240 item->node->doc->URL,
14241 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000014242 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014243 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000014244 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014245 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014246 case XML_SCHEMA_CONTENT_SIMPLE:
14247 xmlGenericError(xmlGenericErrorContext, "simple\n");
14248 break;
14249 case XML_SCHEMA_CONTENT_ELEMENTS:
14250 xmlGenericError(xmlGenericErrorContext, "elements\n");
14251 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000014252 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014253 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
14254 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000014255 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014256 xmlGenericError(xmlGenericErrorContext, "empty\n");
14257 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000014258 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014259 xmlGenericError(xmlGenericErrorContext, "mixed\n");
14260 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014261 /* Removed, since not used. */
14262 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000014263 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014264 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
14265 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014266 */
Daniel Veillard8651f532002-04-17 09:06:27 +000014267 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014268 xmlGenericError(xmlGenericErrorContext, "basic\n");
14269 break;
14270 default:
14271 xmlGenericError(xmlGenericErrorContext,
14272 "not registered !!!\n");
14273 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000014274 }
14275#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000014276}
14277
14278/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014279 * xmlSchemaCheckFacet:
14280 * @facet: the facet
14281 * @typeDecl: the schema type definition
14282 * @ctxt: the schema parser context or NULL
14283 * @name: name of the type
14284 *
14285 * Checks the default values types, especially for facets
14286 *
14287 * Returns 0 if okay or -1 in cae of error
14288 */
14289int
14290xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014291 xmlSchemaTypePtr typeDecl,
14292 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014293{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000014294 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014295 int ret = 0, reuseValCtxt = 0;
14296
Daniel Veillardce682bc2004-11-05 17:22:25 +000014297 if ((facet == NULL) || (typeDecl == NULL))
14298 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014299 /*
14300 * TODO: will the parser context be given if used from
14301 * the relaxNG module?
14302 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014303
14304 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014305 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000014306 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014307 }
14308 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014309 case XML_SCHEMA_FACET_MININCLUSIVE:
14310 case XML_SCHEMA_FACET_MINEXCLUSIVE:
14311 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014312 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
14313 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014314 /*
14315 * Okay we need to validate the value
14316 * at that point.
14317 */
14318 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014319 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014320
14321 /* 4.3.5.5 Constraints on enumeration Schema Components
14322 * Schema Component Constraint: enumeration valid restriction
14323 * It is an ·error· if any member of {value} is not in the
14324 * ·value space· of {base type definition}.
14325 *
14326 * minInclusive, maxInclusive, minExclusive, maxExclusive:
14327 * The value ·must· be in the
14328 * ·value space· of the ·base type·.
14329 */
14330 /*
14331 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014332 * on the facet. In this implementation of XML Schemata the
14333 * type holding a facet, won't be a built-in type.
14334 * Thus to ensure that other API
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014335 * calls (relaxng) do work, if the given type is a built-in
14336 * type, we will assume that the given built-in type *is
14337 * already* the base type.
14338 */
14339 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
14340 base = typeDecl->baseType;
14341 if (base == NULL) {
14342 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014343 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014344 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014345 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014346 typeDecl->name, NULL);
14347 return (-1);
14348 }
14349 } else
14350 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014351 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014352 * This avoids perseverative creation of the
14353 * validation context if a parser context is
14354 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014355 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014356 if (ctxt != NULL) {
14357 reuseValCtxt = 1;
14358 if (ctxt->vctxt == NULL) {
14359 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14360 return (-1);
14361 }
14362 vctxt = ctxt->vctxt;
14363 } else {
14364 vctxt = xmlSchemaNewValidCtxt(NULL);
14365 if (vctxt == NULL) {
14366 xmlSchemaPErr(ctxt, typeDecl->node,
14367 XML_SCHEMAP_INTERNAL,
14368 "Internal error: xmlSchemaCheckFacet, "
14369 "creating a new validation context.\n",
14370 NULL, NULL);
14371 return (-1);
14372 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014373 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014374
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014375 vctxt->node = facet->node;
14376 vctxt->cur = NULL;
14377 /*
14378 * NOTE: This call does not check the content nodes,
14379 * since they are not available:
14380 * facet->node is just the node holding the facet
14381 * definition, *not* the attribute holding the *value*
14382 * of the facet.
14383 */
14384 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014385 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014386 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014387 /* error code */
14388 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014389 xmlChar *str = NULL;
14390
14391 xmlSchemaPCustomErrExt(ctxt,
14392 XML_SCHEMAP_INVALID_FACET_VALUE,
14393 NULL, (xmlSchemaTypePtr) facet, facet->node,
14394 "The value '%s' of the facet does not validate "
14395 "against the base type '%s'",
14396 facet->value,
14397 xmlSchemaFormatQName(&str,
14398 base->targetNamespace, base->name), NULL);
14399 FREE_AND_NULL(str)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014400 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014401 /* xmlSchemaFacetTypeToString(facet->type), */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014402 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014403 } else if (ret < 0) {
14404 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014405 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014406 NULL, NULL, NULL,
14407 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014408 "failed to validate the value '%s' name of the "
14409 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014410 facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014411 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014412 base->name, NULL, NULL);
14413 ret = -1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014414 } else {
14415 if (vctxt->value != NULL) {
14416 facet->val = vctxt->value;
14417 vctxt->value = NULL;
14418 } else {
14419 xmlChar *str;
14420 /*
14421 * Ensure computed values even for type string.
14422 * TODO OPTIMIZE MEMORY: The value will be hold twice,
14423 * by the facet->value and by the computed value.
14424 */
14425 str = xmlStrdup(facet->value);
14426 if (xmlSchemaPostCreateVal(vctxt, typeDecl,
14427 BAD_CAST str, &(facet->val)) == -1) {
14428 FREE_AND_NULL(str)
14429 xmlSchemaPErr(ctxt, typeDecl->node,
14430 XML_SCHEMAP_INTERNAL,
14431 "Internal error: xmlSchemaCheckFacet, "
14432 "post-creating a computed value.\n",
14433 NULL, NULL);
14434 /* Note that we don't return a failure yet.*/
14435 }
14436 }
14437 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014438 if (reuseValCtxt == 0)
14439 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014440 break;
14441 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014442 case XML_SCHEMA_FACET_PATTERN:
14443 facet->regexp = xmlRegexpCompile(facet->value);
14444 if (facet->regexp == NULL) {
14445 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014446 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014447 "Type definition '%s': The value '%s' of the "
14448 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014449 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014450 ret = -1;
14451 }
14452 break;
14453 case XML_SCHEMA_FACET_TOTALDIGITS:
14454 case XML_SCHEMA_FACET_FRACTIONDIGITS:
14455 case XML_SCHEMA_FACET_LENGTH:
14456 case XML_SCHEMA_FACET_MAXLENGTH:
14457 case XML_SCHEMA_FACET_MINLENGTH:{
14458 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014459
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014460 tmp =
14461 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
14462 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000014463 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014464 if (tmp != 0) {
14465 /* error code */
14466 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014467 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014468 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014469 NULL, (xmlSchemaTypePtr) facet, facet->node,
14470 "The value '%s' of the facet is not a valid "
14471 "nonNegativeInteger", facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014472 }
14473 ret = -1;
14474 }
14475 break;
14476 }
14477 case XML_SCHEMA_FACET_WHITESPACE:{
14478 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
14479 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
14480 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
14481 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
14482 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
14483 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
14484 } else {
14485 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014486 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
14487 xmlSchemaPCustomErr(ctxt,
14488 XML_SCHEMAP_INVALID_FACET_VALUE,
14489 NULL, (xmlSchemaTypePtr) facet, facet->node,
14490 "The value '%s' of the facet is not a valid",
14491 facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014492 }
14493 ret = -1;
14494 }
14495 }
14496 default:
14497 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014498 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014499 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014500}
14501
14502/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014503 * xmlSchemaCheckDefaults:
14504 * @typeDecl: the schema type definition
14505 * @ctxt: the schema parser context
14506 *
14507 * Checks the default values types, especially for facets
14508 */
14509static void
14510xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014511 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000014512{
Daniel Veillard4255d502002-04-16 15:50:10 +000014513 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014514 name = typeDecl->name;
14515 /*
14516 * NOTE: It is intended to use the facets list, instead
14517 * of facetSet.
14518 */
14519 if (typeDecl->facets != NULL) {
14520 xmlSchemaFacetPtr facet = typeDecl->facets;
14521
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014522 /*
14523 * Temporarily assign the "schema" to the validation context
14524 * of the parser context. This is needed for NOTATION validation.
14525 */
14526 if (ctxt->vctxt == NULL) {
14527 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14528 return;
14529 }
14530 ctxt->vctxt->schema = ctxt->schema;
14531
Daniel Veillard01fa6152004-06-29 17:04:39 +000014532 while (facet != NULL) {
14533 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
14534 facet = facet->next;
14535 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014536
14537 ctxt->vctxt->schema = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014538 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014539}
14540
14541/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014542 * xmlSchemaGetCircModelGrDefRef:
14543 * @ctxtGr: the searched model group
14544 * @list: the list of model groups to be processed
14545 *
14546 * This one is intended to be used by
14547 * xmlSchemaCheckGroupDefCircular only.
14548 *
14549 * Returns the circular model group definition reference, otherwise NULL.
14550 */
14551static xmlSchemaTypePtr
14552xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
14553 xmlSchemaTypePtr gr)
14554{
14555 xmlSchemaTypePtr circ = NULL;
14556 int marked;
14557 /*
14558 * We will search for an model group reference which
14559 * references the context model group definition.
14560 */
14561 while (gr != NULL) {
14562 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
14563 (gr->type == XML_SCHEMA_TYPE_ALL) ||
14564 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
14565 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
14566 (gr->subtypes != NULL)) {
14567 marked = 0;
14568 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
14569 (gr->ref != NULL)) {
14570 if (gr->subtypes == ctxtGrDef)
14571 return (gr);
14572 else if (gr->subtypes->flags &
14573 XML_SCHEMAS_TYPE_MARKED) {
14574 gr = gr->next;
14575 continue;
14576 } else {
14577 /*
14578 * Mark to avoid infinite recursion on
14579 * circular references not yet examined.
14580 */
14581 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
14582 marked = 1;
14583 }
14584 if (gr->subtypes->subtypes != NULL)
14585 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
14586 gr->subtypes->subtypes);
14587 /*
14588 * Unmark the visited model group definition.
14589 */
14590 if (marked)
14591 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
14592 if (circ != NULL)
14593 return (circ);
14594 } else {
14595 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
14596 (xmlSchemaTypePtr) gr->subtypes);
14597 if (circ != NULL)
14598 return (circ);
14599 }
14600
14601 }
14602 gr = gr->next;
14603 }
14604 return (NULL);
14605}
14606
14607/**
14608 * xmlSchemaCheckGroupDefCircular:
14609 * attrGr: the model group definition
14610 * @ctxt: the parser context
14611 * @name: the name
14612 *
14613 * Checks for circular references to model group definitions.
14614 */
14615static void
14616xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
14617 xmlSchemaParserCtxtPtr ctxt,
14618 const xmlChar * name ATTRIBUTE_UNUSED)
14619{
14620 /*
14621 * Schema Component Constraint: Model Group Correct
14622 * 2 Circular groups are disallowed. That is, within the {particles}
14623 * of a group there must not be at any depth a particle whose {term}
14624 * is the group itself.
14625 */
14626 /*
14627 * NOTE: "gr->subtypes" holds the referenced group.
14628 */
14629 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
14630 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
14631 (modelGrDef->subtypes == NULL))
14632 return;
14633 else {
14634 xmlSchemaTypePtr circ;
14635
14636 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
14637 if (circ != NULL) {
14638 /*
14639 * TODO: Report the referenced attr group as QName.
14640 */
14641 xmlSchemaPCustomErr(ctxt,
14642 XML_SCHEMAP_MG_PROPS_CORRECT_2,
14643 NULL, NULL, circ->node,
14644 "Circular reference to the model group definition '%s' "
14645 "defined", modelGrDef->name);
14646 /*
14647 * NOTE: We will cut the reference to avoid further
14648 * confusion of the processor.
14649 * TODO: SPEC: Does the spec define how to process here?
14650 */
14651 circ->subtypes = NULL;
14652 }
14653 }
14654}
14655
14656
14657/**
14658 * xmlSchemaGetCircAttrGrRef:
14659 * @ctxtGr: the searched attribute group
14660 * @attr: the current attribute list to be processed
14661 *
14662 * This one is intended to be used by
14663 * xmlSchemaCheckSRCAttributeGroupCircular only.
14664 *
14665 * Returns the circular attribute grou reference, otherwise NULL.
14666 */
14667static xmlSchemaAttributeGroupPtr
14668xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
14669 xmlSchemaAttributePtr attr)
14670{
14671 xmlSchemaAttributeGroupPtr circ = NULL, gr;
14672 int marked;
14673 /*
14674 * We will search for an attribute group reference which
14675 * references the context attribute group.
14676 */
14677 while (attr != NULL) {
14678 marked = 0;
14679 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
14680 gr = (xmlSchemaAttributeGroupPtr) attr;
14681 if (gr->refItem != NULL) {
14682 if (gr->refItem == ctxtGr)
14683 return (gr);
14684 else if (gr->refItem->flags &
14685 XML_SCHEMAS_ATTRGROUP_MARKED) {
14686 attr = attr->next;
14687 continue;
14688 } else {
14689 /*
14690 * Mark as visited to avoid infinite recursion on
14691 * circular references not yet examined.
14692 */
14693 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
14694 marked = 1;
14695 }
14696 }
14697 if (gr->attributes != NULL)
14698 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
14699 /*
14700 * Unmark the visited group's attributes.
14701 */
14702 if (marked)
14703 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
14704 if (circ != NULL)
14705 return (circ);
14706 }
14707 attr = attr->next;
14708 }
14709 return (NULL);
14710}
14711
14712/**
14713 * xmlSchemaCheckSRCAttributeGroupCircular:
14714 * attrGr: the attribute group definition
14715 * @ctxt: the parser context
14716 * @name: the name
14717 *
14718 * Checks for circular references of attribute groups.
14719 */
14720static void
14721xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
14722 xmlSchemaParserCtxtPtr ctxt,
14723 const xmlChar * name ATTRIBUTE_UNUSED)
14724{
14725 /*
14726 * Schema Representation Constraint:
14727 * Attribute Group Definition Representation OK
14728 * 3 Circular group reference is disallowed outside <redefine>.
14729 * That is, unless this element information item's parent is
14730 * <redefine>, then among the [children], if any, there must
14731 * not be an <attributeGroup> with ref [attribute] which resolves
14732 * to the component corresponding to this <attributeGroup>. Indirect
14733 * circularity is also ruled out. That is, when QName resolution
14734 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
14735 * any <attributeGroup>s with a ref [attribute] among the [children],
14736 * it must not be the case that a ·QName· is encountered at any depth
14737 * which resolves to the component corresponding to this <attributeGroup>.
14738 */
14739 /*
14740 * Only global components can be referenced.
14741 */
14742 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
14743 (attrGr->attributes == NULL))
14744 return;
14745 else {
14746 xmlSchemaAttributeGroupPtr circ;
14747
14748 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
14749 if (circ != NULL) {
14750 /*
14751 * TODO: Report the referenced attr group as QName.
14752 */
14753 xmlSchemaPCustomErr(ctxt,
14754 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
14755 NULL, NULL, circ->node,
14756 "Circular reference to the attribute group '%s' "
14757 "defined", attrGr->name);
14758 /*
14759 * NOTE: We will cut the reference to avoid further
14760 * confusion of the processor.
14761 * BADSPEC: The spec should define how to process in this case.
14762 */
14763 circ->attributes = NULL;
14764 circ->refItem = NULL;
14765 }
14766 }
14767}
14768
14769/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000014770 * xmlSchemaAttrGrpFixup:
14771 * @attrgrpDecl: the schema attribute definition
14772 * @ctxt: the schema parser context
14773 * @name: the attribute name
14774 *
14775 * Fixes finish doing the computations on the attributes definitions
14776 */
14777static void
Daniel Veillard3646d642004-06-02 19:19:14 +000014778xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014779 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000014780{
14781 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000014782 name = attrgrp->name;
14783 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014784 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000014785 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014786 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000014787
Daniel Veillardc0826a72004-08-10 14:17:33 +000014788 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
14789 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014790 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014791 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014792 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014793 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
14794 "ref", attrgrp->ref, attrgrp->refNs,
14795 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014796 return;
14797 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014798 attrgrp->refItem = ref;
14799 /*
14800 * Check for self reference!
14801 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014802 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000014803 attrgrp->attributes = ref->attributes;
14804 attrgrp->attributeWildcard = ref->attributeWildcard;
14805 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000014806}
14807
14808/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014809 * xmlSchemaAttrCheckValConstr:
14810 * @item: an schema attribute declaration/use
14811 * @ctxt: a schema parser context
14812 * @name: the name of the attribute
14813 *
14814 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000014815 *
14816 * Fixes finish doing the computations on the attributes definitions
14817 */
14818static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014819xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
14820 xmlSchemaParserCtxtPtr ctxt,
14821 const xmlChar * name ATTRIBUTE_UNUSED)
14822{
14823
14824 /*
14825 * a-props-correct
14826 * Schema Component Constraint: Attribute Declaration Properties Correct
14827 *
14828 * 2 if there is a {value constraint}, the canonical lexical
14829 * representation of its value must be ·valid· with respect
14830 * to the {type definition} as defined in String Valid (§3.14.4).
14831 */
14832
14833 if (item->defValue != NULL) {
14834 int ret;
14835 xmlNodePtr node;
14836 xmlSchemaTypePtr type;
14837
14838 if (item->subtypes == NULL) {
14839 xmlSchemaPErr(ctxt, item->node,
14840 XML_SCHEMAP_INTERNAL,
14841 "Internal error: xmlSchemaCheckAttrValConstr, "
14842 "type is missing... skipping validation of "
14843 "value constraint", NULL, NULL);
14844 return;
14845 }
14846
14847 /*
14848 * TODO: Try to avoid creating a new context.
14849 * TODO: This all is not very performant.
14850 */
14851 type = item->subtypes;
14852 /*
14853 * Ensure there's validation context.
14854 */
14855 if (ctxt->vctxt == NULL) {
14856 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
14857 xmlSchemaPErr(ctxt, item->node,
14858 XML_SCHEMAP_INTERNAL,
14859 "Internal error: xmlSchemaCheckAttrValConstr, "
14860 "creating a new validation context.\n",
14861 NULL, NULL);
14862 return;
14863 }
14864 }
14865
14866 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
14867 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
14868 else
14869 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
14870 ctxt->vctxt->node = node;
14871 ctxt->vctxt->cur = NULL;
14872 /*
14873 * NOTE: This call does not check the content nodes,
14874 * since they are not available:
14875 * facet->node is just the node holding the facet
14876 * definition, *not* the attribute holding the *value*
14877 * of the facet.
14878 */
14879 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
14880 item->defValue, 0, 1, 1, 0);
14881 if (ret == 0) {
14882 /*
14883 * Store the computed value.
14884 */
14885 item->defVal = ctxt->vctxt->value;
14886 ctxt->vctxt->value = NULL;
14887 } else if (ret > 0) {
14888 if (ctxt != NULL) {
14889 xmlSchemaPSimpleTypeErr(ctxt,
14890 XML_SCHEMAP_A_PROPS_CORRECT_2,
14891 NULL, NULL, node,
14892 type, NULL, item->defValue,
14893 NULL, NULL, NULL);
14894 }
14895 } else if (ret < 0) {
14896 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14897 NULL, NULL, node,
14898 "Internal error: xmlSchemaAttrCheckValConstr, "
14899 "failed to validate the value constraint of the "
14900 "attribute decl/use against the type '%s'",
14901 type->name);
14902 }
14903 }
14904}
14905
14906#if 0 /* Not used yet. */
14907static int
14908xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
14909 xmlSchemaElementPtr edecl)
14910{
14911 /*
14912 * TODO: 1 The values of the properties of an element declaration must be as
14913 * described in the property tableau in The Element Declaration Schema
14914 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
14915 */
14916 /*
14917 * 2 If there is a {value constraint}, the canonical lexical
14918 * representation of its value must be ·valid· with respect to the {type
14919 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14920 *
14921 * NOTE: This is done in xmlSchemaCheckElemValConstr.
14922 */
14923 /*
14924 * 3 If there is a non-·absent· {substitution group affiliation},
14925 * then {scope} must be global.
14926 *
14927 * NOTE: This is done in xmlSchemaParseElement.
14928 * TODO: Move it to this layer here.
14929 */
14930 /*
14931 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
14932 * of the element declaration must be validly derived from the {type
14933 * definition} of the {substitution group affiliation}, given the value
14934 * of the {substitution group exclusions} of the {substitution group
14935 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
14936 * (if the {type definition} is complex) or as defined in
14937 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
14938 * simple).
14939 */
14940 /*
14941 * TODO: 5 If the {type definition} or {type definition}'s {content type}
14942 * is or is derived from ID then there must not be a {value constraint}.
14943 * Note: The use of ID as a type definition for elements goes beyond
14944 * XML 1.0, and should be avoided if backwards compatibility is desired
14945 */
14946 /*
14947 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
14948 * be possible to return to an element declaration by repeatedly following
14949 * the {substitution group affiliation} property.
14950 */
14951}
14952#endif
14953
14954/**
14955 * xmlSchemaCheckElemValConstr:
14956 * @item: an schema element declaration/particle
14957 * @ctxt: a schema parser context
14958 * @name: the name of the attribute
14959 *
14960 * Validates the value constraints of an element declaration.
14961 *
14962 * Fixes finish doing the computations on the element declarations.
14963 */
14964static void
14965xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
14966 xmlSchemaParserCtxtPtr ctxt,
14967 const xmlChar * name ATTRIBUTE_UNUSED)
14968{
14969 if (decl->value != NULL) {
14970 int ret;
14971 xmlNodePtr node = NULL;
14972 xmlSchemaTypePtr type;
14973
14974 /*
14975 * 2 If there is a {value constraint}, the canonical lexical
14976 * representation of its value must be ·valid· with respect to the {type
14977 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14978 */
14979 if (decl->subtypes == NULL) {
14980 xmlSchemaPErr(ctxt, decl->node,
14981 XML_SCHEMAP_INTERNAL,
14982 "Internal error: xmlSchemaCheckElemValConstr, "
14983 "type is missing... skipping validation of "
14984 "the value constraint", NULL, NULL);
14985 return;
14986 }
14987 /*
14988 * Ensure there's a validation context.
14989 */
14990 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14991 return;
14992
14993 type = decl->subtypes;
14994
14995 if (decl->node != NULL) {
14996 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
14997 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
14998 else
14999 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
15000 }
15001 ctxt->vctxt->node = node;
15002 ctxt->vctxt->cur = NULL;
15003 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
15004 node);
15005 if (ret == 0) {
15006 /*
15007 * Consume the computed value.
15008 */
15009 decl->defVal = ctxt->vctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000015010 ctxt->vctxt->value = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015011 } else if (ret < 0) {
15012 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
15013 NULL, NULL, node,
15014 "Internal error: xmlSchemaElemCheckValConstr, "
15015 "failed to validate the value constraint of the "
15016 "element declaration '%s'",
15017 decl->name);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000015018 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015019 }
15020}
15021
15022/**
15023 * xmlSchemaAttrFixup:
15024 * @item: an schema attribute declaration/use.
15025 * @ctxt: a schema parser context
15026 * @name: the name of the attribute
15027 *
15028 * Fixes finish doing the computations on attribute declarations/uses.
15029 */
15030static void
15031xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
15032 xmlSchemaParserCtxtPtr ctxt,
15033 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000015034{
Daniel Veillardc0826a72004-08-10 14:17:33 +000015035 /*
15036 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015037 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000015038 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015039 /*
15040 * The simple type definition corresponding to the <simpleType> element
15041 * information item in the [children], if present, otherwise the simple
15042 * type definition ·resolved· to by the ·actual value· of the type
15043 * [attribute], if present, otherwise the ·simple ur-type definition·.
15044 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015045 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015046 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015047 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
15048 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015049 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015050 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015051 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000015052
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015053 type = xmlSchemaGetType(ctxt->schema, item->typeName,
15054 item->typeNs);
15055 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015056 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015057 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015058 NULL, (xmlSchemaTypePtr) item, item->node,
15059 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015060 XML_SCHEMA_TYPE_SIMPLE, NULL);
15061 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015062 item->subtypes = type;
15063
15064 } else if (item->ref != NULL) {
15065 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000015066
Daniel Veillardc0826a72004-08-10 14:17:33 +000015067 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015068 * We have an attribute use here; assign the referenced
15069 * attribute declaration.
15070 */
15071 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015072 * TODO: Evaluate, what errors could occur if the declaration is not
15073 * found. It might be possible that the "typefixup" might crash if
15074 * no ref declaration was found.
15075 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015076 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
15077 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015078 xmlSchemaPResCompAttrErr(ctxt,
15079 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015080 NULL, (xmlSchemaTypePtr) item, item->node,
15081 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015082 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015083 return;
15084 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015085 item->refDecl = decl;
15086 xmlSchemaAttrFixup(decl, ctxt, NULL);
15087
15088 item->subtypes = decl->subtypes;
15089 /*
15090 * Attribute Use Correct
15091 * au-props-correct.2: If the {attribute declaration} has a fixed
15092 * {value constraint}, then if the attribute use itself has a
15093 * {value constraint}, it must also be fixed and its value must match
15094 * that of the {attribute declaration}'s {value constraint}.
15095 */
15096 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
15097 (item->defValue != NULL)) {
15098 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
15099 (!xmlStrEqual(item->defValue, decl->defValue))) {
15100 xmlSchemaPCustomErr(ctxt,
15101 XML_SCHEMAP_AU_PROPS_CORRECT_2,
15102 NULL, NULL, item->node,
15103 "The value constraint must be fixed "
15104 "and match the referenced attribute "
15105 "declarations's value constraint '%s'",
15106 decl->defValue);
15107 }
15108 /*
15109 * FUTURE: One should change the values of the attr. use
15110 * if ever validation should be attempted even if the
15111 * schema itself was not fully valid.
15112 */
15113 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015114 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015115 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
15116 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015117}
15118
15119/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015120 * xmlSchemaResolveIDCKeyRef:
15121 * @idc: the identity-constraint definition
15122 * @ctxt: the schema parser context
15123 * @name: the attribute name
15124 *
15125 * Resolve keyRef references to key/unique IDCs.
15126 */
15127static void
15128xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
15129 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000015130 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015131{
15132 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
15133 return;
15134 if (idc->ref->name != NULL) {
15135 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
15136 ctxt->schema->idcDef,
15137 idc->ref->name,
15138 idc->ref->targetNamespace);
15139 if (idc->ref->item == NULL) {
15140 /*
15141 * TODO: It is actually not an error to fail to resolve.
15142 */
15143 xmlSchemaPResCompAttrErr(ctxt,
15144 XML_SCHEMAP_SRC_RESOLVE,
15145 NULL, (xmlSchemaTypePtr) idc, idc->node,
15146 "refer", idc->ref->name,
15147 idc->ref->targetNamespace,
15148 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
15149 return;
15150 }
15151 }
15152}
15153
15154/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015155 * xmlSchemaParse:
15156 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000015157 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000015158 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000015159 * XML Shema struture which can be used to validate instances.
15160 * *WARNING* this interface is highly subject to change
15161 *
15162 * Returns the internal XML Schema structure built from the resource or
15163 * NULL in case of error
15164 */
15165xmlSchemaPtr
15166xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
15167{
15168 xmlSchemaPtr ret = NULL;
15169 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000015170 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000015171 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000015172
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015173 /*
15174 * This one is used if the schema to be parsed was specified via
15175 * the API; i.e. not automatically by the validated instance document.
15176 */
15177
Daniel Veillard4255d502002-04-16 15:50:10 +000015178 xmlSchemaInitTypes();
15179
Daniel Veillard6045c902002-10-09 21:13:59 +000015180 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000015181 return (NULL);
15182
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000015183 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000015184 ctxt->counter = 0;
15185 ctxt->container = NULL;
15186
15187 /*
15188 * First step is to parse the input document into an DOM/Infoset
15189 */
Daniel Veillard6045c902002-10-09 21:13:59 +000015190 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000015191 doc = xmlReadFile((const char *) ctxt->URL, NULL,
15192 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015193 if (doc == NULL) {
15194 xmlSchemaPErr(ctxt, NULL,
15195 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015196 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015197 ctxt->URL, NULL);
15198 return (NULL);
15199 }
Daniel Veillard6045c902002-10-09 21:13:59 +000015200 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000015201 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
15202 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015203 if (doc == NULL) {
15204 xmlSchemaPErr(ctxt, NULL,
15205 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015206 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015207 NULL, NULL);
15208 return (NULL);
15209 }
15210 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000015211 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000015212 } else if (ctxt->doc != NULL) {
15213 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000015214 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000015215 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015216 xmlSchemaPErr(ctxt, NULL,
15217 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015218 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015219 NULL, NULL);
15220 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000015221 }
15222
15223 /*
15224 * Then extract the root and Schema parse it
15225 */
15226 root = xmlDocGetRootElement(doc);
15227 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015228 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
15229 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015230 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000015231 if (!preserve) {
15232 xmlFreeDoc(doc);
15233 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015234 return (NULL);
15235 }
15236
15237 /*
15238 * Remove all the blank text nodes
15239 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000015240 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000015241
15242 /*
15243 * Then do the parsing for good
15244 */
15245 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000015246 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000015247 if (!preserve) {
15248 xmlFreeDoc(doc);
15249 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015250 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000015251 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015252 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000015253 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000015254 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015255 ctxt->ctxtType = NULL;
15256 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015257 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000015258 * Then fixup all attributes declarations
15259 */
15260 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
15261
15262 /*
15263 * Then fixup all attributes group declarations
15264 */
15265 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
15266 ctxt);
15267
15268 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015269 * Resolve identity-constraint keyRefs.
15270 */
15271 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
15272
15273 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015274 * Check attribute groups for circular references.
15275 */
15276 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
15277 xmlSchemaCheckAttributeGroupCircular, ctxt);
15278
15279 /*
15280 * Then fixup all model group definitions.
15281 */
15282 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015283
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015284 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015285 * Then fix references of element declaration; apply constraints.
15286 */
15287 xmlHashScanFull(ret->elemDecl,
15288 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000015289
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015290 /*
15291 * We will stop here if the schema was not valid to avoid internal errors
15292 * on missing sub-components. This is not conforming to the spec, since it
15293 * allows missing components, but it might make further processing crash.
15294 * So see it as a very strict handling, which might be made more lax in the
15295 * future.
15296 */
15297 if (ctxt->nberrors != 0)
15298 goto exit;
15299 /*
15300 * Then fixup all types properties
15301 */
15302 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015303 /*
15304 * Check model groups defnitions for circular references.
15305 */
15306 xmlHashScan(ret->groupDecl, (xmlHashScanner)
15307 xmlSchemaCheckGroupDefCircular, ctxt);
15308
Daniel Veillard4255d502002-04-16 15:50:10 +000015309 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015310 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000015311 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015312 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015313 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000015314
15315 /*
15316 * Then check the defaults part of the type like facets values
15317 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015318 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000015319
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015320 /*
15321 * Validate the value constraint of attribute declarations/uses.
15322 */
15323 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
15324
15325 /*
15326 * Validate the value constraint of element declarations.
15327 */
15328 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
15329
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015330exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000015331 if (ctxt->nberrors != 0) {
15332 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015333 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000015334 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015335 return (ret);
15336}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015337
Daniel Veillard4255d502002-04-16 15:50:10 +000015338/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000015339 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000015340 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000015341 * @err: the error callback
15342 * @warn: the warning callback
15343 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000015344 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000015345 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000015346 */
15347void
15348xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015349 xmlSchemaValidityErrorFunc err,
15350 xmlSchemaValidityWarningFunc warn, void *ctx)
15351{
Daniel Veillard4255d502002-04-16 15:50:10 +000015352 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015353 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000015354 ctxt->error = err;
15355 ctxt->warning = warn;
15356 ctxt->userData = ctx;
15357}
15358
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015359/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000015360 * xmlSchemaGetParserErrors:
15361 * @ctxt: a XMl-Schema parser context
15362 * @err: the error callback result
15363 * @warn: the warning callback result
15364 * @ctx: contextual data for the callbacks result
15365 *
15366 * Get the callback information used to handle errors for a parser context
15367 *
15368 * Returns -1 in case of failure, 0 otherwise
15369 */
15370int
15371xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
15372 xmlSchemaValidityErrorFunc * err,
15373 xmlSchemaValidityWarningFunc * warn, void **ctx)
15374{
15375 if (ctxt == NULL)
15376 return(-1);
15377 if (err != NULL)
15378 *err = ctxt->error;
15379 if (warn != NULL)
15380 *warn = ctxt->warning;
15381 if (ctx != NULL)
15382 *ctx = ctxt->userData;
15383 return(0);
15384}
15385
15386/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015387 * xmlSchemaFacetTypeToString:
15388 * @type: the facet type
15389 *
15390 * Convert the xmlSchemaTypeType to a char string.
15391 *
15392 * Returns the char string representation of the facet type if the
15393 * type is a facet and an "Internal Error" string otherwise.
15394 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015395static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015396xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
15397{
15398 switch (type) {
15399 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015400 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015401 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015402 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015403 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015404 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015405 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015406 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015407 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015408 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015409 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015410 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015411 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015412 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015413 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015414 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015415 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015416 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015417 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015418 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015419 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015420 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015421 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015422 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015423 default:
15424 break;
15425 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015426 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015427}
15428
Daniel Veillardc0826a72004-08-10 14:17:33 +000015429static int
15430xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
15431{
15432 xmlSchemaTypePtr anc;
15433
15434 /*
15435 * The normalization type can be changed only for types which are derived
15436 * from xsd:string.
15437 */
15438 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000015439 if (type->builtInType == XML_SCHEMAS_STRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015440 return(XML_SCHEMAS_FACET_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000015441 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015442 return(XML_SCHEMAS_FACET_REPLACE);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015443 else if (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
15444 /*
15445 * Note that we assume a whitespace of preserve for anySimpleType.
15446 */
15447 return(XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015448 else {
15449 /*
15450 * For all ·atomic· datatypes other than string (and types ·derived·
15451 * by ·restriction· from it) the value of whiteSpace is fixed to
15452 * collapse
15453 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015454 return(XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015455 }
15456 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15457 /*
15458 * For list types the facet "whiteSpace" is fixed to "collapse".
15459 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015460 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015461 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015462 return (XML_SCHEMAS_FACET_UNKNOWN);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015463 } else if (type->facetSet != NULL) {
15464 xmlSchemaTypePtr anyST;
15465 xmlSchemaFacetLinkPtr lin;
15466
15467 /*
15468 * Atomic types.
15469 */
15470 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
15471 anc = type->baseType;
15472 do {
15473 /*
15474 * For all ·atomic· datatypes other than string (and types ·derived·
15475 * by ·restriction· from it) the value of whiteSpace is fixed to
15476 * collapse
15477 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015478 if ((anc->builtInType == XML_SCHEMAS_STRING) ||
15479 (anc->builtInType == XML_SCHEMAS_NORMSTRING)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015480
15481 lin = type->facetSet;
15482 do {
15483 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015484 return(lin->facet->whitespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015485 break;
15486 }
15487 lin = lin->next;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015488 } while (lin != NULL);
15489 if (anc->builtInType == XML_SCHEMAS_NORMSTRING)
15490 return (XML_SCHEMAS_FACET_REPLACE);
15491 else
15492 return (XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015493 }
15494 anc = anc->baseType;
15495 } while (anc != anyST);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015496 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015497 }
15498 return (-1);
15499}
15500
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015501/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000015502 * xmlSchemaValidateFacetsInternal:
15503 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000015504 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000015505 * @facets: the list of facets to check
15506 * @value: the lexical repr of the value to validate
15507 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000015508 * @fireErrors: if 0, only internal errors will be fired;
15509 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000015510 *
15511 * Check a value against all facet conditions
15512 *
15513 * Returns 0 if the element is schemas valid, a positive error code
15514 * number otherwise and -1 in case of internal or API error.
15515 */
15516static int
15517xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015518 xmlSchemaTypePtr type,
15519 const xmlChar * value,
15520 unsigned long length,
15521 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000015522{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015523 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015524 xmlNodePtr node;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015525 xmlSchemaTypePtr biType; /* The build-in type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015526 xmlSchemaTypePtr tmpType;
15527 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000015528 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015529 xmlSchemaFacetPtr facet;
15530 unsigned long len = 0;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015531 xmlSchemaWhitespaceValueType ws;
15532
15533 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
15534 xmlSchemaTypePtr tp;
15535 /*
15536 * TODO: Get rid of this case: the complex type still holds facets in some
15537 * cases.
15538 */
15539 tp = xmlSchemaGetSimpleContentType(type);
15540 ws = (xmlSchemaWhitespaceValueType) xmlSchemaGetWhiteSpaceFacetValue(tp);
15541 } else
15542 ws = (xmlSchemaWhitespaceValueType) xmlSchemaGetWhiteSpaceFacetValue(type);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015543
Daniel Veillardc0826a72004-08-10 14:17:33 +000015544#ifdef DEBUG_UNION_VALIDATION
15545 printf("Facets of type: '%s'\n", (const char *) type->name);
15546 printf(" fireErrors: %d\n", fireErrors);
15547#endif
15548
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015549 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015550 /*
15551 * NOTE: Do not jump away, if the facetSet of the given type is
15552 * empty: until now, "pattern" facets of the *base types* need to
15553 * be checked as well.
15554 */
15555 biType = type->baseType;
15556 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
15557 biType = biType->baseType;
15558 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015559 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015560 "Internal error: xmlSchemaValidateFacetsInternal, "
15561 "the base type axis of the given type '%s' does not resolve to "
15562 "a built-in type.\n",
15563 type->name, NULL);
15564 return (-1);
15565 }
15566
15567 if (type->facetSet != NULL) {
15568 facetLink = type->facetSet;
15569 while (facetLink != NULL) {
15570 facet = facetLink->facet;
15571 /*
15572 * Skip the pattern "whiteSpace": it is used to
15573 * format the character content beforehand.
15574 */
15575 switch (facet->type) {
15576 case XML_SCHEMA_FACET_WHITESPACE:
15577 case XML_SCHEMA_FACET_PATTERN:
15578 case XML_SCHEMA_FACET_ENUMERATION:
15579 break;
15580 case XML_SCHEMA_FACET_LENGTH:
15581 case XML_SCHEMA_FACET_MINLENGTH:
15582 case XML_SCHEMA_FACET_MAXLENGTH:
15583 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15584 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015585 value, length, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015586 len = length;
15587 } else
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015588 ret = xmlSchemaValidateLengthFacetWhtsp(facet,
15589 (xmlSchemaValType) biType->builtInType,
15590 value, ctxt->value, &len, ws);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015591 break;
15592 default:
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015593 ret = xmlSchemaValidateFacetWhtsp(facet, ws,
15594 biType->builtInType, value, ctxt->value, ws);
15595 /*
15596 * ret = xmlSchemaValidateFacet(biType, facet, value,
15597 * ctxt->value);
15598 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015599 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015600 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015601 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015602 "Internal error: xmlSchemaValidateFacetsInternal, "
15603 "validating facet of type '%s'.\n",
15604 type->name, NULL);
15605 break;
15606 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015607 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015608 type, facet, NULL, NULL, NULL, NULL);
15609 }
15610
15611 facetLink = facetLink->next;
15612 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015613
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015614 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015615 if (ret >= 0) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015616 xmlSchemaWhitespaceValueType fws;
15617 /*
15618 * Process enumerations. Facet values are in the value space
15619 * of the defining type's base type. This seems to be a bug in the
15620 * XML Schema 1.0 spec. For use, the normalized value is only
15621 * significant for enumerations. We need to localize the base type for eatch
15622 * enumeration facet, thus walk the ancestor type axis.
15623 */
15624 tmpType = type;
15625 do {
15626 /*
15627 * Use the whitespace type of the base type.
15628 */
15629 if (tmpType->type == XML_SCHEMA_TYPE_COMPLEX)
15630 /* TODO: Get rid of this case. */
15631 fws = (xmlSchemaWhitespaceValueType)
15632 xmlSchemaGetWhiteSpaceFacetValue(
15633 xmlSchemaGetSimpleContentType(tmpType));
15634 else
15635 fws = (xmlSchemaWhitespaceValueType)
15636 xmlSchemaGetWhiteSpaceFacetValue(tmpType->baseType);
15637 retFacet = 0;
15638 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
15639 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
15640 continue;
15641 retFacet = xmlSchemaValidateFacetWhtsp(facet, fws,
15642 biType->builtInType, value, ctxt->value, ws);
15643 if (retFacet == 0)
15644 break;
15645 else if (retFacet < 0) {
15646 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
15647 "Internal error: xmlSchemaValidateFacetsInternal, "
15648 "validating enumeration facet '%s' of type '%s'.\n",
15649 facet->value, tmpType->name);
15650 ret = -1;
15651 break;
15652 }
15653 }
15654 if (retFacet <= 0)
15655 break;
15656 if (tmpType->type == XML_SCHEMA_TYPE_COMPLEX)
15657 /* TODO: Get rid of this case. */
15658 tmpType = xmlSchemaGetSimpleContentType(tmpType);
15659 else
15660 tmpType = tmpType->baseType;
15661 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
15662 if (retFacet > 0) {
15663 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
15664 if (fireErrors) {
15665 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, NULL,
15666 NULL, NULL, NULL, NULL);
15667 }
15668 }
15669 }
15670
15671 if (ret >= 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015672 /*
15673 * Process patters. Pattern facets are ORed at type level
15674 * and ANDed if derived. Walk the base type axis.
15675 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015676 tmpType = type;
15677 facet = NULL;
15678 do {
15679 retFacet = 0;
15680 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015681 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015682 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
15683 continue;
15684 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
15685 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015686 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015687 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015688 else if (retFacet < 0) {
15689 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
15690 "Internal error: xmlSchemaValidateFacetsInternal, "
15691 "validating 'pattern' facet '%s' of type '%s'.\n",
15692 facetLink->facet->value, tmpType->name);
15693 ret = -1;
15694 break;
15695 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000015696 /* Save the last non-validating facet. */
15697 facet = facetLink->facet;
15698 }
15699 if (retFacet != 0)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015700 break;
15701 if (tmpType->type == XML_SCHEMA_TYPE_COMPLEX)
15702 /* TODO: Get rid of this case. */
15703 tmpType = xmlSchemaGetSimpleContentType(tmpType);
15704 else
15705 tmpType = tmpType->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015706 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015707 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015708 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
15709 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015710 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015711 NULL, NULL, NULL, NULL);
15712 }
15713 }
15714 }
15715
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015716 return (ret);
15717}
15718
Daniel Veillard4255d502002-04-16 15:50:10 +000015719/************************************************************************
15720 * *
15721 * Simple type validation *
15722 * *
15723 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000015724
Daniel Veillard4255d502002-04-16 15:50:10 +000015725
15726/************************************************************************
15727 * *
15728 * DOM Validation code *
15729 * *
15730 ************************************************************************/
15731
Daniel Veillard4255d502002-04-16 15:50:10 +000015732static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015733 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000015734 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015735static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015736 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000015737 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015738 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000015739
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015740static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015741static int xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015742
15743#ifdef ELEM_INFO_ENABLED
15744/**
15745 * xmlSchemaGetFreshElemInfo:
15746 * @vctxt: the schema validation context
15747 *
15748 * Creates/reuses and initializes the element info item for
15749 * the currect tree depth.
15750 *
15751 * Returns the element info item or NULL on API or internal errors.
15752 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015753static xmlSchemaNodeInfoPtr
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015754xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt,
15755 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015756{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015757 xmlSchemaNodeInfoPtr info = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015758
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015759 if (depth > vctxt->sizeElemInfos) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015760 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015761 "Internal error: xmlSchemaGetFreshElemInfo, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015762 "an inconsistent depth encountered.\n",
15763 NULL, NULL);
15764 return (NULL);
15765 }
15766 if (vctxt->elemInfos == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015767 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
15768 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015769 if (vctxt->elemInfos == NULL) {
15770 xmlSchemaVErrMemory(vctxt,
15771 "allocating the element info array", NULL);
15772 return (NULL);
15773 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015774 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015775 vctxt->sizeElemInfos = 10;
15776 } else if (vctxt->sizeElemInfos == vctxt->depth) {
15777 int i = vctxt->sizeElemInfos;
15778
15779 vctxt->sizeElemInfos *= 2;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015780 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015781 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015782 sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015783 if (vctxt->elemInfos == NULL) {
15784 xmlSchemaVErrMemory(vctxt,
15785 "re-allocating the element info array", NULL);
15786 return (NULL);
15787 }
15788 /*
15789 * We need the new memory to be NULLed.
15790 * TODO: Use memset instead?
15791 */
15792 for (; i < vctxt->sizeElemInfos; i++)
15793 vctxt->elemInfos[i] = NULL;
15794 } else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015795 info = vctxt->elemInfos[depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015796
15797 if (info == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015798 info = (xmlSchemaNodeInfoPtr)
15799 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015800 if (info == NULL) {
15801 xmlSchemaVErrMemory(vctxt,
15802 "allocating an element info", NULL);
15803 return (NULL);
15804 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015805 vctxt->elemInfos[depth] = info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015806 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015807 memset(info, 0, sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015808 info->depth = depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015809
15810 return (info);
15811}
15812#endif /* ELEM_INFO_ENABLED */
15813
Daniel Veillard3646d642004-06-02 19:19:14 +000015814
15815/**
15816 * xmlSchemaFreeAttrStates:
15817 * @state: a list of attribute states
15818 *
15819 * Free the given list of attribute states
15820 *
15821 */
15822static void
15823xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
15824{
15825 xmlSchemaAttrStatePtr tmp;
15826 while (state != NULL) {
15827 tmp = state;
15828 state = state->next;
15829 xmlFree(tmp);
15830 }
15831}
15832
Daniel Veillard4255d502002-04-16 15:50:10 +000015833/**
15834 * xmlSchemaRegisterAttributes:
15835 * @ctxt: a schema validation context
15836 * @attrs: a list of attributes
15837 *
15838 * Register the list of attributes as the set to be validated on that element
15839 *
15840 * Returns -1 in case of error, 0 otherwise
15841 */
15842static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015843xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
15844{
Daniel Veillard3646d642004-06-02 19:19:14 +000015845 xmlSchemaAttrStatePtr tmp;
15846
15847 ctxt->attr = NULL;
15848 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015849 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015850 if ((attrs->ns != NULL) &&
15851 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
15852 attrs = attrs->next;
15853 continue;
15854 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015855 tmp = (xmlSchemaAttrStatePtr)
15856 xmlMalloc(sizeof(xmlSchemaAttrState));
15857 if (tmp == NULL) {
15858 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
15859 return (-1);
15860 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015861 tmp->attr = attrs;
15862 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
15863 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015864 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015865 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015866 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000015867 else
15868 ctxt->attrTop->next = tmp;
15869 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015870 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015871 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015872 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000015873}
15874
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015875#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000015876/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015877 * xmlSchemaValidateCheckNodeList
15878 * @nodelist: the list of nodes
15879 *
15880 * Check the node list is only made of text nodes and entities pointing
15881 * to text nodes
15882 *
15883 * Returns 1 if true, 0 if false and -1 in case of error
15884 */
15885static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015886xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
15887{
Daniel Veillard4255d502002-04-16 15:50:10 +000015888 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015889 if (nodelist->type == XML_ENTITY_REF_NODE) {
15890 TODO /* implement recursion in the entity content */
15891 }
15892 if ((nodelist->type != XML_TEXT_NODE) &&
15893 (nodelist->type != XML_COMMENT_NODE) &&
15894 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000015895 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015896 return (0);
15897 }
15898 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015899 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015900 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015901}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015902#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015903
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015904static void
15905xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
15906{
15907 int i, nbItems;
15908 xmlSchemaTypePtr item, *items;
15909
15910
15911 /*
15912 * During the Assemble of the schema ctxt->curItems has
15913 * been filled with the relevant new items. Fix those up.
15914 */
15915 nbItems = ctxt->assemble->nbItems;
15916 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
15917
15918 for (i = 0; i < nbItems; i++) {
15919 item = items[i];
15920 switch (item->type) {
15921 case XML_SCHEMA_TYPE_ATTRIBUTE:
15922 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
15923 break;
15924 case XML_SCHEMA_TYPE_ELEMENT:
15925 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
15926 NULL, NULL, NULL);
15927 break;
15928 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15929 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
15930 ctxt, NULL);
15931 break;
15932 case XML_SCHEMA_TYPE_GROUP:
15933 xmlSchemaGroupDefFixup(item, ctxt, NULL);
15934 default:
15935 break;
15936 }
15937 }
15938 /*
15939 * Circularity checks.
15940 */
15941 for (i = 0; i < nbItems; i++) {
15942 item = items[i];
15943 switch (item->type) {
15944 case XML_SCHEMA_TYPE_GROUP:
15945 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
15946 break;
15947 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15948 xmlSchemaCheckAttributeGroupCircular(
15949 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
15950 break;
15951 default:
15952 break;
15953 }
15954 }
15955 /*
15956 * Fixup for all other item.
15957 * TODO: Hmm, not sure if starting from complex/simple types,
15958 * all subsequent items will be reached.
15959 */
15960 for (i = 0; i < nbItems; i++) {
15961 item = items[i];
15962 switch (item->type) {
15963 case XML_SCHEMA_TYPE_SIMPLE:
15964 case XML_SCHEMA_TYPE_COMPLEX:
15965 xmlSchemaTypeFixup(item, ctxt, NULL);
15966 break;
15967 default:
15968 break;
15969 }
15970 }
15971 /*
15972 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015973 * hold by simple type components only (and
15974 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015975 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015976 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015977 for (i = 0; i < nbItems; i++) {
15978 item = items[i];
15979 switch (item->type) {
15980 case XML_SCHEMA_TYPE_SIMPLE:
15981 case XML_SCHEMA_TYPE_COMPLEX:
15982 xmlSchemaCheckDefaults(item, ctxt, NULL);
15983 break;
15984 default:
15985 break;
15986 }
15987 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015988 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015989 /*
15990 * Build the content model for complex types.
15991 */
15992 for (i = 0; i < nbItems; i++) {
15993 item = items[i];
15994 switch (item->type) {
15995 case XML_SCHEMA_TYPE_COMPLEX:
15996 xmlSchemaBuildContentModel(item, ctxt, NULL);
15997 break;
15998 default:
15999 break;
16000 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016001 }
16002 /*
16003 * Validate value contraint values.
16004 */
16005 for (i = 0; i < nbItems; i++) {
16006 item = items[i];
16007 switch (item->type) {
16008 case XML_SCHEMA_TYPE_ATTRIBUTE:
16009 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
16010 break;
16011 case XML_SCHEMA_TYPE_ELEMENT:
16012 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
16013 break;
16014 default:
16015 break;
16016 }
16017 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016018}
16019
16020/**
16021 * xmlSchemaAssembleByLocation:
16022 * @pctxt: a schema parser context
16023 * @vctxt: a schema validation context
16024 * @schema: the existing schema
16025 * @node: the node that fired the assembling
16026 * @nsName: the namespace name of the new schema
16027 * @location: the location of the schema
16028 *
16029 * Expands an existing schema by an additional schema.
16030 *
16031 * Returns 0 if the new schema is correct, a positive error code
16032 * number otherwise and -1 in case of an internal or API error.
16033 */
16034static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016035xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
16036 xmlSchemaPtr schema,
16037 xmlNodePtr node,
16038 const xmlChar *nsName,
16039 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016040{
16041 const xmlChar *targetNs, *oldtns;
16042 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016043 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016044 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016045 xmlSchemaParserCtxtPtr pctxt;
16046
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016047 /*
16048 * This should be used:
16049 * 1. on <import>(s)
16050 * 2. if requested by the validated instance
16051 * 3. if requested via the API
16052 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016053 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016054 return (-1);
16055 /*
16056 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016057 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016058 if ((vctxt->pctxt == NULL) &&
16059 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
16060 xmlSchemaVErr(vctxt, node,
16061 XML_SCHEMAV_INTERNAL,
16062 "Internal error: xmlSchemaAssembleByLocation, "
16063 "failed to create a temp. parser context.\n",
16064 NULL, NULL);
16065 return (-1);
16066 }
16067 pctxt = vctxt->pctxt;
16068 /*
16069 * Set the counter to produce unique names for anonymous items.
16070 */
16071 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016072 /*
16073 * Acquire the schema document.
16074 */
16075 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
16076 nsName, location, &doc, &targetNs, 0);
16077 if (ret != 0) {
16078 if (doc != NULL)
16079 xmlFreeDoc(doc);
16080 } else if (doc != NULL) {
16081 docElem = xmlDocGetRootElement(doc);
16082 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016083 * Create new assemble info.
16084 */
16085 if (pctxt->assemble == NULL) {
16086 pctxt->assemble = xmlSchemaNewAssemble();
16087 if (pctxt->assemble == NULL) {
16088 xmlSchemaVErrMemory(vctxt,
16089 "Memory error: xmlSchemaAssembleByLocation, "
16090 "allocating assemble info", NULL);
16091 xmlFreeDoc(doc);
16092 return (-1);
16093 }
16094 }
16095 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016096 * Save and reset the context & schema.
16097 */
16098 oldflags = schema->flags;
16099 oldtns = schema->targetNamespace;
16100 olddoc = schema->doc;
16101
16102 xmlSchemaClearSchemaDefaults(schema);
16103 schema->targetNamespace = targetNs;
16104 /* schema->nbCurItems = 0; */
16105 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016106 pctxt->ctxtType = NULL;
16107 pctxt->parentItem = NULL;
16108
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016109 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
16110 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016111 xmlSchemaPostSchemaAssembleFixup(pctxt);
16112 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016113 * Set the counter of items.
16114 */
16115 schema->counter = pctxt->counter;
16116 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016117 * Free the list of assembled components.
16118 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016119 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016120 /*
16121 * Restore the context & schema.
16122 */
16123 schema->flags = oldflags;
16124 schema->targetNamespace = oldtns;
16125 schema->doc = olddoc;
16126 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016127 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016128 return (ret);
16129}
16130
16131/**
16132 * xmlSchemaAssembleByXSIAttr:
16133 * @vctxt: a schema validation context
16134 * @xsiAttr: an xsi attribute
16135 * @noNamespace: whether a schema with no target namespace is exptected
16136 *
16137 * Expands an existing schema by an additional schema using
16138 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
16139 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
16140 * must be set to 1.
16141 *
16142 * Returns 0 if the new schema is correct, a positive error code
16143 * number otherwise and -1 in case of an internal or API error.
16144 */
16145static int
16146xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
16147 xmlAttrPtr xsiAttr,
16148 int noNamespace)
16149{
16150 xmlChar *value;
16151 const xmlChar *cur, *end;
16152 const xmlChar *nsname = NULL, *location;
16153 int count = 0;
16154 int ret = 0;
16155
16156 if (xsiAttr == NULL) {
16157 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
16158 NULL, NULL,
16159 "Internal error: xmlSchemaAssembleByXSIAttr, "
16160 "bad arguments", NULL);
16161 return (-1);
16162 }
16163 /*
16164 * Parse the value; we will assume an even number of values
16165 * to be given (this is how Xerces and XSV work).
16166 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016167 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016168 cur = value;
16169 do {
16170 if (noNamespace != 1) {
16171 /*
16172 * Get the namespace name.
16173 */
16174 while (IS_BLANK_CH(*cur))
16175 cur++;
16176 end = cur;
16177 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
16178 end++;
16179 if (end == cur)
16180 break;
16181 count++;
16182 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
16183 cur = end;
16184 }
16185 /*
16186 * Get the URI.
16187 */
16188 while (IS_BLANK_CH(*cur))
16189 cur++;
16190 end = cur;
16191 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
16192 end++;
16193 if (end == cur)
16194 break;
16195 count++;
16196 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016197 cur = end;
16198 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016199 xsiAttr->parent, nsname, location);
16200 if (ret == -1) {
16201 xmlSchemaVCustomErr(vctxt,
16202 XML_SCHEMAV_INTERNAL,
16203 (xmlNodePtr) xsiAttr, NULL,
16204 "Internal error: xmlSchemaAssembleByXSIAttr, "
16205 "assembling schemata", NULL);
16206 if (value != NULL)
16207 xmlFree(value);
16208 return (-1);
16209 }
16210 } while (*cur != 0);
16211 if (value != NULL)
16212 xmlFree(value);
16213 return (ret);
16214}
16215
16216/**
16217 * xmlSchemaAssembleByXSIElem:
16218 * @vctxt: a schema validation context
16219 * @elem: an element node possibly holding xsi attributes
16220 * @noNamespace: whether a schema with no target namespace is exptected
16221 *
16222 * Assembles an existing schema by an additional schema using
16223 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
16224 * of the given @elem.
16225 *
16226 * Returns 0 if the new schema is correct, a positive error code
16227 * number otherwise and -1 in case of an internal or API error.
16228 */
16229static int
16230xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
16231 xmlNodePtr elem)
16232{
16233 int ret = 0, retNs = 0;
16234 xmlAttrPtr attr;
16235
16236 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
16237 if (attr != NULL) {
16238 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
16239 if (retNs == -1)
16240 return (-1);
16241 }
16242 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
16243 if (attr != NULL) {
16244 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
16245 if (ret == -1)
16246 return (-1);
16247 }
16248 if (retNs != 0)
16249 return (retNs);
16250 else
16251 return (ret);
16252}
16253
Daniel Veillard4255d502002-04-16 15:50:10 +000016254/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016255 * xmlSchemaValidateCallback:
16256 * @ctxt: a schema validation context
16257 * @name: the name of the element detected (might be NULL)
16258 * @type: the type
16259 *
16260 * A transition has been made in the automata associated to an element
16261 * content model
16262 */
16263static void
16264xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016265 const xmlChar * name ATTRIBUTE_UNUSED,
16266 xmlSchemaTypePtr type, xmlNodePtr node)
16267{
Daniel Veillard4255d502002-04-16 15:50:10 +000016268 xmlSchemaTypePtr oldtype = ctxt->type;
16269 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016270
Daniel Veillard4255d502002-04-16 15:50:10 +000016271#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000016272 xmlGenericError(xmlGenericErrorContext,
16273 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016274 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000016275#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016276 /*
16277 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
16278 */
Daniel Veillard4255d502002-04-16 15:50:10 +000016279 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016280 ctxt->node = node;
16281 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016282
16283#ifdef ELEM_INFO_ENABLED
16284 xmlSchemaBeginElement(ctxt);
16285#endif
16286
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016287 /*
16288 * Assemble new schemata using xsi.
16289 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016290 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016291 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016292
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016293 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
16294 if (ret == -1) {
16295 xmlSchemaVCustomErr(ctxt,
16296 XML_SCHEMAV_INTERNAL,
16297 ctxt->node, NULL,
16298 "Internal error: xmlSchemaValidateElement, "
16299 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016300 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016301 }
16302 /*
16303 * NOTE: We won't react on schema parser errors here.
16304 * TODO: But a warning would be nice.
16305 */
16306 }
16307 switch (type->type) {
16308 case XML_SCHEMA_TYPE_ELEMENT: {
16309 /*
16310 * NOTE: The build of the content model
16311 * (xmlSchemaBuildAContentModel) ensures that the element
16312 * declaration (and not a reference to it) will be given.
16313 */
16314 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
16315 /*
16316 * This is paranoid coding ;-)... it should not
16317 * happen here any more.
16318 */
16319 xmlSchemaVCustomErr(ctxt,
16320 XML_SCHEMAV_INTERNAL,
16321 node, NULL,
16322 "Internal error: xmlSchemaValidateCallback, "
16323 "element declaration 'reference' encountered, "
16324 "but an element declaration was expected",
16325 NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016326 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016327 }
16328 xmlSchemaValidateElementByDeclaration(ctxt,
16329 (xmlSchemaElementPtr) type);
16330 break;
16331 }
16332 case XML_SCHEMA_TYPE_ANY:
16333 xmlSchemaValidateElementByWildcard(ctxt, type);
16334 break;
16335 default:
16336 break;
16337 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016338leave:
16339
16340#ifdef ELEM_INFO_ENABLED
16341 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016342#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016343 ctxt->type = oldtype;
16344 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016345}
Daniel Veillard4255d502002-04-16 15:50:10 +000016346
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016347static int
16348xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
16349 const xmlChar *value,
16350 xmlSchemaValPtr *val,
16351 xmlNodePtr node)
16352{
16353 int ret;
16354
16355 ret = xmlValidateQName(value, 1);
16356 if (ret != 0)
16357 return (ret);
16358
16359 {
16360 xmlChar *uri = NULL;
16361 xmlChar *local = NULL;
16362 xmlChar *prefix;
16363
16364 local = xmlSplitQName2(value, &prefix);
16365 if (prefix != NULL) {
16366 xmlNsPtr ns;
16367
16368 /*
16369 * TODO: Make this streamable.
16370 */
16371 if ((node == NULL) || (node->doc == NULL)) {
16372 xmlFree(prefix);
16373 xmlFree(local);
16374 return (3);
16375 }
16376
16377 ns = xmlSearchNs(node->doc, node, prefix);
16378 if (ns == NULL) {
16379 xmlFree(prefix);
16380 xmlFree(local);
16381 return (1);
16382 }
16383 }
16384 if (prefix != NULL) {
16385 if (xmlHashLookup2(vctxt->schema->notaDecl, local, uri) == NULL)
16386 ret = 1;
16387 } else if (xmlHashLookup2(vctxt->schema->notaDecl, value,
16388 NULL) == NULL)
16389 ret = 1;
16390
16391 if ((ret == 0) && (val != NULL)) {
16392 if (prefix != NULL) {
16393 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST local,
16394 BAD_CAST xmlStrdup(uri));
16395 local = NULL;
16396 } else
16397 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST xmlStrdup(value),
16398 NULL);
16399 if (*val == NULL)
16400 ret = -1;
16401 }
16402 if (local != NULL)
16403 xmlFree(local);
16404 }
16405
16406 return (ret);
16407}
16408
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016409static xmlSchemaTypePtr
16410xmlSchemaGetSimpleContentType(xmlSchemaTypePtr complexType)
16411{
16412 xmlSchemaTypePtr ret;
16413
16414 if (complexType->type != XML_SCHEMA_TYPE_COMPLEX)
16415 return (NULL);
16416 if (complexType->contentTypeDef != NULL)
16417 return (complexType->contentTypeDef);
16418 /*
16419 * TODO: This is only a workaround until the simple content
16420 * type is computed for complex types with simple content.
16421 */
16422 ret = complexType->baseType;
16423 while (ret != NULL) {
16424 if (IS_SIMPLE_TYPE(ret))
16425 return (ret);
16426 if (ret->builtInType == XML_SCHEMAS_ANYTYPE)
16427 return (NULL);
16428 if ((ret->type == XML_SCHEMA_TYPE_COMPLEX) &&
16429 (ret->contentTypeDef != NULL))
16430 ret = ret->contentTypeDef;
16431 else
16432 ret = ret->baseType;
16433 }
16434 return (ret);
16435}
16436
Daniel Veillard01fa6152004-06-29 17:04:39 +000016437/**
16438 * xmlSchemaValidateSimpleTypeValue:
16439 * @ctxt: a schema validation context
16440 * @value: the value to be validated
16441 * @fireErrors: shall errors be reported?
16442 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000016443 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016444 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000016445 *
16446 * Validates a value by the given type (user derived or built-in).
16447 *
16448 * Returns 0 if the value is valid, a positive error code
16449 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016450 */
16451static int
16452xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016453 xmlSchemaTypePtr type,
16454 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016455 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016456 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016457 int normalize,
16458 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016459{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016460 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016461 int ret = 0;
16462 xmlChar *normValue = NULL;
16463 int wtsp;
16464
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016465 node = ctxt->node;
16466 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016467 wtsp = ctxt->valueWS;
16468 /*
16469 * Normalize the value.
16470 */
16471 if (normalize &&
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016472 (ctxt->valueWS != XML_SCHEMAS_FACET_COLLAPSE)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016473 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
16474
16475 if ((norm != -1) && (norm > ctxt->valueWS)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016476 if (norm == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000016477 normValue = xmlSchemaCollapseString(value);
16478 else
16479 normValue = xmlSchemaWhiteSpaceReplace(value);
16480 ctxt->valueWS = norm;
16481 if (normValue != NULL)
16482 value = (const xmlChar *) normValue;
16483 }
16484 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016485 /*
16486 * The nodes of a content must be checked only once,
16487 * this is not working since list types will fire this
16488 * multiple times.
16489 */
16490 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
16491 xmlNodePtr cur = ctxt->cur;
16492
16493 do {
16494 switch (cur->type) {
16495 case XML_TEXT_NODE:
16496 case XML_CDATA_SECTION_NODE:
16497 case XML_PI_NODE:
16498 case XML_COMMENT_NODE:
16499 case XML_XINCLUDE_START:
16500 case XML_XINCLUDE_END:
16501 break;
16502 case XML_ENTITY_REF_NODE:
16503 case XML_ENTITY_NODE:
16504 /* TODO: Scour the entities for illegal nodes. */
16505 TODO break;
16506 case XML_ELEMENT_NODE: {
16507 /* NOTE: Changed to an internal error, since the
16508 * existence of an element node will be already checked in
16509 * xmlSchemaValidateElementBySimpleType and in
16510 * xmlSchemaValidateElementByComplexType.
16511 */
16512 xmlSchemaVCustomErr(ctxt,
16513 XML_SCHEMAV_INTERNAL,
16514 /* XML_SCHEMAS_ERR_INVALIDELEM, */
16515 node, type,
16516 "Element '%s' found in simple type content",
16517 cur->name);
16518 return (XML_SCHEMAV_INTERNAL);
16519 }
16520 case XML_ATTRIBUTE_NODE:
16521 case XML_DOCUMENT_NODE:
16522 case XML_DOCUMENT_TYPE_NODE:
16523 case XML_DOCUMENT_FRAG_NODE:
16524 case XML_NOTATION_NODE:
16525 case XML_HTML_DOCUMENT_NODE:
16526 case XML_DTD_NODE:
16527 case XML_ELEMENT_DECL:
16528 case XML_ATTRIBUTE_DECL:
16529 case XML_ENTITY_DECL:
16530 case XML_NAMESPACE_DECL:
16531#ifdef LIBXML_DOCB_ENABLED
16532 case XML_DOCB_DOCUMENT_NODE:
16533#endif
16534 xmlSchemaVCustomErr(ctxt,
16535 XML_SCHEMAV_INTERNAL,
16536 /* XML_SCHEMAS_ERR_INVALIDELEM, */
16537 node, NULL,
16538 "Node of unexpected type found in simple type content",
16539 NULL);
16540 return (XML_SCHEMAV_INTERNAL);
16541 }
16542 cur = cur->next;
16543 } while (cur != NULL);
16544 }
16545
William M. Brack2f2a6632004-08-20 23:09:47 +000016546 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016547 xmlSchemaTypePtr simpType, anyType;
William M. Brack2f2a6632004-08-20 23:09:47 +000016548
16549 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
16550
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016551 simpType = xmlSchemaGetSimpleContentType(type);
16552 if (simpType == NULL) {
16553 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
16554 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16555 "failed to obtain the simple content type of the complex "
16556 "type '%s'\n",
16557 type->name, NULL);
16558 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000016559 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016560 ret = xmlSchemaValidateSimpleTypeValue(ctxt, simpType, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016561 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016562 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016563 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16564 "validating complex type '%s'\n",
16565 type->name, NULL);
16566 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
16567 /*
16568 * Check facets.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016569 *
16570 * TODO: This is somehow not nice, since if an error occurs
William M. Brack2f2a6632004-08-20 23:09:47 +000016571 * the reported type will be the complex type; the spec
16572 * wants a simple type to be created on the complex type
16573 * if it has a simple content. For now we have to live with
16574 * it.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016575 */
16576 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016577 value, 0, fireErrors);
16578 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016579 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016580 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16581 "validating facets of complex type '%s'\n",
16582 type->name, NULL);
16583 } else if (ret > 0) {
16584 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000016585 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016586 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000016587 }
16588 }
16589 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016590
16591 if (ctxt->value != NULL) {
16592 xmlSchemaFreeValue(ctxt->value);
16593 ctxt->value = NULL;
16594 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016595 /*
16596 * STREAM-READ-CHILDREN.
16597 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016598 if ((type->builtInType == XML_SCHEMAS_NOTATION) &&
16599 (ctxt->schema != NULL)) {
16600 /*
16601 * NOTATIONs need to be processed here, since they need
16602 * to lookup in the hashtable of NOTATION declarations.
16603 */
16604 ret = xmlSchemaValidateNotation(ctxt, value, &(ctxt->value), node);
16605 } else
16606 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016607 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016608 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
16609 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
16610 else
16611 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016612 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016613 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016614 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016615 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016616 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016617 "validating built-in type '%s'\n", type->name, NULL);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016618 } else if ((ctxt->value == NULL) &&
16619 (type->builtInType == XML_SCHEMAS_STRING) &&
16620 (ctxt->nodeInfo != NULL) &&
16621 (ctxt->nodeInfo->flags & XML_SCHEMA_ELEM_INFO_VALUE_NEEDED)) {
16622#ifdef IDC_VALUE_SUPPORT
16623 xmlChar *valdup;
16624 /*
16625 * Create a precomputed string value for "string" as well if
16626 * requested.
16627 */
16628 valdup = xmlStrdup(value);
16629 ctxt->value = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
16630 BAD_CAST valdup);
16631 if ((valdup != NULL) && (ctxt->value == NULL))
16632 xmlFree(valdup);
16633#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000016634 }
16635 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
16636 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
16637 * a literal in the ·lexical space· of {base type definition}
16638 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016639 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016640 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016641 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016642 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016643 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016644 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016645 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016646 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016647 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016648 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016649 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016650 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016651 * Check facets.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016652 */
16653 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016654 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016655 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016656 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016657 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016658 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016659 type->name, NULL);
16660 } else if (ret > 0) {
16661 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016662 /*
16663 Disabled, since the facet validation already reports errors.
16664 if (fireErrors)
16665 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16666 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016667 }
16668 }
16669 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
16670
16671 xmlSchemaTypePtr tmpType;
16672 const xmlChar *cur, *end;
16673 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016674 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016675
16676 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
16677 * of white space separated tokens, each of which ·match·es a literal
16678 * in the ·lexical space· of {item type definition}
16679 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000016680
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000016681 if (value == NULL)
16682 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000016683 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016684 cur = value;
16685 do {
16686 while (IS_BLANK_CH(*cur))
16687 cur++;
16688 end = cur;
16689 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
16690 end++;
16691 if (end == cur)
16692 break;
16693 tmp = xmlStrndup(cur, end - cur);
16694 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016695 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016696 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016697 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016698 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016699 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16700 "validating an item of list simple type '%s'\n",
16701 type->name, NULL);
16702 break;
16703 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016704 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016705 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016706 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016707 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016708 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016709 cur = end;
16710 } while (*cur != 0);
16711 /*
16712 * Check facets.
16713 */
16714 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016715 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016716 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016717 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016718 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016719 } else if ((ret == 0) && (applyFacets)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016720 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016721 value, len, fireErrors);
16722 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016723 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016724 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16725 "validating facets of list simple type '%s'\n",
16726 type->name, NULL);
16727 } else if (ret > 0) {
16728 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016729 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016730 Disabled, since the facet validation already reports errors.
16731 if (fireErrors)
16732 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016733 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016734 }
16735
Daniel Veillard01fa6152004-06-29 17:04:39 +000016736 }
16737 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
16738 xmlSchemaTypeLinkPtr memberLink;
16739
16740 /*
16741 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
16742 * not apply directly; however, the normalization behavior of ·union·
16743 * types is controlled by the value of whiteSpace on that one of the
16744 * ·memberTypes· against which the ·union· is successfully validated.
16745 *
16746 * This means that the value is normalized by the first validating
16747 * member type, then the facets of the union type are applied. This
16748 * needs changing of the value!
16749 */
16750
16751 /*
16752 * 1.2.3 if {variety} is ·union· then the string must ·match· a
16753 * literal in the ·lexical space· of at least one member of
16754 * {member type definitions}
16755 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016756#ifdef DEBUG_UNION_VALIDATION
16757 printf("Union ST : '%s'\n", (const char *) type->name);
16758 printf(" fireErrors : %d\n", fireErrors);
16759 printf(" applyFacets: %d\n", applyFacets);
16760#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000016761 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
16762 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016763 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016764 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016765 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016766 type->name, NULL);
16767 ret = -1;
16768 }
16769 if (ret == 0) {
16770 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016771 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
16772 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016773 if ((ret <= 0) || (ret == 0))
16774 break;
16775 memberLink = memberLink->next;
16776 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016777 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016778 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016779 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016780 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016781 type->name, NULL);
16782 } else if (ret > 0) {
16783 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016784 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016785 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016786 }
16787 }
16788 /*
16789 * Apply facets (pattern, enumeration).
16790 */
16791 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
16792 int mws;
16793 /*
16794 * The normalization behavior of ·union· types is controlled by
16795 * the value of whiteSpace on that one of the ·memberTypes·
16796 * against which the ·union· is successfully validated.
16797 */
16798 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016799 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016800 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16801 "the value was already normalized for the union simple "
16802 "type '%s'.\n", type->name, NULL);
16803 }
16804 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
16805 if (mws > ctxt->valueWS) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016806 if (mws == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000016807 normValue = xmlSchemaCollapseString(value);
16808 else
16809 normValue = xmlSchemaWhiteSpaceReplace(value);
16810 if (normValue != NULL)
16811 value = (const xmlChar *) normValue;
16812 }
16813
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016814 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016815 value, 0, fireErrors);
16816 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016817 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016818 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16819 "validating facets of union simple type '%s'\n",
16820 type->name, NULL);
16821 } else if (ret > 0) {
16822 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
16823 /*
16824 if (fireErrors)
16825 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16826 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016827 }
16828 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016829 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016830 ctxt->valueWS = wtsp;
16831 if (normValue != NULL)
16832 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016833 return (ret);
16834}
16835
16836/**
16837 * xmlSchemaValidateSimpleTypeElement:
16838 * @ctxt: a schema validation context
16839 * @node: the element node to be validated.
16840 *
16841 * Validate the element against a simple type.
16842 *
16843 * Returns 0 if the element is valid, a positive error code
16844 * number otherwise and -1 in case of an internal or API error.
16845 */
16846static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016847xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016848 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016849 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016850 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016851{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016852 xmlSchemaTypePtr oldtype;
16853 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016854 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016855 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016856 int ret = 0, retval = 0;
16857
Daniel Veillard01fa6152004-06-29 17:04:39 +000016858 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016859 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16860 "Internal error: xmlSchemaValidateElementBySimpleType, "
16861 "bad arguments", NULL);
16862 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016863 }
16864
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016865 oldtype = ctxt->type;
16866 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016867 /*
16868 * cvc-type: 3.1.2 The element information item must have no element
16869 * information item [children].
16870 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016871 /*
16872 * STREAM: Child nodes are processed.
16873 */
16874 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016875 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016876 /*
16877 * TODO: Entities, will they produce elements as well?
16878 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016879 if (cur->type == XML_ELEMENT_NODE) {
16880 xmlSchemaVCustomErr(ctxt,
16881 XML_SCHEMAV_CVC_TYPE_3_1_2,
16882 node, type,
16883 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016884 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016885 }
16886 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016887 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016888
Daniel Veillard01fa6152004-06-29 17:04:39 +000016889 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016890 * cvc-type 3.1.1:
16891 *
16892 * The attributes of must be empty, excepting those whose namespace name
16893 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
16894 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016895 */
16896 /*
16897 * STREAM: Attribute nodes are processed.
16898 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016899 attr = node->properties;
16900 while (attr != NULL) {
16901 if ((attr->ns == NULL) ||
16902 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
16903 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
16904 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
16905 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
16906 (!xmlStrEqual
16907 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016908 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016909 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
16910 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016911 }
16912 attr = attr->next;
16913 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016914 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016915 * This will skip validation if the type is 'anySimpleType' and
16916 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016917 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016918 if ((! isNil) &&
16919 (valSimpleContent == 1) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016920 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
16921 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016922 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016923
16924 value = xmlNodeGetContent(node);
16925 /*
16926 * NOTE: This call will not check the content nodes, since
16927 * this should be checked here already.
16928 */
16929 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
16930 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016931 if (value != NULL)
16932 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016933 if (retval != 0)
16934 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000016935 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016936 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016937 return (ret);
16938}
Daniel Veillard4255d502002-04-16 15:50:10 +000016939
16940/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016941 * xmlSchemaValQNameAcquire:
16942 * @value: the lexical represantation of the QName value
16943 * @node: the node to search for the corresponding namespace declaration
16944 * @nsName: the resulting namespace name if found
16945 *
16946 * Checks that a value conforms to the lexical space of the type QName;
16947 * if valid, the corresponding namespace name is searched and retured
16948 * as a copy in @nsName. The local name is returned in @localName as
16949 * a copy.
16950 *
16951 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
16952 * namespace declaration was found in scope; -1 in case of an internal or
16953 * API error.
16954 */
16955static int
16956xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
16957 xmlChar **nsName, xmlChar **localName)
16958{
16959 int ret;
16960 xmlChar *local = NULL;
16961
16962 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
16963 return (-1);
16964 *nsName = NULL;
16965 *localName = NULL;
16966 ret = xmlValidateQName(value, 1);
16967 if (ret == 0) {
16968 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016969 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016970
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016971 /*
16972 * NOTE: xmlSplitQName2 will return a duplicated
16973 * string.
16974 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016975 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016976 if (local == NULL)
16977 local = xmlStrdup(value);
16978 ns = xmlSearchNs(node->doc, node, prefix);
16979 /*
16980 * A namespace need not to be found if the prefix is NULL.
16981 */
16982 if (ns != NULL) {
16983 /*
16984 * TODO: Is it necessary to duplicate the URI here?
16985 */
16986 *nsName = xmlStrdup(ns->href);
16987 } else if (prefix != NULL) {
16988 xmlFree(prefix);
16989 if (local != NULL)
16990 xmlFree(local);
16991 return (2);
16992 }
16993 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016994 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016995 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016996 } else
16997 return (1);
16998 return (ret);
16999}
17000
17001/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017002 * xmlSchemaHasElemContent:
17003 * @node: the node
17004 *
17005 * Scours the content of the given node for element
17006 * nodes.
17007 *
17008 * Returns 1 if an element node is found,
17009 * 0 otherwise.
17010 */
17011static int
17012xmlSchemaHasElemContent(xmlNodePtr node)
17013{
17014 if (node == NULL)
17015 return (0);
17016 node = node->children;
17017 while (node != NULL) {
17018 if (node->type == XML_ELEMENT_NODE)
17019 return (1);
17020 node = node->next;
17021 }
17022 return (0);
17023}
17024/**
17025 * xmlSchemaHasElemOrCharContent:
17026 * @node: the node
17027 *
17028 * Scours the content of the given node for element
17029 * and character nodes.
17030 *
17031 * Returns 1 if an element or character node is found,
17032 * 0 otherwise.
17033 */
17034static int
17035xmlSchemaHasElemOrCharContent(xmlNodePtr node)
17036{
17037 if (node == NULL)
17038 return (0);
17039 node = node->children;
17040 while (node != NULL) {
17041 switch (node->type) {
17042 case XML_ELEMENT_NODE:
17043 /*
17044 * TODO: Ask Daniel if these are all character nodes.
17045 */
17046 case XML_TEXT_NODE:
17047 case XML_CDATA_SECTION_NODE:
17048 /*
17049 * TODO: How XML_ENTITY_NODEs evaluated?
17050 */
17051 case XML_ENTITY_REF_NODE:
17052 case XML_ENTITY_NODE:
17053 return (1);
17054 break;
17055 default:
17056 break;
17057 }
17058 node = node->next;
17059 }
17060 return (0);
17061}
17062
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017063/************************************************************************
17064 * *
17065 * Identity-constraints (IDC) *
17066 * *
17067 ************************************************************************/
17068
17069#ifdef IDC_ENABLED
17070
17071/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017072 * xmlSchemaAugmentIDC:
17073 * @idcDef: the IDC definition
17074 *
17075 * Creates an augmented IDC definition item.
17076 *
17077 * Returns the item, or NULL on internal errors.
17078 */
17079static void
17080xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
17081 xmlSchemaValidCtxtPtr vctxt)
17082{
17083 xmlSchemaIDCAugPtr aidc;
17084
17085 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
17086 if (aidc == NULL) {
17087 xmlSchemaVErrMemory(vctxt,
17088 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
17089 NULL);
17090 return;
17091 }
17092 aidc->bubbleDepth = -1;
17093 aidc->def = idcDef;
17094 aidc->next = NULL;
17095 if (vctxt->aidcs == NULL)
17096 vctxt->aidcs = aidc;
17097 else {
17098 aidc->next = vctxt->aidcs;
17099 vctxt->aidcs = aidc;
17100 }
17101}
17102
17103/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017104 * xmlSchemaIDCNewBinding:
17105 * @idcDef: the IDC definition of this binding
17106 *
17107 * Creates a new IDC binding.
17108 *
17109 * Returns the new binding in case of succeeded, NULL on internal errors.
17110 */
17111static xmlSchemaPSVIIDCBindingPtr
17112xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
17113{
17114 xmlSchemaPSVIIDCBindingPtr ret;
17115
17116 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
17117 sizeof(xmlSchemaPSVIIDCBinding));
17118 if (ret == NULL) {
17119 xmlSchemaVErrMemory(NULL,
17120 "allocating a PSVI IDC binding item", NULL);
17121 return (NULL);
17122 }
17123 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
17124 ret->definition = idcDef;
17125 return (ret);
17126}
17127
17128/**
17129 * xmlSchemaIDCStoreNodeTableItem:
17130 * @vctxt: the WXS validation context
17131 * @item: the IDC node table item
17132 *
17133 * The validation context is used to store an IDC node table items.
17134 * They are stored to avoid copying them if IDC node-tables are merged
17135 * with corresponding parent IDC node-tables (bubbling).
17136 *
17137 * Returns 0 if succeeded, -1 on internal errors.
17138 */
17139static int
17140xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
17141 xmlSchemaPSVIIDCNodePtr item)
17142{
17143 /*
17144 * Add to gobal list.
17145 */
17146 if (vctxt->idcNodes == NULL) {
17147 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
17148 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
17149 if (vctxt->idcNodes == NULL) {
17150 xmlSchemaVErrMemory(vctxt,
17151 "allocating the IDC node table item list", NULL);
17152 return (-1);
17153 }
17154 vctxt->sizeIdcNodes = 20;
17155 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
17156 vctxt->sizeIdcNodes *= 2;
17157 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
17158 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
17159 sizeof(xmlSchemaPSVIIDCNodePtr));
17160 if (vctxt->idcNodes == NULL) {
17161 xmlSchemaVErrMemory(vctxt,
17162 "re-allocating the IDC node table item list", NULL);
17163 return (-1);
17164 }
17165 }
17166 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
17167
17168 return (0);
17169}
17170
17171/**
17172 * xmlSchemaIDCStoreKey:
17173 * @vctxt: the WXS validation context
17174 * @item: the IDC key
17175 *
17176 * The validation context is used to store an IDC key.
17177 *
17178 * Returns 0 if succeeded, -1 on internal errors.
17179 */
17180static int
17181xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
17182 xmlSchemaPSVIIDCKeyPtr key)
17183{
17184 /*
17185 * Add to gobal list.
17186 */
17187 if (vctxt->idcKeys == NULL) {
17188 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
17189 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
17190 if (vctxt->idcKeys == NULL) {
17191 xmlSchemaVErrMemory(vctxt,
17192 "allocating the IDC key storage list", NULL);
17193 return (-1);
17194 }
17195 vctxt->sizeIdcKeys = 40;
17196 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
17197 vctxt->sizeIdcKeys *= 2;
17198 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
17199 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
17200 sizeof(xmlSchemaPSVIIDCKeyPtr));
17201 if (vctxt->idcKeys == NULL) {
17202 xmlSchemaVErrMemory(vctxt,
17203 "re-allocating the IDC key storage list", NULL);
17204 return (-1);
17205 }
17206 }
17207 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
17208
17209 return (0);
17210}
17211
17212/**
17213 * xmlSchemaIDCAppendNodeTableItem:
17214 * @bind: the IDC binding
17215 * @ntItem: the node-table item
17216 *
17217 * Appends the IDC node-table item to the binding.
17218 *
17219 * Returns 0 on success and -1 on internal errors.
17220 */
17221static int
17222xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
17223 xmlSchemaPSVIIDCNodePtr ntItem)
17224{
17225 if (bind->nodeTable == NULL) {
17226 bind->sizeNodes = 10;
17227 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17228 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
17229 if (bind->nodeTable == NULL) {
17230 xmlSchemaVErrMemory(NULL,
17231 "allocating an array of IDC node-table items", NULL);
17232 return(-1);
17233 }
17234 } else if (bind->sizeNodes <= bind->nbNodes) {
17235 bind->sizeNodes *= 2;
17236 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17237 xmlRealloc(bind->nodeTable, bind->sizeNodes *
17238 sizeof(xmlSchemaPSVIIDCNodePtr));
17239 if (bind->nodeTable == NULL) {
17240 xmlSchemaVErrMemory(NULL,
17241 "re-allocating an array of IDC node-table items", NULL);
17242 return(-1);
17243 }
17244 }
17245 bind->nodeTable[bind->nbNodes++] = ntItem;
17246 return(0);
17247}
17248
17249/**
17250 * xmlSchemaIDCAquireBinding:
17251 * @vctxt: the WXS validation context
17252 * @matcher: the IDC matcher
17253 *
17254 * Looks up an PSVI IDC binding, for the IDC definition and
17255 * of the given matcher. If none found, a new one is created
17256 * and added to the IDC table.
17257 *
17258 * Returns an IDC binding or NULL on internal errors.
17259 */
17260static xmlSchemaPSVIIDCBindingPtr
17261xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
17262 xmlSchemaIDCMatcherPtr matcher)
17263{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017264 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017265
17266 info = vctxt->elemInfos[matcher->depth];
17267
17268 if (info->idcTable == NULL) {
17269 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
17270 if (info->idcTable == NULL)
17271 return (NULL);
17272 return(info->idcTable);
17273 } else {
17274 xmlSchemaPSVIIDCBindingPtr bind = NULL;
17275
17276 bind = info->idcTable;
17277 do {
17278 if (bind->definition == matcher->aidc->def)
17279 return(bind);
17280 if (bind->next == NULL) {
17281 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
17282 if (bind->next == NULL)
17283 return (NULL);
17284 return(bind->next);
17285 }
17286 bind = bind->next;
17287 } while (bind != NULL);
17288 }
17289 return (NULL);
17290}
17291
17292/**
17293 * xmlSchemaIDCFreeKey:
17294 * @key: the IDC key
17295 *
17296 * Frees an IDC key together with its compiled value.
17297 */
17298static void
17299xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
17300{
17301 if (key->compValue != NULL)
17302 xmlSchemaFreeValue(key->compValue);
17303 xmlFree(key);
17304}
17305
17306/**
17307 * xmlSchemaIDCFreeBinding:
17308 *
17309 * Frees an IDC binding. Note that the node table-items
17310 * are not freed.
17311 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017312static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017313xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
17314{
17315 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017316 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17317 int i;
17318 /*
17319 * Node-table items for keyrefs are not stored globally
17320 * to the validation context, since they are not bubbled.
17321 * We need to free them here.
17322 */
17323 for (i = 0; i < bind->nbNodes; i++) {
17324 xmlFree(bind->nodeTable[i]->keys);
17325 xmlFree(bind->nodeTable[i]);
17326 }
17327 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017328 xmlFree(bind->nodeTable);
17329 }
17330 xmlFree(bind);
17331}
17332
17333/**
17334 * xmlSchemaIDCFreeIDCTable:
17335 * @bind: the first IDC binding in the list
17336 *
17337 * Frees an IDC table, i.e. all the IDC bindings in the list.
17338 */
17339static void
17340xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
17341{
17342 xmlSchemaPSVIIDCBindingPtr prev;
17343
17344 while (bind != NULL) {
17345 prev = bind;
17346 bind = bind->next;
17347 xmlSchemaIDCFreeBinding(prev);
17348 }
17349}
17350
17351/**
17352 * xmlSchemaIDCFreeMatcherList:
17353 * @matcher: the first IDC matcher in the list
17354 *
17355 * Frees a list of IDC matchers.
17356 */
17357static void
17358xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
17359{
17360 xmlSchemaIDCMatcherPtr next;
17361
17362 while (matcher != NULL) {
17363 next = matcher->next;
17364 if (matcher->keySeqs != NULL) {
17365 int i;
17366 for (i = 0; i < matcher->sizeKeySeqs; i++)
17367 if (matcher->keySeqs[i] != NULL)
17368 xmlFree(matcher->keySeqs[i]);
17369 xmlFree(matcher->keySeqs);
17370 }
17371 xmlFree(matcher);
17372 matcher = next;
17373 }
17374}
17375
17376/**
17377 * xmlSchemaAreValuesEqual:
17378 * @ta: the first type
17379 * @a: the first value
17380 * @tb: the second type
17381 * @b: the second value
17382 *
17383 * Compares two values.
17384 *
17385 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
17386 */
17387static int
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017388xmlSchemaAreValuesEqual(xmlSchemaValidCtxtPtr vctxt,
17389 xmlSchemaTypePtr ta,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017390 xmlSchemaValPtr a,
17391 xmlSchemaTypePtr tb,
17392 xmlSchemaValPtr b)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017393{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017394 /* Same user derived/built-in derived/built-in primitive types. */
17395 if (ta == tb)
17396 goto compareValue;
17397
17398 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017399 * Note that comparison with anySimpleTypes with be supported for
17400 * string based types as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017401 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017402#if 0
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017403 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
17404 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
17405 return(0);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017406#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017407
17408 /*
17409 * 4.2.1 equal (data-types)
17410 *
17411 * the ·value space·s of all ·primitive· datatypes are disjoint
17412 * (they do not share any values)
17413 */
17414 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
17415 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
17416 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
17417 return(0);
17418
17419 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
17420 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
17421 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
17422 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
17423 TODO
17424 return(0);
17425 }
17426 /*
17427 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
17428 * T then the ·value space· of T' is a subset of the ·value space· of T.
17429 */
17430 /*
17431 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
17432 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
17433 */
17434
17435 {
17436 xmlSchemaTypePtr pta = ta, ptb = tb;
17437
17438 /* Note that we will compare the primitives here. */
17439 while ((pta->builtInType == 0) ||
17440 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
17441 pta = pta->baseType;
17442 while ((ptb->builtInType == 0) ||
17443 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
17444 ptb = ptb->baseType;
17445 if (pta == ptb)
17446 goto compareValue;
17447 return(0);
17448 }
17449compareValue:
17450 {
17451#ifdef IDC_VALUE_SUPPORT
17452 int ret;
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017453 int aws, bws;
17454
17455 aws = xmlSchemaGetWhiteSpaceFacetValue(ta);
17456 bws = xmlSchemaGetWhiteSpaceFacetValue(tb);
17457
17458 ret = xmlSchemaCompareValuesWhtsp(
17459 a, (xmlSchemaWhitespaceValueType) aws,
17460 b, (xmlSchemaWhitespaceValueType) bws);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017461 if (ret == 0)
17462 return(1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017463 else if (ret == -2) {
17464 xmlSchemaVErr(vctxt, vctxt->node,
17465 XML_SCHEMAV_INTERNAL,
17466 "Internal error: xmlSchemaAreValuesEqual, "
17467 "failed to compare the values.\n",
17468 NULL, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017469 return(-1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017470 } else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017471 return(0);
17472#else
17473 return (1);
17474#endif
17475 }
17476}
17477
17478/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017479 * xmlSchemaIDCAddStateObject:
17480 * @vctxt: the WXS validation context
17481 * @matcher: the IDC matcher
17482 * @sel: the XPath information
17483 * @parent: the parent "selector" state object if any
17484 * @type: "selector" or "field"
17485 *
17486 * Creates/reuses and activates state objects for the given
17487 * XPath information; if the XPath expression consists of unions,
17488 * multiple state objects are created for every unioned expression.
17489 *
17490 * Returns 0 on success and -1 on internal errors.
17491 */
17492static int
17493xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
17494 xmlSchemaIDCMatcherPtr matcher,
17495 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017496 int type)
17497{
17498 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017499
17500 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017501 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017502 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017503 if (vctxt->xpathStatePool != NULL) {
17504 sto = vctxt->xpathStatePool;
17505 vctxt->xpathStatePool = sto->next;
17506 sto->next = NULL;
17507 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017508 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017509 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017510 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017511 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
17512 if (sto == NULL) {
17513 xmlSchemaVErrMemory(NULL,
17514 "allocating an IDC state object", NULL);
17515 return (-1);
17516 }
17517 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
17518 }
17519 /*
17520 * Add to global list.
17521 */
17522 if (vctxt->xpathStates != NULL)
17523 sto->next = vctxt->xpathStates;
17524 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017525
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017526 /*
17527 * Free the old xpath validation context.
17528 */
17529 if (sto->xpathCtxt != NULL)
17530 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
17531
17532 /*
17533 * Create a new XPath (pattern) validation context.
17534 */
17535 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
17536 (xmlPatternPtr) sel->xpathComp);
17537 if (sto->xpathCtxt == NULL) {
17538 xmlSchemaVErr(vctxt, vctxt->node,
17539 XML_SCHEMAV_INTERNAL,
17540 "Internal error: xmlSchemaIDCAddStateObject, "
17541 "failed to create the XPath validation context.\n",
17542 NULL, NULL);
17543 return (-1);
17544 }
17545 sto->type = type;
17546 sto->depth = vctxt->depth;
17547 sto->matcher = matcher;
17548 sto->sel = sel;
17549 sto->nbHistory = 0;
17550
17551#if DEBUG_IDC
17552 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
17553 sto->sel->xpath);
17554#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017555 return (0);
17556}
17557
17558/**
17559 * xmlSchemaXPathEvaluate:
17560 * @vctxt: the WXS validation context
17561 * @nodeType: the nodeType of the current node
17562 *
17563 * Evaluates all active XPath state objects.
17564 *
17565 * Returns the number of IC "field" state objects which resolved to
17566 * this node, 0 if none resolved and -1 on internal errors.
17567 */
17568static int
17569xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017570 xmlElementType nodeType)
17571{
17572 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017573 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017574
17575 if (vctxt->xpathStates == NULL)
17576 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017577
17578 if (nodeType == XML_ATTRIBUTE_NODE)
17579 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017580#if DEBUG_IDC
17581 {
17582 xmlChar *str = NULL;
17583 xmlGenericError(xmlGenericErrorContext,
17584 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017585 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17586 vctxt->nodeInfo->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017587 FREE_AND_NULL(str)
17588 }
17589#endif
17590 /*
17591 * Process all active XPath state objects.
17592 */
17593 first = vctxt->xpathStates;
17594 sto = first;
17595 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017596#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017597 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017598 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
17599 sto->matcher->aidc->def->name, sto->sel->xpath);
17600 else
17601 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
17602 sto->matcher->aidc->def->name, sto->sel->xpath);
17603#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017604
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017605#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017606 if (nodeType == XML_ELEMENT_NODE)
17607 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
17608 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
17609 else
17610 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
17611 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
17612
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017613#else
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017614 res = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017615#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017616 if (res == -1) {
17617 xmlSchemaVErr(vctxt, vctxt->node,
17618 XML_SCHEMAV_INTERNAL,
17619 "Internal error: xmlSchemaXPathEvaluate, "
17620 "failed to evaluate a node.\n",
17621 NULL, NULL);
17622 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017623 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017624 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017625 goto next_sto;
17626 /*
17627 * Full match.
17628 */
17629#if DEBUG_IDC
17630 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017631 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017632#endif
17633 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017634 * Register a match in the state object history.
17635 */
17636 if (sto->history == NULL) {
17637 sto->history = (int *) xmlMalloc(5 * sizeof(int));
17638 if (sto->history == NULL) {
17639 xmlSchemaVErrMemory(NULL,
17640 "allocating the state object history", NULL);
17641 return(-1);
17642 }
17643 sto->sizeHistory = 10;
17644 } else if (sto->sizeHistory <= sto->nbHistory) {
17645 sto->sizeHistory *= 2;
17646 sto->history = (int *) xmlRealloc(sto->history,
17647 sto->sizeHistory * sizeof(int));
17648 if (sto->history == NULL) {
17649 xmlSchemaVErrMemory(NULL,
17650 "re-allocating the state object history", NULL);
17651 return(-1);
17652 }
17653 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017654 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017655
17656#ifdef DEBUG_IDC
17657 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
17658 vctxt->depth);
17659#endif
17660
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017661 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
17662 xmlSchemaIDCSelectPtr sel;
17663 /*
17664 * Activate state objects for the IDC fields of
17665 * the IDC selector.
17666 */
17667#if DEBUG_IDC
17668 xmlGenericError(xmlGenericErrorContext, "IDC: "
17669 "activating field states\n");
17670#endif
17671 sel = sto->matcher->aidc->def->fields;
17672 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017673 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
17674 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
17675 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017676 sel = sel->next;
17677 }
17678 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
17679 /*
17680 * An IDC key node was found.
17681 */
17682#if DEBUG_IDC
17683 xmlGenericError(xmlGenericErrorContext,
17684 "IDC: key found\n");
17685#endif
17686 /*
17687 * Notify that the character value of this node is
17688 * needed.
17689 */
17690 if (resolved == 0)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017691 vctxt->nodeInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017692 resolved++;
17693 }
17694next_sto:
17695 if (sto->next == NULL) {
17696 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017697 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017698 */
17699 head = first;
17700 sto = vctxt->xpathStates;
17701 } else
17702 sto = sto->next;
17703 }
17704 return (resolved);
17705}
17706
17707/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017708 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017709 * @vctxt: the WXS validation context
17710 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017711 * @compValue: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017712 *
17713 * Processes and pops the history items of the IDC state objects.
17714 * IDC key-sequences are validated/created on IDC bindings.
17715 *
17716 * Returns 0 on success and -1 on internal errors.
17717 */
17718static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017719xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017720 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017721{
17722 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017723 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017724 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017725 xmlSchemaTypePtr type = vctxt->nodeInfo->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017726
17727 if (vctxt->xpathStates == NULL)
17728 return (0);
17729 sto = vctxt->xpathStates;
17730
17731#if DEBUG_IDC
17732 {
17733 xmlChar *str = NULL;
17734 xmlGenericError(xmlGenericErrorContext,
17735 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017736 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17737 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017738 FREE_AND_NULL(str)
17739 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017740#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017741 /*
17742 * Evaluate the state objects.
17743 */
17744 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017745#ifdef IDC_XPATH_SUPPORT
17746 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
17747 #if DEBUG_IDC
17748 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
17749 sto->sel->xpath);
17750 #endif
17751#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017752 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017753 goto deregister_check;
17754
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017755 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017756
17757 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017758 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017759 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017760 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017761 sto = sto->next;
17762 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017763 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017764 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
17765 if (! IS_SIMPLE_TYPE(type)) {
17766 /*
17767 * Not qualified if the field resolves to a node of non
17768 * simple type.
17769 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017770 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017771 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017772 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017773 (xmlSchemaTypePtr) sto->matcher->aidc->def,
17774 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017775 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017776
17777 sto->nbHistory--;
17778 goto deregister_check;
17779 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017780 if ((key == NULL) && (vctxt->nodeInfo->value == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017781 /*
17782 * Failed to provide the normalized value; maby
17783 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017784 */
17785 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017786 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017787 vctxt->nodeInfo,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017788 (xmlSchemaTypePtr) sto->matcher->aidc->def,
17789 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017790 "was either invalid or something strange happend",
17791 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017792 /*
17793 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017794 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017795 "Internal error: xmlSchemaXPathProcessHistory, "
17796 "computed value not available.\n",
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017797 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017798 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017799 sto->nbHistory--;
17800 goto deregister_check;
17801 } else {
17802 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
17803 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017804 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017805
17806 /*
17807 * The key will be anchored on the matcher's list of
17808 * key-sequences. The position in this list is determined
17809 * by the target node's depth relative to the matcher's
17810 * depth of creation (i.e. the depth of the scope element).
17811 */
17812 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017813 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017814
17815 /*
17816 * Create/grow the array of key-sequences.
17817 */
17818 if (matcher->keySeqs == NULL) {
17819 if (pos > 9)
17820 matcher->sizeKeySeqs = pos * 2;
17821 else
17822 matcher->sizeKeySeqs = 10;
17823 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17824 xmlMalloc(matcher->sizeKeySeqs *
17825 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17826 if (matcher->keySeqs == NULL) {
17827 xmlSchemaVErrMemory(NULL,
17828 "allocating an array of key-sequences",
17829 NULL);
17830 return(-1);
17831 }
17832 memset(matcher->keySeqs, 0,
17833 matcher->sizeKeySeqs *
17834 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17835 } else if (pos >= matcher->sizeKeySeqs) {
17836 int i = matcher->sizeKeySeqs;
17837
17838 matcher->sizeKeySeqs *= 2;
17839 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17840 xmlRealloc(matcher->keySeqs,
17841 matcher->sizeKeySeqs *
17842 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017843 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017844 xmlSchemaVErrMemory(NULL,
17845 "reallocating an array of key-sequences",
17846 NULL);
17847 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017848 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017849 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017850 * The array needs to be NULLed.
17851 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017852 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017853 for (; i < matcher->sizeKeySeqs; i++)
17854 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017855 }
17856
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017857 /*
17858 * Get/create the key-sequence.
17859 */
17860 keySeq = matcher->keySeqs[pos];
17861 if (keySeq == NULL) {
17862 goto create_sequence;
17863 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017864 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017865 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017866 * cvc-identity-constraint:
17867 * 3 For each node in the ·target node set· all
17868 * of the {fields}, with that node as the context
17869 * node, evaluate to either an empty node-set or
17870 * a node-set with exactly one member, which must
17871 * have a simple type.
17872 *
17873 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017874 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017875 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017876 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017877 vctxt->nodeInfo,
17878 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017879 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017880 "with more than one member",
17881 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017882 sto->nbHistory--;
17883 goto deregister_check;
17884 } else {
17885 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017886 }
17887 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017888
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017889create_sequence:
17890 /*
17891 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017892 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017893 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
17894 matcher->aidc->def->nbFields *
17895 sizeof(xmlSchemaPSVIIDCKeyPtr));
17896 if (keySeq == NULL) {
17897 xmlSchemaVErrMemory(NULL,
17898 "allocating an IDC key-sequence", NULL);
17899 return(-1);
17900 }
17901 memset(keySeq, 0, matcher->aidc->def->nbFields *
17902 sizeof(xmlSchemaPSVIIDCKeyPtr));
17903 matcher->keySeqs[pos] = keySeq;
17904create_key:
17905 /*
17906 * Created a key once per node only.
17907 */
17908 if (key == NULL) {
17909 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
17910 sizeof(xmlSchemaPSVIIDCKey));
17911 if (key == NULL) {
17912 xmlSchemaVErrMemory(NULL,
17913 "allocating a IDC key", NULL);
17914 xmlFree(keySeq);
17915 matcher->keySeqs[pos] = NULL;
17916 return(-1);
17917 }
17918 /*
17919 * Consume the compiled value.
17920 */
17921 key->type = type;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017922 key->compValue = vctxt->nodeInfo->value;
17923 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017924 /*
17925 * Store the key in a global list.
17926 */
17927 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
17928 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017929 return (-1);
17930 }
17931 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017932 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017933 }
17934 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017935
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017936 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
17937 xmlSchemaPSVIIDCBindingPtr bind;
17938 xmlSchemaPSVIIDCNodePtr ntItem;
17939 xmlSchemaIDCMatcherPtr matcher;
17940 xmlSchemaIDCPtr idc;
17941 int pos, i, j, nbKeys;
17942 /*
17943 * Here we have the following scenario:
17944 * An IDC 'selector' state object resolved to a target node,
17945 * during the time this target node was in the
17946 * ancestor-or-self axis, the 'field' state object(s) looked
17947 * out for matching nodes to create a key-sequence for this
17948 * target node. Now we are back to this target node and need
17949 * to put the key-sequence, together with the target node
17950 * itself, into the node-table of the corresponding IDC
17951 * binding.
17952 */
17953 matcher = sto->matcher;
17954 idc = matcher->aidc->def;
17955 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017956 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017957 /*
17958 * Check if the matcher has any key-sequences at all, plus
17959 * if it has a key-sequence for the current target node.
17960 */
17961 if ((matcher->keySeqs == NULL) ||
17962 (matcher->sizeKeySeqs <= pos)) {
17963 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17964 goto selector_key_error;
17965 else
17966 goto selector_leave;
17967 }
17968
17969 keySeq = &(matcher->keySeqs[pos]);
17970 if (*keySeq == NULL) {
17971 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17972 goto selector_key_error;
17973 else
17974 goto selector_leave;
17975 }
17976
17977 for (i = 0; i < nbKeys; i++) {
17978 if ((*keySeq)[i] == NULL) {
17979 /*
17980 * Not qualified, if not all fields did resolve.
17981 */
17982 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
17983 /*
17984 * All fields of a "key" IDC must resolve.
17985 */
17986 goto selector_key_error;
17987 }
17988 goto selector_leave;
17989 }
17990 }
17991 /*
17992 * All fields did resolve.
17993 */
17994
17995 /*
17996 * 4.1 If the {identity-constraint category} is unique(/key),
17997 * then no two members of the ·qualified node set· have
17998 * ·key-sequences· whose members are pairwise equal, as
17999 * defined by Equal in [XML Schemas: Datatypes].
18000 *
18001 * Get the IDC binding from the matcher and check for
18002 * duplicate key-sequences.
18003 */
18004 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
18005 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
18006 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018007 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018008
18009 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018010 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018011 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018012 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018013 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018014 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018015 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018016 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018017 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018018 bkey = bkeySeq[j];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018019 res = xmlSchemaAreValuesEqual(vctxt, ckey->type,
18020 ckey->compValue, bkey->type, bkey->compValue);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018021 if (res == -1) {
18022 return (-1);
18023 } else if (res == 0)
18024 break;
18025 }
18026 if (res == 1) {
18027 /*
18028 * Duplicate found.
18029 */
18030 break;
18031 }
18032 i++;
18033 } while (i < bind->nbNodes);
18034 if (i != bind->nbNodes) {
18035 /*
18036 * TODO: Try to report the key-sequence.
18037 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018038 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018039 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018040 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018041 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018042 "Duplicate key-sequence found", NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018043
18044 goto selector_leave;
18045 }
18046 }
18047 /*
18048 * Add a node-table item to the IDC binding.
18049 */
18050 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
18051 sizeof(xmlSchemaPSVIIDCNode));
18052 if (ntItem == NULL) {
18053 xmlSchemaVErrMemory(NULL,
18054 "allocating an IDC node-table item", NULL);
18055 xmlFree(*keySeq);
18056 *keySeq = NULL;
18057 return(-1);
18058 }
18059 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
18060
18061 /*
18062 * Store the node-table item on global list.
18063 */
18064 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
18065 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
18066 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018067 xmlFree(*keySeq);
18068 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018069 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018070 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018071 }
18072 /*
18073 * Init the node-table item. Consume the key-sequence.
18074 */
18075 ntItem->node = vctxt->node;
18076 ntItem->keys = *keySeq;
18077 *keySeq = NULL;
18078 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
18079 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18080 /*
18081 * Free the item, since keyref items won't be
18082 * put on a global list.
18083 */
18084 xmlFree(ntItem->keys);
18085 xmlFree(ntItem);
18086 }
18087 return (-1);
18088 }
18089
18090 goto selector_leave;
18091selector_key_error:
18092 /*
18093 * 4.2.1 (KEY) The ·target node set· and the
18094 * ·qualified node set· are equal, that is, every
18095 * member of the ·target node set· is also a member
18096 * of the ·qualified node set· and vice versa.
18097 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018098 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018099 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018100 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018101 (xmlSchemaTypePtr) idc,
18102 "All 'key' fields must evaluate to a node",
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018103 NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018104selector_leave:
18105 /*
18106 * Free the key-sequence if not added to the IDC table.
18107 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018108 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018109 xmlFree(*keySeq);
18110 *keySeq = NULL;
18111 }
18112 } /* if selector */
18113
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018114 sto->nbHistory--;
18115
18116deregister_check:
18117 /*
18118 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018119 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018120 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018121#if DEBUG_IDC
18122 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
18123 sto->sel->xpath);
18124#endif
18125 if (vctxt->xpathStates != sto) {
18126 xmlSchemaVErr(vctxt, vctxt->node,
18127 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018128 "Internal error: xmlSchemaXPathProcessHistory, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018129 "The state object to be removed is not the first "
18130 "in the list.\n",
18131 NULL, NULL);
18132 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018133 nextsto = sto->next;
18134 /*
18135 * Unlink from the list of active XPath state objects.
18136 */
18137 vctxt->xpathStates = sto->next;
18138 sto->next = vctxt->xpathStatePool;
18139 /*
18140 * Link it to the pool of reusable state objects.
18141 */
18142 vctxt->xpathStatePool = sto;
18143 sto = nextsto;
18144 } else
18145 sto = sto->next;
18146 } /* while (sto != NULL) */
18147 return (0);
18148}
18149
18150/**
18151 * xmlSchemaIDCRegisterMatchers:
18152 * @vctxt: the WXS validation context
18153 * @elemDecl: the element declaration
18154 *
18155 * Creates helper objects to evaluate IDC selectors/fields
18156 * successively.
18157 *
18158 * Returns 0 if OK and -1 on internal errors.
18159 */
18160static int
18161xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
18162 xmlSchemaElementPtr elemDecl)
18163{
18164 xmlSchemaIDCMatcherPtr matcher, last = NULL;
18165 xmlSchemaIDCPtr idc, refIdc;
18166 xmlSchemaIDCAugPtr aidc;
18167
18168 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
18169 if (idc == NULL)
18170 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018171
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018172#if DEBUG_IDC
18173 {
18174 xmlChar *str = NULL;
18175 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018176 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018177 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
18178 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018179 FREE_AND_NULL(str)
18180 }
18181#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018182 if (vctxt->nodeInfo->idcMatchers != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018183 xmlSchemaVErr(vctxt, vctxt->node,
18184 XML_SCHEMAV_INTERNAL,
18185 "Internal error: xmlSchemaIDCRegisterMatchers: "
18186 "The chain of IDC matchers is expected to be empty.\n",
18187 NULL, NULL);
18188 return (-1);
18189 }
18190 do {
18191 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18192 /*
18193 * Since IDCs bubbles are expensive we need to know the
18194 * depth at which the bubbles should stop; this will be
18195 * the depth of the top-most keyref IDC. If no keyref
18196 * references a key/unique IDC, the bubbleDepth will
18197 * be -1, indicating that no bubbles are needed.
18198 */
18199 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
18200 if (refIdc != NULL) {
18201 /*
18202 * Lookup the augmented IDC.
18203 */
18204 aidc = vctxt->aidcs;
18205 while (aidc != NULL) {
18206 if (aidc->def == refIdc)
18207 break;
18208 aidc = aidc->next;
18209 }
18210 if (aidc == NULL) {
18211 xmlSchemaVErr(vctxt, vctxt->node,
18212 XML_SCHEMAV_INTERNAL,
18213 "Internal error: xmlSchemaIDCRegisterMatchers: "
18214 "Could not find an augmented IDC item for an IDC "
18215 "definition.\n",
18216 NULL, NULL);
18217 return (-1);
18218 }
18219 if ((aidc->bubbleDepth == -1) ||
18220 (vctxt->depth < aidc->bubbleDepth))
18221 aidc->bubbleDepth = vctxt->depth;
18222 }
18223 }
18224 /*
18225 * Lookup the augmented IDC item for the IDC definition.
18226 */
18227 aidc = vctxt->aidcs;
18228 while (aidc != NULL) {
18229 if (aidc->def == idc)
18230 break;
18231 aidc = aidc->next;
18232 }
18233 if (aidc == NULL) {
18234 xmlSchemaVErr(vctxt, vctxt->node,
18235 XML_SCHEMAV_INTERNAL,
18236 "Internal error: xmlSchemaIDCRegisterMatchers: "
18237 "Could not find an augmented IDC item for an IDC definition.\n",
18238 NULL, NULL);
18239 return (-1);
18240 }
18241 /*
18242 * Create an IDC matcher for every IDC definition.
18243 */
18244 matcher = (xmlSchemaIDCMatcherPtr)
18245 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
18246 if (matcher == NULL) {
18247 xmlSchemaVErrMemory(vctxt,
18248 "allocating an IDC matcher", NULL);
18249 return (-1);
18250 }
18251 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
18252 if (last == NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018253 vctxt->nodeInfo->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018254 else
18255 last->next = matcher;
18256 last = matcher;
18257
18258 matcher->type = IDC_MATCHER;
18259 matcher->depth = vctxt->depth;
18260 matcher->aidc = aidc;
18261#if DEBUG_IDC
18262 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
18263#endif
18264 /*
18265 * Init the automaton state object.
18266 */
18267 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018268 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018269 return (-1);
18270
18271 idc = idc->next;
18272 } while (idc != NULL);
18273 return (0);
18274}
18275
18276/**
18277 * xmlSchemaBubbleIDCNodeTables:
18278 * @depth: the current tree depth
18279 *
18280 * Merges IDC bindings of an element at @depth into the corresponding IDC
18281 * bindings of its parent element. If a duplicate note-table entry is found,
18282 * both, the parent node-table entry and child entry are discarded from the
18283 * node-table of the parent.
18284 *
18285 * Returns 0 if OK and -1 on internal errors.
18286 */
18287static int
18288xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
18289{
18290 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018291 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
18292 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018293 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
18294 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018295 int i, j, k, ret = 0, oldNum, newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018296 int duplTop;
18297
18298 /*
18299 * The node table has the following sections:
18300 *
18301 * O --> old node-table entries (first)
18302 * O
18303 * + --> new node-table entries
18304 * +
18305 * % --> new duplicate node-table entries
18306 * %
18307 * # --> old duplicate node-table entries
18308 * # (last)
18309 *
18310 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018311 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018312 if (bind == NULL) {
18313 /* Fine, no table, no bubbles. */
18314 return (0);
18315 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018316
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018317 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
18318 /*
18319 * Walk all bindings; create new or add to existing bindings.
18320 * Remove duplicate key-sequences.
18321 */
18322start_binding:
18323 while (bind != NULL) {
18324 /*
18325 * Skip keyref IDCs.
18326 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018327 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18328 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018329 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018330 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018331 /*
18332 * Check if the key/unique IDC table needs to be bubbled.
18333 */
18334 aidc = vctxt->aidcs;
18335 do {
18336 if (aidc->def == bind->definition) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018337 if (aidc->bubbleDepth >= vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018338 bind = bind->next;
18339 goto start_binding;
18340 }
18341 break;
18342 }
18343 aidc = aidc->next;
18344 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018345
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018346 if (parTable != NULL)
18347 parBind = *parTable;
18348 while (parBind != NULL) {
18349 /*
18350 * Search a matching parent binding for the
18351 * IDC definition.
18352 */
18353 if (parBind->definition == bind->definition) {
18354
18355 /*
18356 * Compare every node-table entry of the child node,
18357 * i.e. the key-sequence within, ...
18358 */
18359 oldNum = parBind->nbNodes; /* Skip newly added items. */
18360 duplTop = oldNum + parBind->nbDupls;
18361
18362 for (i = 0; i < bind->nbNodes; i++) {
18363 node = bind->nodeTable[i];
18364 if (node == NULL)
18365 continue;
18366 /*
18367 * ...with every key-sequence of the parent node, already
18368 * evaluated to be a duplicate key-sequence.
18369 */
18370 if (parBind->nbDupls != 0) {
18371 j = bind->nbNodes + newDupls;
18372 while (j < duplTop) {
18373 parNode = parBind->nodeTable[j];
18374 for (k = 0; k < bind->definition->nbFields; k++) {
18375 key = node->keys[k];
18376 parKey = parNode->keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018377 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018378 key->compValue,
18379 parKey->type, parKey->compValue);
18380 if (ret == -1) {
18381 /* TODO: Internal error */
18382 return(-1);
18383 } else if (ret == 0)
18384 break;
18385
18386 }
18387 if (ret == 1)
18388 /* Duplicate found. */
18389 break;
18390 j++;
18391 }
18392 if (j != duplTop) {
18393 /* Duplicate found. */
18394 continue;
18395 }
18396 }
18397 /*
18398 * ... and with every key-sequence of the parent node.
18399 */
18400 j = 0;
18401 while (j < oldNum) {
18402 parNode = parBind->nodeTable[j];
18403 /*
18404 * Compare key by key.
18405 */
18406 for (k = 0; k < parBind->definition->nbFields; k++) {
18407 key = node->keys[k];
18408 parKey = parNode->keys[k];
18409
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018410 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018411 key->compValue,
18412 parKey->type, parKey->compValue);
18413 if (ret == -1) {
18414 /* TODO: Internal error */
18415 } else if (ret == 0)
18416 break;
18417
18418 }
18419 if (ret == 1)
18420 /*
18421 * The key-sequences are equal.
18422 */
18423 break;
18424 j++;
18425 }
18426 if (j != oldNum) {
18427 /*
18428 * Handle duplicates.
18429 */
18430 newDupls++;
18431 oldNum--;
18432 parBind->nbNodes--;
18433 /*
18434 * Move last old item to pos of duplicate.
18435 */
18436 parBind->nodeTable[j] =
18437 parBind->nodeTable[oldNum];
18438
18439 if (parBind->nbNodes != oldNum) {
18440 /*
18441 * If new items exist, move last new item to
18442 * last of old items.
18443 */
18444 parBind->nodeTable[oldNum] =
18445 parBind->nodeTable[parBind->nbNodes];
18446 }
18447 /*
18448 * Move duplicate to last pos of new/old items.
18449 */
18450 parBind->nodeTable[parBind->nbNodes] = parNode;
18451
18452 } else {
18453 /*
18454 * Add the node-table entry (node and key-sequence) of
18455 * the child node to the node table of the parent node.
18456 */
18457 if (parBind->nodeTable == NULL) {
18458 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18459 xmlMalloc(1 * sizeof(xmlSchemaPSVIIDCNodePtr));
18460 if (parBind->nodeTable == NULL) {
18461 xmlSchemaVErrMemory(NULL,
18462 "allocating IDC list of node-table items", NULL);
18463 return(-1);
18464 }
18465 parBind->sizeNodes = 1;
18466 } else if (duplTop >= parBind->sizeNodes) {
18467 parBind->sizeNodes++;
18468 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18469 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
18470 sizeof(xmlSchemaPSVIIDCNodePtr));
18471 if (parBind->nodeTable == NULL) {
18472 xmlSchemaVErrMemory(NULL,
18473 "re-allocating IDC list of node-table items", NULL);
18474 return(-1);
18475 }
18476 }
18477
18478 /*
18479 * Move first old duplicate to last position
18480 * of old duplicates +1.
18481 */
18482 if (parBind->nbDupls != 0) {
18483 parBind->nodeTable[duplTop] =
18484 parBind->nodeTable[parBind->nbNodes + newDupls];
18485 }
18486 /*
18487 * Move first new duplicate to last position of
18488 * new duplicates +1.
18489 */
18490 if (newDupls != 0) {
18491 parBind->nodeTable[parBind->nbNodes + newDupls] =
18492 parBind->nodeTable[parBind->nbNodes];
18493 }
18494 /*
18495 * Append the new node-table entry to the 'new node-table
18496 * entries' section.
18497 */
18498 parBind->nodeTable[parBind->nbNodes] = node;
18499 parBind->nbNodes++;
18500 duplTop++;
18501 }
18502 }
18503 parBind->nbDupls += newDupls;
18504 break;
18505 }
18506 if (parBind->next == NULL)
18507 lastParBind = parBind;
18508 parBind = parBind->next;
18509 }
18510 if (parBind == NULL) {
18511 /*
18512 * No binding for the IDC was found: create a new one and
18513 * copy all node-tables.
18514 */
18515 parBind = xmlSchemaIDCNewBinding(bind->definition);
18516 if (parBind == NULL)
18517 return(-1);
18518
18519 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18520 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
18521 if (parBind->nodeTable == NULL) {
18522 xmlSchemaVErrMemory(NULL,
18523 "allocating an array of IDC node-table items", NULL);
18524 xmlSchemaIDCFreeBinding(parBind);
18525 return(-1);
18526 }
18527 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018528 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018529 memcpy(parBind->nodeTable, bind->nodeTable,
18530 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018531 if (*parTable == NULL)
18532 *parTable = parBind;
18533 else
18534 lastParBind->next = parBind;
18535 }
18536 bind = bind->next;
18537 }
18538 return (0);
18539}
18540
18541/**
18542 * xmlSchemaCheckCVCIDCKeyRef:
18543 * @vctxt: the WXS validation context
18544 * @elemDecl: the element declaration
18545 *
18546 * Check the cvc-idc-keyref constraints.
18547 */
18548static int
18549xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
18550{
18551 xmlSchemaPSVIIDCBindingPtr refbind, bind;
18552
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018553 refbind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018554 /*
18555 * Find a keyref.
18556 */
18557 while (refbind != NULL) {
18558 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18559 int i, j, k, res;
18560 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
18561 xmlSchemaPSVIIDCKeyPtr refKey, key;
18562
18563 /*
18564 * Find the referred key/unique.
18565 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018566 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018567 do {
18568 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
18569 bind->definition)
18570 break;
18571 bind = bind->next;
18572 } while (bind != NULL);
18573
18574 /*
18575 * Search for a matching key-sequences.
18576 */
18577 for (i = 0; i < refbind->nbNodes; i++) {
18578 res = 0;
18579 if (bind != NULL) {
18580 refKeys = refbind->nodeTable[i]->keys;
18581 for (j = 0; j < bind->nbNodes; j++) {
18582 keys = bind->nodeTable[j]->keys;
18583 for (k = 0; k < bind->definition->nbFields; k++) {
18584 refKey = refKeys[k];
18585 key = keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018586 res = xmlSchemaAreValuesEqual(vctxt,
18587 key->type, key->compValue,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018588 refKey->type, refKey->compValue);
18589 if (res == 0)
18590 break;
18591 else if (res == -1) {
18592 return (-1);
18593 }
18594 }
18595 if (res == 1) {
18596 /*
18597 * Match found.
18598 */
18599 break;
18600 }
18601 }
18602 }
18603 if (res == 0) {
18604 /* TODO: Report the key-sequence. */
18605 xmlSchemaVCustomErr(vctxt,
18606 XML_SCHEMAV_CVC_IDC,
18607 refbind->nodeTable[i]->node,
18608 (xmlSchemaTypePtr) refbind->definition,
18609 "No matching key-sequence found", NULL);
18610 }
18611 }
18612 }
18613 refbind = refbind->next;
18614 }
18615 return (0);
18616}
18617#endif /* IDC_ENABLED */
18618
18619#ifdef ELEM_INFO_ENABLED
18620/**
18621 * xmlSchemaBeginElement:
18622 * @vctxt: the WXS validation context
18623 *
18624 * Just a temporary workaround to simulate streaming validation
18625 * a bit.
18626 */
18627static void
18628xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
18629{
18630 vctxt->depth++;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018631 vctxt->nodeInfo = xmlSchemaGetFreshElemInfo(vctxt, vctxt->depth);
18632 vctxt->nodeInfo->node = vctxt->node;
18633 vctxt->nodeInfo->localName = vctxt->node->name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018634 if (vctxt->node->ns != NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018635 vctxt->nodeInfo->namespaceName = vctxt->node->ns->href;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018636 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018637 vctxt->nodeInfo->namespaceName = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018638}
18639
18640/**
18641 * xmlSchemaEndElement:
18642 * @vctxt: the WXS validation context
18643 *
18644 * Just a temporary workaround to simulate streaming validation
18645 * a bit.
18646 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018647static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018648xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
18649{
18650 if (vctxt->depth < 0) {
18651 /* TODO: raise error? */
18652 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018653 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018654 }
18655#ifdef IDC_ENABLED
18656 /*
18657 * Evaluate the history of changes of active state objects.
18658 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018659 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
18660 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018661
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018662 if (vctxt->nodeInfo->value != NULL) {
18663 xmlSchemaFreeValue(vctxt->nodeInfo->value);
18664 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018665 }
18666 /*
18667 * TODO: 6 The element information item must be ·valid· with respect to each of
18668 * the {identity-constraint definitions} as per Identity-constraint
18669 * Satisfied (§3.11.4).
18670 */
18671 /*
18672 * Validate IDC keyrefs.
18673 */
18674 xmlSchemaCheckCVCIDCKeyRef(vctxt);
18675#endif
18676
18677 /*
18678 * Merge/free the IDC table.
18679 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018680 if (vctxt->nodeInfo->idcTable != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018681#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018682#ifdef DEBUG_IDC
18683 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018684 vctxt->nodeInfo->namespaceName,
18685 vctxt->nodeInfo->localName,
18686 vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018687#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018688 if (vctxt->depth > 0) {
18689 /*
18690 * Merge the IDC node table with the table of the parent node.
18691 */
18692 xmlSchemaBubbleIDCNodeTables(vctxt);
18693 }
18694 /*
18695 * TODO: Don't free the PSVI IDC tables if they are
18696 * requested for the PSVI.
18697 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018698 xmlSchemaIDCFreeIDCTable(vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018699#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018700 vctxt->nodeInfo->idcTable = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018701 }
18702
18703 /*
18704 * Cleanup IDC matchers.
18705 */
18706#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018707 if (vctxt->nodeInfo->idcMatchers != NULL) {
18708 xmlSchemaIDCFreeMatcherList(vctxt->nodeInfo->idcMatchers);
18709 vctxt->nodeInfo->idcMatchers = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018710 }
18711#endif
18712
18713 /*
18714 * Skip further processing if we are on the validation root.
18715 */
18716 if (vctxt->depth == 0) {
18717 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018718 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018719 }
18720
18721 /*
18722 * Reset the bubbleDepth if needed.
18723 */
18724#ifdef IDC_ENABLED
18725 if (vctxt->aidcs != NULL) {
18726 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
18727 do {
18728 if (aidc->bubbleDepth == vctxt->depth) {
18729 /*
18730 * A bubbleDepth of a key/unique IDC matches the current
18731 * depth, this means that we are leaving the scope of the
18732 * top-most keyref IDC.
18733 */
18734 aidc->bubbleDepth = -1;
18735 }
18736 aidc = aidc->next;
18737 } while (aidc != NULL);
18738 }
18739#endif
18740 vctxt->depth--;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018741 /*
18742 * Clear the current elemInfo.
18743 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018744 if (vctxt->nodeInfo->value != NULL) {
18745 xmlSchemaFreeValue(vctxt->nodeInfo->value);
18746 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018747 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018748 vctxt->nodeInfo = vctxt->elemInfos[vctxt->depth];
18749 vctxt->node = vctxt->nodeInfo->node;
18750
18751 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018752}
18753
18754#endif /* ELEM_INFO_ENABLED */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018755
18756/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018757 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000018758 * @ctxt: a schema validation context
18759 * @node: the top node.
18760 *
18761 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018762 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000018763 *
18764 * Returns 0 if the element is schemas valid, a positive error code
18765 * number otherwise and -1 in case of internal or API error.
18766 */
18767static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018768xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
18769 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018770{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018771 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018772 int ret = 0;
18773 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018774 xmlAttrPtr attr;
18775 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018776 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000018777
18778 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018779 * This one is called by xmlSchemaValidateElementByWildcardInternal,
18780 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018781 * Note that @elemDecl will be the declaration and never the
18782 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018783 */
Daniel Veillard3646d642004-06-02 19:19:14 +000018784
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018785 if (ctxt == NULL) {
18786 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
18787 "Internal error: xmlSchemaValidateElementByDeclaration, "
18788 "bad arguments.\n",
18789 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018790 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018791 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018792
18793 elem = ctxt->node;
18794
18795 /*
18796 * cvc-elt (3.3.4) : 1
18797 */
18798 if (elemDecl == NULL) {
18799 xmlSchemaVCustomErr(ctxt,
18800 XML_SCHEMAV_CVC_ELT_1,
18801 elem, NULL,
18802 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018803 /*
18804 * Evaluate IDCs even if an error occured.
18805 */
18806#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018807 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018808 return (-1);
18809#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018810 return (ctxt->err);
18811 }
18812 /*
18813 * cvc-elt (3.3.4) : 2
18814 */
18815 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
18816 xmlSchemaVCustomErr(ctxt,
18817 XML_SCHEMAV_CVC_ELT_2,
18818 elem, NULL,
18819 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018820 /*
18821 * Evaluate IDCs even if an error occured.
18822 */
18823#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018824 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018825 return (-1);
18826#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018827 return (ctxt->err);
18828 }
18829
18830 /*
18831 * cvc-elt (3.3.4) : 3
18832 * Handle 'xsi:nil'.
18833 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018834
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018835 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018836 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018837 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18838 ctxt->node = (xmlNodePtr) attr;
18839 ctxt->cur = attr->children;
18840 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
18841 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
18842 BAD_CAST attrValue, 1, 1, 1, 1);
18843 ctxt->node = elem;
18844 ctxt->type = (xmlSchemaTypePtr) elemDecl;
18845 if (ret < 0) {
18846 xmlSchemaVCustomErr(ctxt,
18847 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018848 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018849 "Internal error: xmlSchemaValidateElementByDeclaration, "
18850 "validating the attribute 'xsi:nil'", NULL);
18851 if (attrValue != NULL)
18852 xmlFree(attrValue);
18853 return (-1);
18854 }
18855 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018856 /*
18857 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018858 */
18859 xmlSchemaVCustomErr(ctxt,
18860 XML_SCHEMAV_CVC_ELT_3_1,
18861 elem, NULL,
18862 "The element is not 'nillable'", NULL);
18863 } else {
18864 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018865 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018866 ret = 0;
18867 /*
18868 * cvc-elt (3.3.4) : 3.2.1
18869 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018870 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
18871 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018872 xmlSchemaVCustomErr(ctxt,
18873 XML_SCHEMAV_CVC_ELT_3_2_1,
18874 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018875 elem, (xmlSchemaTypePtr) elemDecl,
18876 "The 'nilled' element must have no character or "
18877 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018878 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
18879 }
18880 /*
18881 * cvc-elt (3.3.4) : 3.2.2
18882 */
18883 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
18884 (elemDecl->value != NULL)) {
18885 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
18886 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018887 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018888 "There is a fixed value constraint defined for "
18889 "the 'nilled' element", NULL);
18890 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
18891 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018892 if (ret == 0)
18893 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018894 }
18895 }
18896 if (attrValue != NULL)
18897 xmlFree(attrValue);
18898 }
18899
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018900
18901 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018902 /*
18903 * cvc-elt (3.3.4) : 4
18904 * Handle 'xsi:type'.
18905 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018906
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018907 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
18908 if (attr != NULL) {
18909 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018910
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018911 /*
18912 * TODO: We should report a *warning* that the type was overriden
18913 * by the instance.
18914 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018915
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018916 /*
18917 * cvc-elt (3.3.4) : 4.1
18918 */
18919 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18920 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
18921 &nsName, &local);
18922 if (ret < 0) {
18923 xmlSchemaVCustomErr(ctxt,
18924 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018925 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018926 "Internal error: xmlSchemaValidateElementByDeclaration, "
18927 "validating the attribute 'xsi:type'", NULL);;
18928 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018929 FREE_AND_NULL(nsName)
18930 FREE_AND_NULL(local)
18931 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018932 } else if (ret == 1) {
18933 xmlSchemaVSimpleTypeErr(ctxt,
18934 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18935 (xmlNodePtr) attr, attrValue,
18936 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
18937 } else if (ret == 2) {
18938 xmlSchemaVCustomErr(ctxt,
18939 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18940 (xmlNodePtr) attr,
18941 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18942 "The QName value '%s' has no "
18943 "corresponding namespace declaration in scope",
18944 attrValue);
18945 } else {
18946 /*
18947 * cvc-elt (3.3.4) : 4.2
18948 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018949 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
18950 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018951 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018952
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018953 xmlSchemaVCustomErr(ctxt,
18954 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018955 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018956 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18957 "The value %s does not resolve to a type "
18958 "definition",
18959 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
18960 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018961 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018962 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018963 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018964 */
18965 }
18966 }
18967 FREE_AND_NULL(attrValue)
18968 FREE_AND_NULL(nsName)
18969 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018970 }
18971 /* TODO: Change the handling of missing types according to
18972 * the spec.
18973 */
18974 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018975 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018976 XML_SCHEMAV_CVC_TYPE_1,
18977 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018978 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018979 /*
18980 * Evaluate IDCs even if an error occured.
18981 */
18982#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018983 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018984 return (-1);
18985#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018986 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018987 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018988
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018989 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018990 * Remember the actual-type definition.
18991 */
18992#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018993 ctxt->nodeInfo->typeDef = actualType;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018994#endif
18995
18996 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018997 * TODO: Since this should be already checked by the content model automaton,
18998 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
18999 * has been changed to XML_SCHEMAV_INTERNAL.
19000 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019001 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000019002 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019003 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019004 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019005 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019006 "Element %s: missing child %s\n",
19007 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019008 }
19009 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019010 }
19011 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019012 /*
19013 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019014 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019015 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000019016 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019017 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019018 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019019 "Element %s: missing child %s found %s\n",
19020 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019021 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019022 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019023 */
19024 if (elemHasContent == -1)
19025 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019026
19027 /*
19028 * IDC: Register identity-constraint XPath matchers.
19029 */
19030#ifdef IDC_ENABLED
19031 if (elemDecl->idcs != NULL)
19032 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
19033 /*
19034 * Evaluate IDCs.
19035 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019036 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019037 return (-1);
19038#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019039 /*
19040 * cvc-elt (3.3.4) : 5
19041 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019042 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019043 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019044 * cvc-elt (3.3.4) : 5.1
19045 * If the declaration has a {value constraint},
19046 * the item has neither element nor character [children] and
19047 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019048 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019049 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
19050 /*
19051 * cvc-elt (3.3.4) : 5.1.1
19052 * If the ·actual type definition· is a ·local type definition·
19053 * then the canonical lexical representation of the {value constraint}
19054 * value must be a valid default for the ·actual type definition· as
19055 * defined in Element Default Valid (Immediate) (§3.3.6).
19056 */
19057 /*
19058 * NOTE: 'local' above means types aquired by xsi:type.
19059 */
19060 ret = 0;
19061 if (actualType != elemDecl->subtypes) {
19062 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
19063 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019064 elemDecl->value, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019065 if (ret < 0) {
19066 xmlSchemaVCustomErr(ctxt,
19067 XML_SCHEMAV_INTERNAL,
19068 elem, actualType,
19069 "Internal error: xmlSchemaValidateElementByDeclaration, "
19070 "validating a default value", NULL);
19071 return (-1);
19072 }
19073 }
19074 /*
19075 * cvc-elt (3.3.4) : 5.1.2
19076 * The element information item with the canonical lexical
19077 * representation of the {value constraint} value used as its
19078 * ·normalized value· must be ·valid· with respect to the
19079 * ·actual type definition· as defined by Element Locally Valid (Type)
19080 * (§3.3.4).
19081 */
19082 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019083 * Disable validation of the simple content, if it was already
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019084 * done above.
19085 */
19086 if (ret == 0) {
19087 if (actualType != elemDecl->subtypes)
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019088 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019089 else
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019090 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019091 ctxt->node = elem;
19092 if (ret < 0) {
19093 xmlSchemaVCustomErr(ctxt,
19094 XML_SCHEMAV_INTERNAL,
19095 elem, actualType,
19096 "Internal error: xmlSchemaValidateElementByDeclaration, "
19097 "validating against the type", NULL);
19098 return (-1);
19099 }
19100 /*
19101 * PSVI: Create a text node on the instance element.
19102 */
19103 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
19104 xmlNodePtr textChild;
19105
19106 textChild = xmlNewText(elemDecl->value);
19107 if (textChild == NULL) {
19108 xmlSchemaVCustomErr(ctxt,
19109 XML_SCHEMAV_INTERNAL,
19110 elem, actualType,
19111 "Internal error: xmlSchemaValidateElementByDeclaration, "
19112 "could not create a default text node for the instance",
19113 NULL);
19114 } else
19115 xmlAddChild(elem, textChild);
19116 }
19117 }
19118
19119 } else {
19120 /*
19121 * 5.2.1 The element information item must be ·valid· with respect
19122 * to the ·actual type definition· as defined by Element Locally
19123 * Valid (Type) (§3.3.4).
19124 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019125 ret = xmlSchemaValidateElementByType(ctxt, actualType, nilled, 1);
19126 /*
19127 * Consume the computed value for IDCs, ect. Note that default
19128 * values are not supported yet.
19129 */
19130#ifdef ELEM_INFO_ENABLED
19131 if (ctxt->value != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019132 ctxt->nodeInfo->value = ctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019133 ctxt->value = NULL;
19134 }
19135#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019136 ctxt->node = elem;
19137 if (ret < 0) {
19138 xmlSchemaVCustomErr(ctxt,
19139 XML_SCHEMAV_INTERNAL,
19140 elem, actualType,
19141 "Internal error: xmlSchemaValidateElementByDeclaration, "
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019142 "calling validation by type", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019143 return (-1);
19144 }
19145 /*
19146 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
19147 * not applied, all of the following must be true:
19148 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019149 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
19150 /*
19151 * 5.2.2.1 The element information item must have no element
19152 * information item [children].
19153 *
19154 * TODO REDUNDANT: If the actual type exists, the above call to
19155 * xmlSchemaValidateElementByType will already check for element
19156 * nodes.
19157 */
19158 if (xmlSchemaHasElemContent(elem)) {
19159 xmlSchemaVCustomErr(ctxt,
19160 XML_SCHEMAV_CVC_ELT_5_2_2_1,
19161 elem, (xmlSchemaTypePtr) elemDecl,
19162 "Elements in the content are not allowed if it is "
19163 "constrained by a fixed value", NULL);
19164 } else {
19165 /*
19166 * 5.2.2.2 The appropriate case among the following must
19167 * be true:
19168 */
19169
19170 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
19171 xmlChar *value;
19172 /*
19173 * 5.2.2.2.1 If the {content type} of the ·actual type
19174 * definition· is mixed, then the *initial value* of the
19175 * item must match the canonical lexical representation
19176 * of the {value constraint} value.
19177 *
19178 * ... the *initial value* of an element information
19179 * item is the string composed of, in order, the
19180 * [character code] of each character information item in
19181 * the [children] of that element information item.
19182 */
19183 value = xmlNodeListGetString(elem->doc, elem->children, 1);
19184 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
19185 /*
19186 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019187 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019188 */
19189 xmlSchemaVCustomErr(ctxt,
19190 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
19191 elem, (xmlSchemaTypePtr) elemDecl,
19192 "The value does not match the cononical "
19193 "lexical representation of the fixed constraint",
19194 NULL);
19195 }
19196 if (value != NULL)
19197 xmlFree(value);
19198 } else if ((actualType->contentType ==
19199 XML_SCHEMA_CONTENT_SIMPLE) ||
19200 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
19201 xmlChar *value;
19202
19203 /*
19204 * 5.2.2.2.2 If the {content type} of the ·actual type
19205 * definition· is a simple type definition, then the
19206 * *actual value* of the item must match the canonical
19207 * lexical representation of the {value constraint} value.
19208 */
19209 /*
19210 * TODO: *actual value* is the normalized value, impl. this.
19211 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019212 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019213 *
19214 */
19215 value = xmlNodeListGetString(elem->doc, elem->children, 1);
19216 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
19217 xmlSchemaVCustomErr(ctxt,
19218 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
19219 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019220 "The normalized value does not match the canonical "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019221 "lexical representation of the fixed constraint",
19222 NULL);
19223 }
19224 if (value != NULL)
19225 xmlFree(value);
19226
19227 }
19228 /*
19229 * TODO: What if the content type is not 'mixed' or simple?
19230 */
19231
19232 }
19233
19234 }
19235 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019236 /*
19237 * TODO: 7 If the element information item is the ·validation root·, it must be
19238 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
19239 */
19240
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019241 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019242}
19243
Daniel Veillard4255d502002-04-16 15:50:10 +000019244/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019245 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000019246 * @ctxt: a schema validation context
19247 * @node: the top node.
19248 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019249 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
19250 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000019251 *
19252 * Returns 0 if the element is valid, a positive error code
19253 * number otherwise and -1 in case of an internal error.
19254 */
19255static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019256xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
19257 xmlSchemaWildcardPtr wild,
19258 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000019259{
19260 const xmlChar *uri;
19261 int ret = 0;
19262 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019263
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019264 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019265 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
19266 if (ret == -1) {
19267 xmlSchemaVCustomErr(ctxt,
19268 XML_SCHEMAV_INTERNAL,
19269 ctxt->node, NULL,
19270 "Internal error: xmlSchemaValidateElement, "
19271 "assembling schema by xsi", NULL);
19272 return (-1);
19273 }
19274 /*
19275 * NOTE: We won't react on schema parser errors here.
19276 * TODO: But a warning would be nice.
19277 */
19278 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019279 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
19280 xmlSchemaElementPtr decl = NULL;
19281
19282 if (node->ns != NULL)
19283 decl = xmlHashLookup3(ctxt->schema->elemDecl,
19284 node->name, node->ns->href, NULL);
19285 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019286 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
19287 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019288 if (decl != NULL) {
19289 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019290 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019291 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019292 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019293 "Internal error: xmlSchemaValidateAnyInternal, "
19294 "validating an element in the context of a wildcard.",
19295 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000019296 }
19297 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019298 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
19299 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019300 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019301 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019302 /*
19303 * Evaluate IDCs even if a validation error occured.
19304 */
19305#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019306 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019307 return(-1);
19308#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000019309 return (ctxt->err);
19310 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019311 /*
19312 * Evaluate IDCs; we need to know if an IDC field resolves to
19313 * such a node. This node has no type definition and will
19314 * definitely result in an IDC validation error if an IDC field
19315 * resolves.
19316 */
19317#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019318 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019319 return(-1);
19320#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000019321 }
19322 if (node->children != NULL) {
19323 child = node->children;
19324 do {
19325 if (child->type == XML_ELEMENT_NODE) {
19326 if (child->ns != NULL)
19327 uri = child->ns->href;
19328 else
19329 uri = NULL;
19330 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019331 /* TODO: error code. */
19332 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019333 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019334 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000019335 return (ctxt->err);
19336 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019337#ifdef ELEM_INFO_ENABLED
19338 ctxt->node = child;
19339 xmlSchemaBeginElement(ctxt);
19340#endif
19341 /*
19342 * Recurse over the children.
19343 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019344 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
19345 wild, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019346 if (ret == -1)
19347 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019348#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019349 if (xmlSchemaEndElement(ctxt) == -1)
19350 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019351#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000019352 if (ret != 0)
19353 return (ret);
19354 }
19355 child = child->next;
19356 } while (child != NULL);
19357 }
19358 return (0);
19359}
19360
19361/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019362 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000019363 * @ctxt: a schema validation context
19364 *
19365 * Returns 0 if the element is valid, a positive error code
19366 * number otherwise and -1 in case of an internal or API error.
19367 */
19368static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019369xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
19370 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000019371{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019372 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
19373 (ctxt->node == NULL)) {
19374 xmlSchemaVCustomErr(ctxt,
19375 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
19376 "Internal error: xmlSchemaValidateElementByWildcard, "
19377 "bad arguments", NULL);
19378 return (-1);
19379 }
19380 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
19381 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000019382}
19383
19384/**
William M. Brack2f2a6632004-08-20 23:09:47 +000019385 * xmlSchemaValidateAnyTypeContent:
19386 * @ctxt: a schema validation context
19387 * @node: the current element
19388 *
19389 * This one validates the content of an element of the type
19390 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
19391 * thus elements in the subtree will be validated, if a corresponding
19392 * declaration in the schema exists.
19393 *
19394 * Returns 0 if the element and its subtree is valid, a positive error code
19395 * otherwise and -1 in case of an internal or API error.
19396 */
19397static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019398xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
19399 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000019400{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019401 xmlSchemaTypePtr oldtype;
19402 xmlNodePtr top, cur;
19403 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000019404 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019405
19406 if ((type == NULL) || (ctxt->node == NULL))
19407 return (-1);
19408
19409 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000019410 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019411
19412 oldtype = ctxt->type;
19413 top = ctxt->node;
19414 /*
19415 * STREAM: Child nodes are processed.
19416 */
19417 cur = ctxt->node->children;
19418 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019419 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019420 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019421 /*
19422 * The process contents of the wildcard is "lax", thus
19423 * we need to validate the element if a declaration
19424 * exists.
19425 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019426 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000019427 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019428 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000019429 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019430 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000019431 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019432 ctxt->node = cur;
19433 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
19434 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000019435 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019436 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000019437 "Internal error: xmlSchemaValidateAnyTypeContent, "
19438 "validating an element in the context of a wildcard.",
19439 NULL, NULL);
19440 return (ret);
19441 } else if (ret > 0)
19442 return (ret);
19443 skipContent = 1;
19444 }
19445 }
19446 /*
19447 * Browse the full subtree, deep first.
19448 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019449 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019450 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019451 cur = cur->children;
19452 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019453 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019454 cur = cur->next;
19455 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019456 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019457 while (cur != top) {
19458 if (cur->parent != NULL)
19459 cur = cur->parent;
19460 if ((cur != top) && (cur->next != NULL)) {
19461 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000019462 break;
19463 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019464 if (cur->parent == NULL) {
19465 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000019466 break;
19467 }
19468 }
19469 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019470 if (cur == top)
19471 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000019472 } else
19473 break;
19474 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019475 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000019476 return (0);
19477}
19478
19479/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019480 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000019481 * @ctxt: a schema validation context
19482 * @node: the top node.
19483 *
19484 * Validate the content of an element expected to be a complex type type
19485 * xmlschema-1.html#cvc-complex-type
19486 * Validation Rule: Element Locally Valid (Complex Type)
19487 *
19488 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000019489 * number otherwise and -1 in case of internal or API error.
19490 * Note on reported errors: Although it might be nice to report
19491 * the name of the simple/complex type, used to validate the content
19492 * of a node, it is quite unnecessary: for global defined types
19493 * the local name of the element is equal to the NCName of the type,
19494 * for local defined types it makes no sense to output the internal
19495 * computed name of the type. TODO: Instead, one should attach the
19496 * struct of the type involved to the error handler - this allows
19497 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000019498 */
19499static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019500xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019501 xmlSchemaTypePtr type,
19502 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019503{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019504 xmlSchemaTypePtr oldtype;
19505 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019506 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000019507 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019508 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000019509
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019510 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
19511 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000019512
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019513 oldtype = ctxt->type;
19514 ctxt->type = type;
19515 elem = ctxt->node;
19516
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019517 /*
19518 * Verify the attributes
19519 */
19520 /*
19521 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019522 */
19523 /* NOTE: removed, since a check for abstract is
19524 * done in the cvc-type constraint.
19525 *
19526 *
19527 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
19528 * xmlSchemaVComplexTypeErr(ctxt,
19529 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
19530 * elem, type,
19531 * "The type definition is abstract");
19532 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
19533 *}
19534 */
19535
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019536 attrs = ctxt->attr;
19537 attrTop = ctxt->attrTop;
19538 /*
19539 * STREAM: Attribute nodes are processed.
19540 */
19541 xmlSchemaRegisterAttributes(ctxt, elem->properties);
19542 xmlSchemaValidateAttributes(ctxt, elem, type);
19543 if (ctxt->attr != NULL)
19544 xmlSchemaFreeAttributeStates(ctxt->attr);
19545 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019546 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019547
19548 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019549 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019550 * model was defined. Somehow ->contModel is always not NULL
19551 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019552 * TODO: Check if the obove still occurs.
19553 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019554 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019555 case XML_SCHEMA_CONTENT_EMPTY: {
19556 /*
19557 * 1 If the {content type} is empty, then the element information
19558 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000019559 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019560 /*
19561 * TODO: Is the entity stuff correct?
19562 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019563 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019564 xmlSchemaVComplexTypeErr(ctxt,
19565 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019566 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019567 "Character or element content is not allowed, "
19568 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019569 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019570 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019571 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019572 case XML_SCHEMA_CONTENT_MIXED:
19573 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019574 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019575 /*
19576 * The type has 'anyType' as its base and no content model
19577 * is defined -> use 'anyType' as the type to validate
19578 * against.
19579 */
19580 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
19581 /* TODO: Handle -1. */
19582 break;
19583 }
19584 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019585 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019586 {
19587 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019588 xmlChar *values[10];
19589 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019590
19591 /*
19592 * Content model check initialization.
19593 */
19594 if (type->contModel != NULL) {
19595 oldregexp = ctxt->regexp;
19596 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
19597 (xmlRegExecCallbacks)
19598 xmlSchemaValidateCallback, ctxt);
19599#ifdef DEBUG_AUTOMATA
19600 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
19601#endif
19602 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019603 /*
19604 * STREAM: Children are processed.
19605 */
19606 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019607 while (child != NULL) {
19608 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019609 if (child->ns != NULL)
19610 nsUri = child->ns->href;
19611 else
19612 nsUri = NULL;
19613 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019614 child->name, nsUri, child);
19615 if (ctxt->err == XML_SCHEMAV_INTERNAL)
19616 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019617 /*
19618 * URGENT TODO: Could we anchor an error report
19619 * here to notify of invalid elements?
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019620 * TODO: Perhaps it would be better to report
19621 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019622 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019623#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000019624 if (ret < 0)
19625 xmlGenericError(xmlGenericErrorContext,
19626 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000019627 else
19628 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019629 " --> %s\n", child->name);
19630#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019631 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019632 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
19633 &values[0], &terminal);
19634 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019635 XML_SCHEMAV_ELEMENT_CONTENT,
19636 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019637 "This element is not expected",
19638 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019639 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019640 /*
19641 * Note that this will skip further validation of the
19642 * content.
19643 */
19644 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019645 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019646 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
19647 /*
19648 * TODO: Ask Daniel if this are all character nodes.
19649 */
19650 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
19651 (child->type == XML_ENTITY_NODE) ||
19652 (child->type == XML_ENTITY_REF_NODE) ||
19653 (child->type == XML_CDATA_SECTION_NODE))) {
19654 /*
19655 * 2.3 If the {content type} is element-only, then the
19656 * element information item has no character information
19657 * item [children] other than those whose [character
19658 * code] is defined as a white space in [XML 1.0 (Second
19659 * Edition)].
19660 */
William M. Brack2f2a6632004-08-20 23:09:47 +000019661 xmlSchemaVComplexTypeErr(ctxt,
19662 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019663 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019664 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019665 "because the content type is element-only");
19666 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019667 break;
19668 }
19669 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019670 }
19671 /*
19672 * Content model check finalization.
19673 */
19674 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019675 if (ret == 0) {
19676 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
19677 &values[0], &terminal);
19678 if (nbval + nbneg != 0) {
19679 /*
19680 * If a next value still exists, I does not have to
19681 * mean that there's an element missing, since it
19682 * might be an optional element. So double check it.
19683 */
19684 ret = xmlRegExecPushString(ctxt->regexp,
19685 NULL, NULL);
19686 if (ret <= 0) {
19687 ret = 1;
19688 xmlSchemaVComplexTypeElemErr(ctxt,
19689 XML_SCHEMAV_ELEMENT_CONTENT,
19690 elem, type, "Missing child element(s)",
19691 nbval, nbneg, values);
19692 } else
19693 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019694#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019695 xmlGenericError(xmlGenericErrorContext,
19696 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019697#endif
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019698 }
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019699#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019700 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019701 xmlGenericError(xmlGenericErrorContext,
19702 "Element %s content check succeeded\n",
19703 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019704#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019705 }
19706 xmlRegFreeExecCtxt(ctxt->regexp);
19707 ctxt->regexp = oldregexp;
19708 }
19709 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019710 break;
19711 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019712 case XML_SCHEMA_CONTENT_BASIC:
19713 /*
19714 * If the simple content was already validated
19715 * (e.g. a default value), the content need not
19716 * to be validated again.
19717 */
19718 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019719 xmlChar *value = NULL;
19720 /*
19721 * We hit a complexType with a simpleContent resolving
19722 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000019723 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019724 /*
19725 * 2.2 If the {content type} is a simple type definition,
19726 * then the element information item has no element
19727 * information item [children], and the ·normalized value·
19728 * of the element information item is ·valid· with respect
19729 * to that simple type definition as defined by String
19730 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019731 */
19732 /*
19733 * STREAM: Children are processed.
19734 */
19735 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019736 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019737 /*
19738 * TODO: Could the entity stuff produce elements
19739 * as well?
19740 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019741 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019742 xmlSchemaVComplexTypeErr(ctxt,
19743 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019744 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019745 "Element content is not allowed, because "
19746 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019747 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19748 break;
19749 }
19750 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019751 }
19752 ctxt->node = elem;
19753 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019754 if (ret == 0) {
19755 /*
19756 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000019757 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019758 /*
19759 * STREAM: Children are processed.
19760 */
19761 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000019762 value = NULL;
19763 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019764 value = xmlNodeGetContent(elem);
19765 /*
19766 * URGENT TODO: Should facets for the simple type validation be
19767 * disabled, if the derivation of facets for complex types
19768 * is implemented?
19769 */
19770 /*
19771 * NOTE: This call won't check the correct types of the
19772 * content nodes, since this should be done here.
19773 */
19774 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000019775 if (ret > 0) {
19776 /*
19777 * NOTE: Although an error will be reported by
19778 * xmlSchemaValidateSimpleTypeValue, the spec wants
19779 * a specific complex type error to be reported
19780 * additionally.
19781 */
19782 xmlSchemaVComplexTypeErr(ctxt,
19783 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019784 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019785 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019786 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19787 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019788 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019789 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019790 "Element '%s': Error while validating character "
19791 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019792 elem->name, type->name);
19793 if (value != NULL)
19794 xmlFree(value);
19795 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019796 return (-1);
19797 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019798 }
19799#if 0
19800 /*
19801 * REMOVED since handled by xmlSchemaValidateSimpleTypeValue
19802 * already.
19803 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019804 if (ret == 0) {
19805 /*
19806 * Apply facets of the complexType. Be sure to pass the
19807 * built-in type to xmlSchemaValidateFacetsInternal.
19808 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019809 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000019810 * are used, or if the facets, defined by this complex type,
19811 * are to be used only. This here applies both facet sets.
19812 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000019813
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019814 ret = xmlSchemaValidateFacetsInternal(ctxt,
19815 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019816 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019817 xmlSchemaVComplexTypeErr(ctxt,
19818 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019819 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019820 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019821 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19822 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019823 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019824 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019825 "Element '%s': Error while validating character "
19826 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000019827 "apply facets.\n",
19828 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019829 if (value != NULL)
19830 xmlFree(value);
19831 ctxt->type = oldtype;
19832 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019833 }
19834 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019835#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000019836 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019837 xmlFree(value);
19838
Daniel Veillard01fa6152004-06-29 17:04:39 +000019839 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019840 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019841 default:
19842 TODO xmlGenericError(xmlGenericErrorContext,
19843 "unimplemented content type %d\n",
19844 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000019845 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019846 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019847 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019848}
19849
19850/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019851 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000019852 * @ctxt: a schema validation context
19853 * @elem: an element
19854 * @type: the list of type declarations
19855 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019856 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000019857 *
19858 * Returns 0 if the element is schemas valid, a positive error code
19859 * number otherwise and -1 in case of internal or API error.
19860 */
19861static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019862xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019863 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019864 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019865 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019866{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019867 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000019868
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019869
19870 if ((ctxt == NULL) || (type == NULL)) {
19871 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
19872 "Internal error: xmlSchemaValidateElementByType, "
19873 "bad arguments", NULL);
19874 return (-1);
19875 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019876 /*
19877 * This one is called by "xmlSchemaValidateElementByDeclaration".
19878 * It will forward to the proper validation
19879 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019880 */
19881 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019882 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019883 XML_SCHEMAV_CVC_TYPE_1,
19884 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019885 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019886 return (XML_SCHEMAV_CVC_TYPE_1);
19887 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019888
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019889 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019890 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019891 XML_SCHEMAV_CVC_TYPE_2,
19892 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019893 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019894 return (XML_SCHEMAV_CVC_TYPE_2);
19895 }
19896
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019897 switch (type->type) {
19898 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019899 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
19900 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019901 break;
19902 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019903 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019904 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019905 break;
19906 case XML_SCHEMA_TYPE_BASIC:
19907 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
19908 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
19909 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019910 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019911 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019912 break;
19913 default:
19914 ret = -1;
19915 break;
19916 }
19917 if (ret == -1)
19918 return (-1);
19919 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019920 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019921}
19922
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019923static int
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019924xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019925 xmlSchemaTypePtr type,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019926 const xmlChar *value,
19927 xmlSchemaValPtr *val)
19928{
19929 xmlSchemaTypePtr prim;
19930
19931 if (val == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019932 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019933 XML_SCHEMAV_INTERNAL,
19934 "Internal error: xmlSchemaPostCreateVal, "
19935 "bad arguments", NULL, NULL);
19936 return (-1);
19937 }
19938 /*
19939 * Only string or anySimpleType values are expected to be post-created.
19940 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019941 prim = xmlSchemaGetPrimitiveType(type);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019942 if ((prim->builtInType == XML_SCHEMAS_STRING) ||
19943 (prim->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
19944 {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019945 if (value == NULL)
19946 /* TODO: Can this happen at all? */
19947 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
19948 xmlStrdup(BAD_CAST ""));
19949 else
19950 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING, value);
19951 if ((*val) == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019952 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019953 XML_SCHEMAV_INTERNAL,
19954 "Internal error: xmlSchemaPostCreateVal, "
19955 "failed to create the value", NULL, NULL);
19956 return (-1);
19957 }
19958 return (0);
19959 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019960 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019961 XML_SCHEMAV_INTERNAL,
19962 "Internal error: xmlSchemaPostCreateVal, "
19963 "the given type is not supported", NULL, NULL);
19964 return (-1);
19965}
19966
19967static int
19968xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019969 xmlSchemaAttrStatePtr state)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019970{
19971 xmlChar *value;
19972 const xmlChar *defValue;
19973 xmlSchemaValPtr defVal;
19974 int fixed;
19975 int ret;
19976
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019977 if (vctxt->attrInfo->typeDef == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019978 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
19979 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
19980 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019981 vctxt->node = vctxt->attrInfo->node;
19982 vctxt->cur = vctxt->node->children;
19983 /* STREAM */
19984 value = xmlNodeListGetString(vctxt->node->doc, vctxt->cur, 1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019985
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019986 /*
19987 * NOTE: This call also checks the content nodes for correct type.
19988 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019989 ret = xmlSchemaValidateSimpleTypeValue(vctxt, vctxt->attrInfo->typeDef,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019990 value, 1, 1, 1, 1);
19991
19992 /*
19993 * Handle 'fixed' attributes.
19994 */
19995 if (ret > 0) {
19996 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
19997 /*
19998 * NOTE: Fixed value constraints will be not
19999 * applied if the value was invalid, because:
20000 * 1. The validation process does not return a precomputed
20001 * value.
20002 * 2. An invalid value implies a violation of a fixed
20003 * value constraint.
20004 */
20005 } else if (ret == 0) {
20006 state->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020007 if (xmlSchemaGetEffectiveValueConstraint(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020008 (xmlSchemaAttributePtr) vctxt->attrInfo->decl,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020009 &fixed, &defValue, &defVal) && (fixed == 1)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000020010
20011 int ws = xmlSchemaGetWhiteSpaceFacetValue(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020012 vctxt->nodeInfo->typeDef);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020013 /*
20014 * cvc-au : Attribute Locally Valid (Use)
20015 * For an attribute information item to be·valid·
20016 * with respect to an attribute use its ·normalized
20017 * value· must match the canonical lexical representation
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020018 * of the attribute use's {value constraint} value, if it
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020019 * is present and fixed.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020020 *
20021 * TODO: Use somehow the *normalized* value and the *canonical*
20022 * fixed value. This here compares the canonical values of both.
20023 * The normalized value of, for example, a float type can differ
20024 * from its canonical representation. This all means that a fixed
20025 * value can only be OK, if it's present in the canonical form in
20026 * the instance.
20027 * NOTE: Since the value for string and anySimpleType is not always
20028 * precomputed during validation, we need to do it now.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020029 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020030 if (vctxt->value == NULL) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000020031 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020032 * Post-create the value.
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000020033 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000020034 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
20035 value, &(vctxt->value)) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020036 ret = -1;
20037 goto exit;
20038 }
20039 value = NULL;
20040 }
20041 if (defVal == NULL) {
20042 xmlChar *str;
20043
20044 /*
20045 * Post-create the default/fixed value.
20046 */
20047 if (defValue == NULL)
20048 str = xmlStrdup(BAD_CAST "");
20049 else
20050 str = xmlStrdup(defValue);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000020051 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
20052 str, &defVal) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020053 ret = -1;
20054 FREE_AND_NULL(str)
20055 goto exit;
20056 }
20057 ((xmlSchemaAttributePtr) vctxt->attrInfo->decl)->defVal = defVal;
20058 }
20059 if (xmlSchemaCompareValuesWhtsp(vctxt->value,
20060 (xmlSchemaWhitespaceValueType) ws,
20061 defVal,
20062 (xmlSchemaWhitespaceValueType) ws) != 0)
20063 {
20064 state->state = XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020065 }
20066 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020067 }
20068exit:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020069 if (value != NULL) {
20070 xmlFree(value);
20071 }
20072 return (ret);
20073}
20074
Daniel Veillard4255d502002-04-16 15:50:10 +000020075/**
20076 * xmlSchemaValidateAttributes:
20077 * @ctxt: a schema validation context
20078 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000020079 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000020080 *
20081 * Validate the attributes of an element.
20082 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000020083 * 1. Existent, invalid attributes are reported in the form
20084 * "prefix:localName".
20085 * Reason: readability - it is easier to find the actual XML
20086 * representation of the attributes QName.
20087 * 2. Missing attributes are reported in the form
20088 * {"URI", "localName"}.
20089 * This is necessary, since the the prefix need not to be declared
20090 * at all, and thus is not computable.
20091 *
Daniel Veillard4255d502002-04-16 15:50:10 +000020092 * Returns 0 if the element is schemas valid, a positive error code
20093 * number otherwise and -1 in case of internal or API error.
20094 */
20095static int
Daniel Veillard3646d642004-06-02 19:19:14 +000020096xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020097{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020098 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000020099 int ret;
20100 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020101 const xmlChar *defValue;
20102 xmlSchemaValPtr defVal;
20103 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020104 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000020105 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000020106 int found;
William M. Brack803812b2004-06-03 02:11:24 +000020107 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020108 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020109 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000020110#ifdef DEBUG_ATTR_VALIDATION
20111 int redundant = 0;
20112#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000020113
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020114
Daniel Veillardc0826a72004-08-10 14:17:33 +000020115 /*
20116 * Allow all attributes if the type is anyType.
20117 */
20118 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
20119 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020120
20121 oldnode = ctxt->node;
20122 if (type != NULL)
20123 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000020124 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000020125 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000020126 attrDecl = attrUse->attr;
20127#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020128 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000020129 printf("attr use - use: %d\n", attrDecl->occurs);
20130#endif
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020131 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
Daniel Veillard3646d642004-06-02 19:19:14 +000020132
20133 if (curState->decl == attrUse->attr) {
20134#ifdef DEBUG_ATTR_VALIDATION
20135 redundant = 1;
20136#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020137 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020138 attr = curState->attr;
20139#ifdef DEBUG_ATTR_VALIDATION
20140 printf("attr - name: %s\n", attr->name);
20141 if (attr->ns != NULL)
20142 printf("attr - ns: %s\n", attr->ns->href);
20143 else
20144 printf("attr - ns: none\n");
20145#endif
20146 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020147 if (attr == NULL)
20148 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000020149 if (attrDecl->ref != NULL) {
20150 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020151 continue;
20152 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000020153 if ((attrDecl->refNs == NULL) ||
20154 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020155 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000020156 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020157 continue;
20158 }
20159 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000020160 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020161 continue;
20162 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020163 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020164 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020165 if (attr->ns == NULL) {
20166 /*
William M. Bracke7091952004-05-11 15:09:58 +000020167 * accept an unqualified attribute only if the target
20168 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020169 */
Daniel Veillard3646d642004-06-02 19:19:14 +000020170 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000020171 /*
20172 * This check was removed, since the target namespace
20173 * was evaluated during parsing and already took
20174 * "attributeFormDefault" into account.
20175 */
20176 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020177 continue;
20178 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000020179 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020180 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000020181 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020182 attr->ns->href))
20183 continue;
20184 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020185 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020186#ifdef DEBUG_ATTR_VALIDATION
20187 printf("found\n");
20188#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020189 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000020190 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020191 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
20192 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020193 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020194 */
Daniel Veillard3646d642004-06-02 19:19:14 +000020195 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020196 if (!found) {
20197 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
20198 xmlSchemaAttrStatePtr tmp;
20199
Daniel Veillard3646d642004-06-02 19:19:14 +000020200#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020201 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000020202#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020203 /*
20204 * Add a new dummy attribute state.
20205 */
20206 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
20207 if (tmp == NULL) {
20208 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
20209 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020210 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020211 }
20212 tmp->attr = NULL;
20213 tmp->state = XML_SCHEMAS_ATTR_MISSING;
20214 tmp->decl = attrDecl;
20215 tmp->next = NULL;
20216
20217 if (reqAttrStates == NULL) {
20218 reqAttrStates = tmp;
20219 reqAttrStatesTop = tmp;
20220 } else {
20221 reqAttrStatesTop->next = tmp;
20222 reqAttrStatesTop = tmp;
20223 }
20224 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
20225 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
20226 &fixed, &defValue, &defVal))) {
20227 xmlSchemaAttrStatePtr tmp;
20228 /*
20229 * Handle non existent default/fixed attributes.
20230 */
20231 tmp = (xmlSchemaAttrStatePtr)
20232 xmlMalloc(sizeof(xmlSchemaAttrState));
20233 if (tmp == NULL) {
20234 xmlSchemaVErrMemory(ctxt,
20235 "registering schema specified attributes", NULL);
20236 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020237 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020238 }
20239 tmp->attr = NULL;
20240 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
20241 tmp->decl = attrDecl;
20242 tmp->value = defValue;
20243 tmp->next = NULL;
20244
20245 if (defAttrStates == NULL) {
20246 defAttrStates = tmp;
20247 defAttrStates = tmp;
20248 } else {
20249 defAttrStates->next = tmp;
20250 defAttrStatesTop = tmp;
20251 }
20252 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020253 }
20254 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000020255 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020256 /*
20257 * Add required attributes to the attribute states of the context.
20258 */
20259 if (reqAttrStates != NULL) {
20260 if (ctxt->attr == NULL) {
20261 ctxt->attr = reqAttrStates;
20262 } else {
20263 ctxt->attrTop->next = reqAttrStates;
20264 }
20265 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000020266 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020267 /*
20268 * Process wildcards.
20269 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020270
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020271 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000020272#ifdef DEBUG_ATTR_VALIDATION
20273 xmlSchemaWildcardNsPtr ns;
20274 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020275 if (type->attributeWildcard->processContents ==
20276 XML_SCHEMAS_ANY_LAX)
20277 printf("processContents: lax\n");
20278 else if (type->attributeWildcard->processContents ==
20279 XML_SCHEMAS_ANY_STRICT)
20280 printf("processContents: strict\n");
20281 else
20282 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000020283 if (type->attributeWildcard->any)
20284 printf("type: any\n");
20285 else if (type->attributeWildcard->negNsSet != NULL) {
20286 printf("type: negated\n");
20287 if (type->attributeWildcard->negNsSet->value == NULL)
20288 printf("ns: (absent)\n");
20289 else
20290 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
20291 } else if (type->attributeWildcard->nsSet != NULL) {
20292 printf("type: set\n");
20293 ns = type->attributeWildcard->nsSet;
20294 while (ns != NULL) {
20295 if (ns->value == NULL)
20296 printf("ns: (absent)\n");
20297 else
20298 printf("ns: %s\n", ns->value);
20299 ns = ns->next;
20300 }
20301 } else
20302 printf("empty\n");
20303
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020304
20305#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000020306 curState = ctxt->attr;
20307 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020308 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
20309 if (curState->attr->ns != NULL)
20310 nsURI = curState->attr->ns->href;
20311 else
20312 nsURI = NULL;
20313 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
20314 nsURI)) {
20315 /*
20316 * Handle processContents.
20317 */
20318 if ((type->attributeWildcard->processContents ==
20319 XML_SCHEMAS_ANY_LAX) ||
20320 (type->attributeWildcard->processContents ==
20321 XML_SCHEMAS_ANY_STRICT)) {
20322
20323 attr = curState->attr;
20324 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020325 attr->name, nsURI);
20326 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020327 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020328 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020329 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
20330 /* TODO
20331 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
20332 */
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020333 } else if (type->attributeWildcard->processContents ==
20334 XML_SCHEMAS_ANY_LAX) {
20335 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020336 } else
20337 curState->state = XML_SCHEMAS_ATTR_WILD_NO_DECL;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020338 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000020339 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020340 }
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020341 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020342 curState = curState->next;
20343 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020344 }
20345
Daniel Veillardc0826a72004-08-10 14:17:33 +000020346 if (ctxt->attr != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020347 int valueNeeded;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020348
20349 /*
20350 * Validate the value of the attribute.
20351 */
20352 if (ctxt->value != NULL) {
20353 xmlSchemaFreeValue(ctxt->value);
20354 ctxt->value = NULL;
20355 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000020356 curState = ctxt->attr;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020357 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020358 valueNeeded = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020359 switch (curState->state) {
20360 case XML_SCHEMAS_ATTR_VALIDATE_VALUE:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020361
20362 /*
20363 * Create an attribute info if needed.
20364 */
20365 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020366 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
20367 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020368 if (ctxt->attrInfo == NULL) {
20369 xmlSchemaVErrMemory(ctxt,
20370 "allocating an attribute info", NULL);
20371 goto fatal_exit;
20372 }
20373 }
20374 /*
20375 * Init the attribute info.
20376 */
20377 ctxt->attrInfo->flags = 0;
20378 ctxt->attrInfo->node = (xmlNodePtr) curState->attr;
20379 ctxt->attrInfo->decl = (xmlSchemaTypePtr) curState->decl;
20380 ctxt->attrInfo->value = NULL;
20381 if (curState->decl != NULL)
20382 ctxt->attrInfo->typeDef = curState->decl->subtypes;
20383 else
20384 ctxt->attrInfo->typeDef = NULL;
20385 if (curState->attr->ns != NULL)
20386 ctxt->attrInfo->namespaceName =
20387 curState->attr->ns->href;
20388 else
20389 ctxt->attrInfo->namespaceName = NULL;
20390 ctxt->attrInfo->localName = curState->attr->name;
20391
20392 ctxt->nodeInfo = ctxt->attrInfo;
20393
20394#ifdef IDC_ENABLED
20395 /*
20396 * Evaluate IDCs.
20397 */
20398 if (ctxt->xpathStates != NULL) {
20399 ret = xmlSchemaXPathEvaluate(ctxt,
20400 XML_ATTRIBUTE_NODE);
20401 if (ret == -1)
20402 goto fatal_exit;
20403 }
20404
20405#endif
20406 ret = xmlSchemaCheckAttrLocallyValid(ctxt, curState);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020407 if (ret == -1)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020408 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020409 if ((ret != 0) && (ctxt->value != NULL)) {
20410 xmlSchemaFreeValue(ctxt->value);
20411 ctxt->value = NULL;
20412 }
20413 /* No break on purpose. */
20414 case XML_SCHEMAS_ATTR_CHECKED:
20415#ifdef IDC_ENABLED
20416 if (ctxt->xpathStates != NULL) {
20417 /*
20418 * Evaluate IDCs.
20419 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020420 if (ctxt->value != NULL) {
20421 ctxt->attrInfo->value = ctxt->value;
20422 ctxt->value = NULL;
20423 }
20424 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
20425 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020426 }
20427 break;
20428#endif
20429 default:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020430 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020431 }
20432 curState = curState->next;
20433 }
20434
20435 /*
20436 * Report missing and illegal attributes.
20437 */
20438 curState = ctxt->attr;
20439 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020440 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
20441 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020442 if (curState->decl != NULL) {
20443 if (curState->decl->ref != NULL)
20444 attrDecl = curState->decl->refDecl;
20445 else
20446 attrDecl = curState->decl;
20447 } else
20448 attrDecl = NULL;
20449 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
20450 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
20451 } else if (curState->state ==
20452 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
20453 xmlSchemaVCustomErr(ctxt,
20454 XML_SCHEMAV_CVC_ATTRIBUTE_2,
20455 (xmlNodePtr) attr,
20456 (xmlSchemaTypePtr) attrDecl,
20457 "The type definition is absent",
20458 NULL);
20459 } else if (curState->state ==
20460 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
20461 xmlSchemaVCustomErr(ctxt,
20462 XML_SCHEMAV_CVC_AU,
20463 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
20464 "The value does not match the fixed value "
20465 "constraint", NULL);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020466 } else if (curState->state == XML_SCHEMAS_ATTR_WILD_NO_DECL) {
20467 xmlSchemaVWildcardErr(ctxt,
20468 XML_SCHEMAV_CVC_WILDCARD,
20469 (xmlNodePtr) attr,
20470 type->attributeWildcard,
20471 "No global attribute declaration found, but "
20472 "stipulated by the strict processContents of "
20473 "the wildcard");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020474 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020475 /* TODO: "prohibited" won't ever be touched here!.
20476 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
20477 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020478 /*
20479 * TODO: One might report different error messages
20480 * for the following errors.
20481 */
20482 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020483 xmlSchemaVIllegalAttrErr(ctxt,
20484 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
20485 } else {
20486 xmlSchemaVIllegalAttrErr(ctxt,
20487 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
20488 }
20489 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000020490 }
20491 curState = curState->next;
20492 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020493 }
20494
20495 /*
20496 * Add missing default/fixed attributes.
20497 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020498 if (defAttrStates != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020499 curState = defAttrStates;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020500
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020501 while (curState != NULL) {
20502 attrDecl = curState->decl;
20503 if (attrDecl->ref != NULL)
20504 attrDecl = attrDecl->refDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020505
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020506#ifdef IDC_ENABLED
20507 /*
20508 * Evaluate IDCs on default attributes.
20509 */
20510 if (ctxt->xpathStates != NULL) {
20511 /*
20512 * Create an attribute info if needed.
20513 */
20514 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020515 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
20516 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020517 if (ctxt->attrInfo == NULL) {
20518 xmlSchemaVErrMemory(ctxt,
20519 "allocating an attribute info", NULL);
20520 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020521 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020522 ctxt->attrInfo->value = NULL;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020523 }
20524 /*
20525 * Init the attribute info.
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020526 * TODO: Hmm, maby a bit oversized this all.
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020527 */
20528 ctxt->attrInfo->flags = 0;
20529 ctxt->attrInfo->decl = (xmlSchemaTypePtr) attrDecl;
20530 ctxt->attrInfo->node = NULL;
20531 ctxt->attrInfo->typeDef = attrDecl->subtypes;
20532 ctxt->attrInfo->namespaceName = attrDecl->targetNamespace;
20533 ctxt->attrInfo->localName = attrDecl->name;
20534
20535 ctxt->nodeInfo = ctxt->attrInfo;
20536
20537 ret = xmlSchemaXPathEvaluate(ctxt,
20538 XML_ATTRIBUTE_NODE);
20539 if (ret == -1)
20540 goto fatal_exit;
20541 if (ctxt->attrInfo->value != NULL) {
20542 xmlSchemaFreeValue(ctxt->attrInfo->value);
20543 ctxt->attrInfo->value = NULL;
20544 }
20545 if (ret > 0) {
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020546 /*
20547 * IDCs will consume the precomputed default value,
20548 * so we need to clone it somehow.
20549 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020550 /*
20551 * string or anySimpleType does not create a precomputed value
20552 * by default, so it will be created here on demand.
20553 * TODO: default/fixed attributes are a bit unoptimized:
20554 * the string value will be hold by ->defValue and inside
20555 * the precomputed value.
20556 */
20557 if (attrDecl->defVal == NULL) {
20558 xmlChar *str = xmlStrdup(attrDecl->defValue);
20559
20560 if (xmlSchemaPostCreateVal(ctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000020561 ctxt->attrInfo->typeDef,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020562 str,
20563 &(attrDecl->defVal)) == -1) {
20564 FREE_AND_NULL(str)
20565 goto fatal_exit;
20566 }
20567 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020568 ctxt->attrInfo->value = xmlSchemaCopyValue(attrDecl->defVal);
20569 /* TODO: error on NULL return. */
20570 }
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020571
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020572 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
20573 goto fatal_exit;
20574 }
20575#endif
20576
20577 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
20578 /*
20579 * PSVI: Add a new attribute node to the current element.
20580 */
20581 if (attrDecl->targetNamespace == NULL) {
20582 xmlNewProp(elem, attrDecl->name, curState->value);
20583 } else {
20584 xmlNsPtr ns;
20585
20586 ns = xmlSearchNsByHref(elem->doc, elem,
20587 attrDecl->targetNamespace);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020588 if (ns == NULL) {
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020589 xmlChar prefix[12];
20590 int counter = 1;
20591
20592 attr = curState->attr;
20593 /*
20594 * Create a namespace declaration on the validation
20595 * root node if no namespace declaration is in scope.
20596 */
20597 snprintf((char *) prefix, sizeof(prefix), "p");
20598 /*
20599 * This is somehow not performant, since the ancestor
20600 * axis beyond @elem will be searched as well.
20601 */
20602 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
20603 while (ns != NULL) {
20604 if (counter > 1000) {
20605 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
20606 XML_SCHEMAV_INTERNAL,
20607 "Internal error: xmlSchemaValidateAttributes, "
20608 "could not compute a ns prefix for "
20609 "default/fixed attribute '%s'.\n",
20610 attrDecl->name, NULL);
20611
20612 break;
20613 }
20614 snprintf((char *) prefix,
20615 sizeof(prefix), "p%d", counter++);
20616 ns = xmlSearchNs(elem->doc, elem,
20617 BAD_CAST prefix);
20618 }
20619 if (ns == NULL) {
20620 ns = xmlNewNs(ctxt->validationRoot,
20621 attrDecl->targetNamespace, BAD_CAST prefix);
20622 xmlNewNsProp(elem, ns, attrDecl->name,
20623 curState->value);
20624 }
20625 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020626 xmlNewNsProp(elem, ns, attrDecl->name,
20627 curState->value);
20628 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020629 }
20630 }
20631 curState = curState->next;
20632 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000020633 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020634 ret = ctxt->err;
20635 goto exit;
20636
20637fatal_exit:
20638 ret = -1;
20639
20640exit:
20641
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020642 if (defAttrStates != NULL)
20643 xmlSchemaFreeAttributeStates(defAttrStates);
20644
Daniel Veillard3646d642004-06-02 19:19:14 +000020645#ifdef DEBUG_ATTR_VALIDATION
20646 if (redundant)
20647 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020648 "xmlSchemaValidateAttributes: redundant call by "
20649 "type: %s\n", type->name);
Daniel Veillard3646d642004-06-02 19:19:14 +000020650#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020651 ctxt->nodeInfo = ctxt->elemInfos[ctxt->depth];
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020652 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020653 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020654}
20655
20656/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020657 * xmlSchemaStartValidation:
Daniel Veillard4255d502002-04-16 15:50:10 +000020658 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000020659 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020660 * The starting point of the validation, called by
20661 * xmlSchemaValidateDocument and xmlSchemaValidateOneElement.
Daniel Veillard4255d502002-04-16 15:50:10 +000020662 *
20663 * Returns 0 if the element is schemas valid, a positive error code
20664 * number otherwise and -1 in case of internal or API error.
20665 */
20666static int
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020667xmlSchemaStartValidation(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020668{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020669 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020670 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020671
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020672 ctxt->err = 0;
20673 ctxt->nberrors = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020674 if (ctxt->schema == NULL) {
20675 /*
20676 * No schema was specified at time of creation of the validation
20677 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
20678 * of the instance to build a schema.
20679 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020680 if (ctxt->pctxt == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020681 if (xmlSchemaCreatePCtxtOnVCtxt(ctxt) == -1)
20682 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020683 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
20684 if (ctxt->schema == NULL)
20685 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020686 ctxt->xsiAssemble = 1;
20687 } else
20688 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020689 /*
20690 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000020691 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020692 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020693 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
20694 if (ret == -1) {
20695 xmlSchemaVCustomErr(ctxt,
20696 XML_SCHEMAV_INTERNAL,
20697 ctxt->node, NULL,
20698 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020699 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020700 }
20701 /*
20702 * NOTE: We won't react on schema parser errors here.
20703 * TODO: But a warning would be nice.
20704 */
20705 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020706 if (ret != -1) {
20707 if (ctxt->node->ns != NULL)
20708 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
20709 ctxt->node->ns->href);
20710 else
20711 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
20712
20713 if (elemDecl == NULL) {
20714 xmlSchemaVCustomErr(ctxt,
20715 XML_SCHEMAV_CVC_ELT_1,
20716 ctxt->node, NULL,
20717 "No matching global declaration available", NULL);
20718 ret = XML_SCHEMAV_CVC_ELT_1;
20719 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020720 /*
20721 * Augment the IDC definitions.
20722 */
20723 if (ctxt->schema->idcDef != NULL) {
20724 xmlHashScan(ctxt->schema->idcDef,
20725 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
20726 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020727 ctxt->depth = -1;
20728 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020729 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020730 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020731 if (ret < 0) {
20732 xmlSchemaVCustomErr(ctxt,
20733 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
20734 "Internal error: xmlSchemaValidateElement, "
20735 "calling validation by declaration", NULL);
20736 }
20737 }
20738 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020739
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020740 if (ctxt->xsiAssemble) {
20741 if (ctxt->schema != NULL) {
20742 xmlSchemaFree(ctxt->schema);
20743 ctxt->schema = NULL;
20744 }
Daniel Veillard4255d502002-04-16 15:50:10 +000020745 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020746 xmlSchemaClearValidCtxt(ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020747 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020748}
20749
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020750
Daniel Veillard4255d502002-04-16 15:50:10 +000020751/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020752 * xmlSchemaValidateOneElement:
20753 * @ctxt: a schema validation context
20754 * @elem: an element node
20755 *
20756 * Validate a branch of a tree, starting with the given @elem.
20757 *
20758 * Returns 0 if the element and its subtree is valid, a positive error
20759 * code number otherwise and -1 in case of an internal or API error.
20760 */
20761int
20762xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
20763{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020764 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020765 return (-1);
20766
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020767 if (ctxt->schema == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020768 xmlSchemaVErr(ctxt, NULL,
20769 XML_SCHEMAV_INTERNAL,
20770 "API error: xmlSchemaValidateOneElement, "
20771 "no schema specified.\n", NULL, NULL);
20772 return (-1);
20773 }
20774
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020775 ctxt->doc = elem->doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020776 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020777 ctxt->validationRoot = elem;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020778 return (xmlSchemaStartValidation(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000020779}
20780
20781/************************************************************************
20782 * *
20783 * SAX Validation code *
20784 * *
20785 ************************************************************************/
20786
20787/************************************************************************
20788 * *
20789 * Validation interfaces *
20790 * *
20791 ************************************************************************/
20792
20793/**
20794 * xmlSchemaNewValidCtxt:
20795 * @schema: a precompiled XML Schemas
20796 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020797 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000020798 *
20799 * Returns the validation context or NULL in case of error
20800 */
20801xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020802xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
20803{
Daniel Veillard4255d502002-04-16 15:50:10 +000020804 xmlSchemaValidCtxtPtr ret;
20805
20806 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
20807 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020808 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000020809 return (NULL);
20810 }
20811 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000020812 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000020813 return (ret);
20814}
20815
20816/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020817 * xmlSchemaClearValidCtxt:
20818 * @ctxt: the schema validation context
20819 *
20820 * Free the resources associated to the schema validation context;
20821 * leaves some fields alive intended for reuse of the context.
20822 */
20823static void
20824xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
20825{
20826 if (vctxt == NULL)
20827 return;
20828
20829 vctxt->validationRoot = NULL;
20830 if (vctxt->attr != NULL) {
20831 xmlSchemaFreeAttributeStates(vctxt->attr);
20832 vctxt->attr = NULL;
20833 }
20834 if (vctxt->value != NULL) {
20835 xmlSchemaFreeValue(vctxt->value);
20836 vctxt->value = NULL;
20837 }
20838 /*
20839 * Augmented IDC information.
20840 */
20841 if (vctxt->aidcs != NULL) {
20842 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
20843 do {
20844 next = cur->next;
20845 xmlFree(cur);
20846 cur = next;
20847 } while (cur != NULL);
20848 vctxt->aidcs = NULL;
20849 }
20850 if (vctxt->idcNodes != NULL) {
20851 int i;
20852 xmlSchemaPSVIIDCNodePtr item;
20853
20854 for (i = 0; i < vctxt->nbIdcNodes; i++) {
20855 item = vctxt->idcNodes[i];
20856 xmlFree(item->keys);
20857 xmlFree(item);
20858 }
20859 xmlFree(vctxt->idcNodes);
20860 vctxt->idcNodes = NULL;
20861 }
20862 /*
20863 * Note that we won't delete the XPath state pool here.
20864 */
20865 if (vctxt->xpathStates != NULL) {
20866 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
20867 vctxt->xpathStates = NULL;
20868 }
20869 if (vctxt->attrInfo != NULL) {
20870 if (vctxt->attrInfo->value != NULL) {
20871 xmlSchemaFreeValue(vctxt->attrInfo->value);
20872 }
20873 memset(vctxt->attrInfo, 0, sizeof(xmlSchemaNodeInfo));
20874 }
20875 if (vctxt->elemInfos != NULL) {
20876 int i;
20877 xmlSchemaNodeInfoPtr info;
20878
20879 for (i = 0; i < vctxt->sizeElemInfos; i++) {
20880 info = vctxt->elemInfos[i];
20881 if (info == NULL)
20882 break;
20883 if (info->value != NULL) {
20884 xmlSchemaFreeValue(info->value);
20885 info->value = NULL;
20886 }
20887 if (info->idcMatchers != NULL) {
20888 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
20889 info->idcMatchers = NULL;
20890 }
20891 if (info->idcTable != NULL) {
20892 xmlSchemaIDCFreeIDCTable(info->idcTable);
20893 info->idcTable = NULL;
20894 }
20895 }
20896 }
20897}
20898
20899/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020900 * xmlSchemaFreeValidCtxt:
20901 * @ctxt: the schema validation context
20902 *
20903 * Free the resources associated to the schema validation context
20904 */
20905void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020906xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
20907{
Daniel Veillard4255d502002-04-16 15:50:10 +000020908 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020909 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000020910 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000020911 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000020912 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020913 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020914 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020915 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020916 if (ctxt->idcNodes != NULL) {
20917 int i;
20918 xmlSchemaPSVIIDCNodePtr item;
20919
20920 for (i = 0; i < ctxt->nbIdcNodes; i++) {
20921 item = ctxt->idcNodes[i];
20922 xmlFree(item->keys);
20923 xmlFree(item);
20924 }
20925 xmlFree(ctxt->idcNodes);
20926 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020927 if (ctxt->idcKeys != NULL) {
20928 int i;
20929 for (i = 0; i < ctxt->nbIdcKeys; i++)
20930 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
20931 xmlFree(ctxt->idcKeys);
20932 }
20933
20934 if (ctxt->xpathStates != NULL)
20935 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
20936 if (ctxt->xpathStatePool != NULL)
20937 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
20938
20939 /*
20940 * Augmented IDC information.
20941 */
20942 if (ctxt->aidcs != NULL) {
20943 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
20944 do {
20945 next = cur->next;
20946 xmlFree(cur);
20947 cur = next;
20948 } while (cur != NULL);
20949 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020950 if (ctxt->attrInfo != NULL) {
20951 if (ctxt->attrInfo->value != NULL)
20952 xmlSchemaFreeValue(ctxt->attrInfo->value);
20953 xmlFree(ctxt->attrInfo);
20954 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020955 if (ctxt->elemInfos != NULL) {
20956 int i;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020957 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020958
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020959 for (i = 0; i < ctxt->sizeElemInfos; i++) {
20960 info = ctxt->elemInfos[i];
20961 if (info == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020962 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020963 if (info->value != NULL)
20964 xmlSchemaFreeValue(info->value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020965 if (info->idcMatchers != NULL)
20966 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020967 if (info->idcTable != NULL)
20968 xmlSchemaIDCFreeIDCTable(info->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020969 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020970 * TODO: Don't know if those will have to be freed if in streaming
20971 * mode.
20972 *
20973 * xmlFree(info->localName);
20974 * if (info->namespaceName != NULL)
20975 * xmlFree(info->namespaceName);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020976 */
20977 xmlFree(info);
20978 }
20979 xmlFree(ctxt->elemInfos);
20980 }
Daniel Veillard4255d502002-04-16 15:50:10 +000020981 xmlFree(ctxt);
20982}
20983
20984/**
20985 * xmlSchemaSetValidErrors:
20986 * @ctxt: a schema validation context
20987 * @err: the error function
20988 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000020989 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000020990 *
William M. Brack2f2a6632004-08-20 23:09:47 +000020991 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000020992 */
20993void
20994xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020995 xmlSchemaValidityErrorFunc err,
20996 xmlSchemaValidityWarningFunc warn, void *ctx)
20997{
Daniel Veillard4255d502002-04-16 15:50:10 +000020998 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020999 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000021000 ctxt->error = err;
21001 ctxt->warning = warn;
21002 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021003 if (ctxt->pctxt != NULL)
21004 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000021005}
21006
21007/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000021008 * xmlSchemaGetValidErrors:
21009 * @ctxt: a XML-Schema validation context
21010 * @err: the error function result
21011 * @warn: the warning function result
21012 * @ctx: the functions context result
21013 *
21014 * Get the error and warning callback informations
21015 *
21016 * Returns -1 in case of error and 0 otherwise
21017 */
21018int
21019xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
21020 xmlSchemaValidityErrorFunc * err,
21021 xmlSchemaValidityWarningFunc * warn, void **ctx)
21022{
21023 if (ctxt == NULL)
21024 return (-1);
21025 if (err != NULL)
21026 *err = ctxt->error;
21027 if (warn != NULL)
21028 *warn = ctxt->warning;
21029 if (ctx != NULL)
21030 *ctx = ctxt->userData;
21031 return (0);
21032}
21033
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021034
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021035/**
Daniel Veillard6927b102004-10-27 17:29:04 +000021036 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021037 * @ctxt: a schema validation context
21038 * @options: a combination of xmlSchemaValidOption
21039 *
21040 * Sets the options to be used during the validation.
21041 *
21042 * Returns 0 in case of success, -1 in case of an
21043 * API error.
21044 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021045int
21046xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
21047 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021048
21049{
21050 int i;
21051
21052 if (ctxt == NULL)
21053 return (-1);
21054 /*
21055 * WARNING: Change the start value if adding to the
21056 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021057 * TODO: Is there an other, more easy to maintain,
21058 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021059 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021060 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021061 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021062 xmlSchemaVErr(ctxt, NULL,
21063 XML_SCHEMAV_INTERNAL,
21064 "Internal error: xmlSchemaSetValidOptions, "
21065 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021066 return (-1);
21067 }
21068 }
21069 ctxt->options = options;
21070 return (0);
21071}
21072
21073/**
Daniel Veillard6927b102004-10-27 17:29:04 +000021074 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021075 * @ctxt: a schema validation context
21076 *
William M. Brack21e4ef22005-01-02 09:53:13 +000021077 * Get the validation context options.
21078 *
21079 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021080 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021081int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021082xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
21083
21084{
21085 if (ctxt == NULL)
21086 return (-1);
21087 else
21088 return (ctxt->options);
21089}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021090
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021091
Daniel Veillard259f0df2004-08-18 09:13:18 +000021092/**
Daniel Veillard4255d502002-04-16 15:50:10 +000021093 * xmlSchemaValidateDoc:
21094 * @ctxt: a schema validation context
21095 * @doc: a parsed document tree
21096 *
21097 * Validate a document tree in memory.
21098 *
21099 * Returns 0 if the document is schemas valid, a positive error code
21100 * number otherwise and -1 in case of internal or API error.
21101 */
21102int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021103xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
21104{
Daniel Veillard4255d502002-04-16 15:50:10 +000021105 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021106 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000021107
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000021108 ctxt->doc = doc;
21109 ctxt->node = xmlDocGetRootElement(doc);
21110 if (ctxt->node == NULL) {
21111 xmlSchemaVCustomErr(ctxt,
21112 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
21113 (xmlNodePtr) doc, NULL,
21114 "The document has no document element", NULL);
21115 return (ctxt->err);
21116 }
21117 ctxt->validationRoot = ctxt->node;
21118 xmlSchemaStartValidation(ctxt);
21119
21120 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000021121}
21122
21123/**
21124 * xmlSchemaValidateStream:
21125 * @ctxt: a schema validation context
21126 * @input: the input to use for reading the data
21127 * @enc: an optional encoding information
21128 * @sax: a SAX handler for the resulting events
21129 * @user_data: the context to provide to the SAX handler.
21130 *
21131 * Validate a document tree in memory.
21132 *
21133 * Returns 0 if the document is schemas valid, a positive error code
21134 * number otherwise and -1 in case of internal or API error.
21135 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021136int
Daniel Veillard4255d502002-04-16 15:50:10 +000021137xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021138 xmlParserInputBufferPtr input, xmlCharEncoding enc,
21139 xmlSAXHandlerPtr sax, void *user_data)
21140{
Daniel Veillard4255d502002-04-16 15:50:10 +000021141 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021142 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000021143 ctxt->input = input;
21144 ctxt->enc = enc;
21145 ctxt->sax = sax;
21146 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021147 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000021148}
21149
21150#endif /* LIBXML_SCHEMAS_ENABLED */