blob: 6cffc4fb23b3dfc57a30701c63bed63377270537 [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. Buchcikb06b4de2005-02-17 19:00:23 +000057/* #define IDC_ENABLED 1 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000058
59/* #define IDC_VALUE_SUPPORT 1 */
60
61/* #define IDC_XPATH_SUPPORT 1 */
62
63/* #define DEBUG_IDC 1 */
64
Daniel Veillardc0826a72004-08-10 14:17:33 +000065
Daniel Veillard4255d502002-04-16 15:50:10 +000066#define UNBOUNDED (1 << 30)
67#define TODO \
68 xmlGenericError(xmlGenericErrorContext, \
69 "Unimplemented block at %s:%d\n", \
70 __FILE__, __LINE__);
71
William M. Brack2f2a6632004-08-20 23:09:47 +000072#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000073
Daniel Veillard4255d502002-04-16 15:50:10 +000074/*
75 * The XML Schemas namespaces
76 */
77static const xmlChar *xmlSchemaNs = (const xmlChar *)
78 "http://www.w3.org/2001/XMLSchema";
79
80static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
81 "http://www.w3.org/2001/XMLSchema-instance";
82
Daniel Veillardc0826a72004-08-10 14:17:33 +000083static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
84 "Element decl.";
85static const xmlChar *xmlSchemaElemDesElemRef = (const xmlChar *)
86 "Element ref.";
87static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
88 "Attribute decl.";
89static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
90 "Attribute ref.";
91static const xmlChar *xmlSchemaElemDesST = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000092 "simple type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000093static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000094 "complex type";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000095static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
96 "Model group";
97static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
98 "Model group ref.";
Daniel Veillardc0826a72004-08-10 14:17:33 +000099
Daniel Veillard4255d502002-04-16 15:50:10 +0000100#define IS_SCHEMA(node, type) \
101 ((node != NULL) && (node->ns != NULL) && \
102 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
103 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
104
Daniel Veillardc0826a72004-08-10 14:17:33 +0000105#define FREE_AND_NULL(str) \
106 if (str != NULL) { \
107 xmlFree(str); \
108 str = NULL; \
109 }
110
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000111#define IS_ANYTYPE(item) \
112 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
113 (item->builtInType == XML_SCHEMAS_ANYTYPE))
114
115#define IS_COMPLEX_TYPE(item) \
116 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
117 (item->builtInType == XML_SCHEMAS_ANYTYPE))
118
119#define IS_SIMPLE_TYPE(item) \
120 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
121 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
122 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
123
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +0000124/*
Daniel Veillardc0826a72004-08-10 14:17:33 +0000125#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
126#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
127#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +0000128*/
Daniel Veillardc0826a72004-08-10 14:17:33 +0000129
Daniel Veillard4255d502002-04-16 15:50:10 +0000130#define XML_SCHEMAS_PARSE_ERROR 1
131
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000132#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
133
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000134
135/*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000136* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
137* locate schemata to be imported
138* using the namespace name; otherwise
139* the location URI will be used */
140
141/*
142* xmlSchemaParserOption:
143*
144* This is the set of XML Schema parser options.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000145*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000146typedef enum {
147 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000148 * locate schemata to be imported
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000149 * using the namespace name; otherwise
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000150 * the location URI will be used *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000151} xmlSchemaParserOption;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000152*/
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000153
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000154typedef struct _xmlSchemaAssemble xmlSchemaAssemble;
155typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
156struct _xmlSchemaAssemble {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000157 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000158 int nbItems; /* used for dynamic addition of schemata */
159 int sizeItems; /* used for dynamic addition of schemata */
160};
161
Daniel Veillard4255d502002-04-16 15:50:10 +0000162struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000163 void *userData; /* user specific data block */
164 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
165 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000166 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000167 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000168 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000169
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000170 xmlSchemaPtr topschema; /* The main schema */
171 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
172
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000173 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000174 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000175 int counter;
176
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000177 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000178 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000179 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000180
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000181 const char *buffer;
182 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000183
Daniel Veillard4255d502002-04-16 15:50:10 +0000184 /*
185 * Used to build complex element content models
186 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000187 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000188 xmlAutomataStatePtr start;
189 xmlAutomataStatePtr end;
190 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000191
192 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000193 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000194 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
195 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000196 xmlSchemaAssemblePtr assemble;
197 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000198 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard4255d502002-04-16 15:50:10 +0000199};
200
201
202#define XML_SCHEMAS_ATTR_UNKNOWN 1
203#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000204#define XML_SCHEMAS_ATTR_PROHIBITED 3
205#define XML_SCHEMAS_ATTR_MISSING 4
206#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
207#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000208#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
209#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000210#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
211#define XML_SCHEMAS_ATTR_WILD_NO_DECL 10
Daniel Veillard4255d502002-04-16 15:50:10 +0000212
213typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
214typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
215struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000216 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000217 xmlAttrPtr attr;
218 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000219 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000220 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000221};
222
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000223typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
224typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
225struct _xmlSchemaBasicItem {
226 xmlSchemaTypeType type;
227 xmlSchemaAnnotPtr annot;
228};
229
230typedef struct _xmlSchemaItemQNRef xmlSchemaItemQNRef;
231typedef xmlSchemaItemQNRef *xmlSchemaItemQNRefPtr;
232struct _xmlSchemaItemQNRef {
233 xmlSchemaBasicItemPtr item;
234 const xmlChar *name;
235 const xmlChar *targetNamespace;
236};
237
238typedef struct _xmlSchemaIDC xmlSchemaIDC;
239typedef xmlSchemaIDC *xmlSchemaIDCPtr;
240
241/**
242 * xmlSchemaIDCSelect:
243 *
244 * The identity-constraint "field" and "selector" item, holding the
245 * XPath expression.
246 */
247typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
248typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
249struct _xmlSchemaIDCSelect {
250 xmlSchemaIDCSelectPtr next;
251 xmlSchemaIDCPtr idc;
252 int index; /* an index position if significant for IDC key-sequences */
253 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000254 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000255};
256
257/**
258 * xmlSchemaIDC:
259 *
260 * The identity-constraint definition component.
261 */
262
263struct _xmlSchemaIDC {
264 xmlSchemaTypeType type;
265 xmlSchemaAnnotPtr annot;
266 xmlSchemaIDCPtr next;
267 xmlNodePtr node;
268 const xmlChar *name;
269 const xmlChar *targetNamespace;
270 xmlSchemaIDCSelectPtr selector;
271 xmlSchemaIDCSelectPtr fields;
272 int nbFields;
273 xmlSchemaItemQNRefPtr ref;
274};
275
276/**
277 * xmlSchemaIDCAug:
278 *
279 * The augmented IDC information used for validation.
280 */
281typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
282typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
283struct _xmlSchemaIDCAug {
284 xmlSchemaIDCAugPtr next; /* next in a list */
285 xmlSchemaIDCPtr def; /* the IDC definition */
286 int bubbleDepth; /* the lowest level to which IDC
287 tables need to be bubbled upwards */
288};
289
290/**
291 * xmlSchemaPSVIIDCKeySequence:
292 *
293 * The key sequence of a node table item.
294 */
295typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
296typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
297struct _xmlSchemaPSVIIDCKey {
298 xmlSchemaTypePtr type;
299 xmlSchemaValPtr compValue;
300};
301
302/**
303 * xmlSchemaPSVIIDCNode:
304 *
305 * The node table item of a node table.
306 */
307typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
308typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
309struct _xmlSchemaPSVIIDCNode {
310 xmlNodePtr node;
311 xmlSchemaPSVIIDCKeyPtr *keys;
312};
313
314/**
315 * xmlSchemaPSVIIDCBinding:
316 *
317 * The identity-constraint binding item of the [identity-constraint table].
318 */
319typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
320typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
321struct _xmlSchemaPSVIIDCBinding {
322 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
323 xmlSchemaIDCPtr definition; /* the IDC definition */
324 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
325 int nbNodes; /* number of entries in the node table */
326 int sizeNodes; /* size of the node table */
327 int nbDupls; /* number of already identified duplicates in the node
328 table */
329 /* int nbKeys; number of keys in each key-sequence */
330};
331
332#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
333#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
334
335#define XPATH_STATE_OBJ_MATCHES -2
336#define XPATH_STATE_OBJ_BLOCKED -3
337
338typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
339typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
340
341/**
342 * xmlSchemaIDCStateObj:
343 *
344 * The state object used to evaluate XPath expressions.
345 */
346typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
347typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
348struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000349 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000350 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000351 int depth; /* depth of creation */
352 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000353 int nbHistory;
354 int sizeHistory;
355 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
356 matcher */
357 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000358 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000359};
360
361#define IDC_MATCHER 0
362
363/**
364 * xmlSchemaIDCMatcher:
365 *
366 * Used to IDC selectors (and fields) successively.
367 */
368struct _xmlSchemaIDCMatcher {
369 int type;
370 int depth; /* the tree depth at creation time */
371 xmlSchemaIDCMatcherPtr next; /* next in the list */
372 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
373 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
374 elements */
375 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000376 int targetDepth;
377};
378
379/*
380* Element info flags.
381*/
382#define XML_SCHEMA_ELEM_INFO_VALUE_NEEDED 1<<0
383
384/**
385 * xmlSchemaElemInfo:
386 *
387 * Holds information of an element node.
388 */
389typedef struct _xmlSchemaElemInfo xmlSchemaElemInfo;
390typedef xmlSchemaElemInfo *xmlSchemaElemInfoPtr;
391struct _xmlSchemaElemInfo {
392 int depth;
393 int flags; /* combination of element info flags */
394 xmlNodePtr node;
395 const xmlChar *localName;
396 const xmlChar *namespaceName;
397 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +0000398 xmlSchemaTypePtr decl; /* the element/attribute declaration */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000399 xmlSchemaValPtr value; /* the pre-computed value if any */
400 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
401 for the scope element*/
402 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
403 element */
404};
405
Daniel Veillard4255d502002-04-16 15:50:10 +0000406/**
407 * xmlSchemaValidCtxt:
408 *
409 * A Schemas validation context
410 */
411
412struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000413 void *userData; /* user specific data block */
414 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000415 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000416 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000417
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000418 xmlSchemaPtr schema; /* The schema in use */
419 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000420 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000421 xmlCharEncoding enc;
422 xmlSAXHandlerPtr sax;
423 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000424
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000425 xmlDocPtr myDoc;
426 int err;
427 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000428
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000429 xmlNodePtr node;
430 xmlNodePtr cur;
431 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000432
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000433 xmlRegExecCtxtPtr regexp;
434 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000435
Daniel Veillard3646d642004-06-02 19:19:14 +0000436 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000437 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000438 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000439 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000440 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000441 xmlNodePtr validationRoot;
442 xmlSchemaParserCtxtPtr pctxt;
443 int xsiAssemble;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000444#ifdef ELEM_INFO_ENABLED
445 int depth;
446 xmlSchemaElemInfoPtr *elemInfos; /* array of element informations */
447 int sizeElemInfos;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +0000448 xmlSchemaElemInfoPtr nodeInfo; /* the current element information */
449 xmlSchemaElemInfoPtr attrInfo; /* node infor for the current attribute */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000450#endif
451#ifdef IDC_ENABLED
452 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
453
454 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
455 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
456
457 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
458 int nbIdcNodes;
459 int sizeIdcNodes;
460
461 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
462 int nbIdcKeys;
463 int sizeIdcKeys;
464#endif
Daniel Veillard4255d502002-04-16 15:50:10 +0000465};
466
Daniel Veillard1d913862003-11-21 00:28:39 +0000467/*
468 * These are the entries in the schemas importSchemas hash table
469 */
470typedef struct _xmlSchemaImport xmlSchemaImport;
471typedef xmlSchemaImport *xmlSchemaImportPtr;
472struct _xmlSchemaImport {
473 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000474 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000475 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000476 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000477};
Daniel Veillard4255d502002-04-16 15:50:10 +0000478
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000479/*
480 * These are the entries associated to includes in a schemas
481 */
482typedef struct _xmlSchemaInclude xmlSchemaInclude;
483typedef xmlSchemaInclude *xmlSchemaIncludePtr;
484struct _xmlSchemaInclude {
485 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000486 const xmlChar *schemaLocation;
487 xmlDocPtr doc;
488};
489
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000490typedef struct _xmlSchemaParticle xmlSchemaParticle;
491typedef xmlSchemaParticle *xmlSchemaParticlePtr;
492struct _xmlSchemaParticle {
493 xmlSchemaTypeType type;
494 xmlSchemaParticlePtr next; /* the next particle if in a list */
495 int minOccurs;
496 int maxOccurs;
497 xmlSchemaTypePtr term;
498};
499
500
501typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
502typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
503struct _xmlSchemaModelGroup {
504 xmlSchemaTypeType type;
505 int compositor; /* one of all, choice or sequence */
506 xmlSchemaParticlePtr particles; /* list of particles */
507 xmlSchemaAnnotPtr annot;
508};
509
510typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
511typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
512struct _xmlSchemaModelGroupDef {
513 xmlSchemaTypeType type;
514 const xmlChar *name;
515 const xmlChar *targetNamespace;
516 xmlSchemaModelGroupPtr modelGroup;
517 xmlSchemaAnnotPtr annot;
518};
519
Daniel Veillard4255d502002-04-16 15:50:10 +0000520/************************************************************************
521 * *
522 * Some predeclarations *
523 * *
524 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000525
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000526static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
527 xmlSchemaPtr schema,
528 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000529static void
530xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
531 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000532static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000533xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
534static int
535xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000536 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000537 const xmlChar *value,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000538 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000539 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000540 int normalize,
541 int checkNodes);
542static int
543xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
544 xmlSchemaElementPtr elemDecl);
545static int
546xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
547 xmlSchemaTypePtr type);
548static int
549xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000550static int
551xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
552 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000553static void
554xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
555 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
William M. Brack87640d52004-04-17 14:58:15 +0000556
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000557/************************************************************************
558 * *
559 * Datatype error handlers *
560 * *
561 ************************************************************************/
562
563/**
564 * xmlSchemaPErrMemory:
565 * @node: a context node
566 * @extra: extra informations
567 *
568 * Handle an out of memory condition
569 */
570static void
571xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
572 const char *extra, xmlNodePtr node)
573{
574 if (ctxt != NULL)
575 ctxt->nberrors++;
576 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
577 extra);
578}
579
580/**
581 * xmlSchemaPErr:
582 * @ctxt: the parsing context
583 * @node: the context node
584 * @error: the error code
585 * @msg: the error message
586 * @str1: extra data
587 * @str2: extra data
588 *
589 * Handle a parser error
590 */
591static void
592xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
593 const char *msg, const xmlChar * str1, const xmlChar * str2)
594{
595 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000596 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000597 void *data = NULL;
598
599 if (ctxt != NULL) {
600 ctxt->nberrors++;
601 channel = ctxt->error;
602 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000603 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000604 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000605 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000606 error, XML_ERR_ERROR, NULL, 0,
607 (const char *) str1, (const char *) str2, NULL, 0, 0,
608 msg, str1, str2);
609}
610
611/**
612 * xmlSchemaPErr2:
613 * @ctxt: the parsing context
614 * @node: the context node
615 * @node: the current child
616 * @error: the error code
617 * @msg: the error message
618 * @str1: extra data
619 * @str2: extra data
620 *
621 * Handle a parser error
622 */
623static void
624xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
625 xmlNodePtr child, int error,
626 const char *msg, const xmlChar * str1, const xmlChar * str2)
627{
628 if (child != NULL)
629 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
630 else
631 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
632}
633
Daniel Veillard01fa6152004-06-29 17:04:39 +0000634
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000635/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000636 * xmlSchemaPErrExt:
637 * @ctxt: the parsing context
638 * @node: the context node
639 * @error: the error code
640 * @strData1: extra data
641 * @strData2: extra data
642 * @strData3: extra data
643 * @msg: the message
644 * @str1: extra parameter for the message display
645 * @str2: extra parameter for the message display
646 * @str3: extra parameter for the message display
647 * @str4: extra parameter for the message display
648 * @str5: extra parameter for the message display
649 *
650 * Handle a parser error
651 */
652static void
653xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
654 const xmlChar * strData1, const xmlChar * strData2,
655 const xmlChar * strData3, const char *msg, const xmlChar * str1,
656 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
657 const xmlChar * str5)
658{
659
660 xmlGenericErrorFunc channel = NULL;
661 xmlStructuredErrorFunc schannel = NULL;
662 void *data = NULL;
663
664 if (ctxt != NULL) {
665 ctxt->nberrors++;
666 channel = ctxt->error;
667 data = ctxt->userData;
668 schannel = ctxt->serror;
669 }
670 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
671 error, XML_ERR_ERROR, NULL, 0,
672 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000673 (const char *) strData3, 0, 0, msg, str1, str2,
674 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000675}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000676
Daniel Veillard3646d642004-06-02 19:19:14 +0000677
678/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000679 * xmlSchemaVTypeErrMemory:
680 * @node: a context node
681 * @extra: extra informations
682 *
683 * Handle an out of memory condition
684 */
685static void
686xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
687 const char *extra, xmlNodePtr node)
688{
689 if (ctxt != NULL) {
690 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000691 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000692 }
693 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
694 extra);
695}
696
697/**
698 * xmlSchemaVErr3:
699 * @ctxt: the validation context
700 * @node: the context node
701 * @error: the error code
702 * @msg: the error message
703 * @str1: extra data
704 * @str2: extra data
705 * @str3: extra data
706 *
707 * Handle a validation error
708 */
709static void
710xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
711 const char *msg, const xmlChar *str1, const xmlChar *str2,
712 const xmlChar *str3)
713{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000714 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000715 xmlGenericErrorFunc channel = NULL;
716 void *data = NULL;
717
718 if (ctxt != NULL) {
719 ctxt->nberrors++;
720 ctxt->err = error;
721 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000722 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000723 data = ctxt->userData;
724 }
725 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000726 /* Removed, since the old schema error codes have been
727 * substituted for the global error codes.
728 *
729 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
730 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000731 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000732 error, XML_ERR_ERROR, NULL, 0,
733 (const char *) str1, (const char *) str2,
734 (const char *) str3, 0, 0,
735 msg, str1, str2, str3);
736}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000737
738/**
739 * xmlSchemaVErrExt:
740 * @ctxt: the validation context
741 * @node: the context node
742 * @error: the error code
743 * @msg: the message
744 * @str1: extra parameter for the message display
745 * @str2: extra parameter for the message display
746 * @str3: extra parameter for the message display
747 * @str4: extra parameter for the message display
748 * @str5: extra parameter for the message display
749 *
750 * Handle a validation error
751 */
752static void
753xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
754 const char *msg, const xmlChar * str1,
755 const xmlChar * str2, const xmlChar * str3,
756 const xmlChar * str4, const xmlChar * str5)
757{
758 xmlStructuredErrorFunc schannel = NULL;
759 xmlGenericErrorFunc channel = NULL;
760 void *data = NULL;
761
762 if (ctxt != NULL) {
763 ctxt->nberrors++;
764 ctxt->err = error;
765 channel = ctxt->error;
766 schannel = ctxt->serror;
767 data = ctxt->userData;
768 }
769 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000770 /* Removed, since the old schema error codes have been
771 * substituted for the global error codes.
772 *
773 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
774 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000775 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
776 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
777 msg, str1, str2, str3, str4, str5);
778}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000779/**
780 * xmlSchemaVErr:
781 * @ctxt: the validation context
782 * @node: the context node
783 * @error: the error code
784 * @msg: the error message
785 * @str1: extra data
786 * @str2: extra data
787 *
788 * Handle a validation error
789 */
790static void
791xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
792 const char *msg, const xmlChar * str1, const xmlChar * str2)
793{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000794 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000795 xmlGenericErrorFunc channel = NULL;
796 void *data = NULL;
797
798 if (ctxt != NULL) {
799 ctxt->nberrors++;
800 ctxt->err = error;
801 channel = ctxt->error;
802 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000803 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000804 }
805 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000806 /* Removed, since the old schema error codes have been
807 * substituted for the global error codes.
808 *
809 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
810 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000811 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000812 error, XML_ERR_ERROR, NULL, 0,
813 (const char *) str1, (const char *) str2, NULL, 0, 0,
814 msg, str1, str2);
815}
Daniel Veillard4255d502002-04-16 15:50:10 +0000816
Daniel Veillardc0826a72004-08-10 14:17:33 +0000817/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000818 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000819 * @attr: the attribute declaration/use
820 *
821 * Returns the name of the attribute; if the attribute
822 * is a reference, the name of the referenced global type will be returned.
823 */
824static const xmlChar *
825xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
826{
827 if (attr->ref != NULL)
828 return(attr->ref);
829 else
830 return(attr->name);
831}
832
833/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000834 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000835 * @type: the type (element or attribute)
836 *
837 * Returns the target namespace URI of the type; if the type is a reference,
838 * the target namespace of the referenced type will be returned.
839 */
840static const xmlChar *
841xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
842{
843 if (attr->ref != NULL)
844 return (attr->refNs);
845 else
846 return(attr->targetNamespace);
847}
848
849/**
850 * xmlSchemaFormatNsUriLocal:
851 * @buf: the string buffer
852 * @uri: the namespace URI
853 * @local: the local name
854 *
855 * Returns a representation of the given URI used
856 * for error reports.
857 *
858 * Returns an empty string, if @ns is NULL, a formatted
859 * string otherwise.
860 */
861static const xmlChar*
862xmlSchemaFormatNsUriLocal(xmlChar **buf,
863 const xmlChar *uri, const xmlChar *local)
864{
865 if (*buf != NULL)
866 xmlFree(*buf);
867 if (uri == NULL) {
868 *buf = xmlStrdup(BAD_CAST "{'");
869 *buf = xmlStrcat(*buf, local);
870 } else {
871 *buf = xmlStrdup(BAD_CAST "{'");
872 *buf = xmlStrcat(*buf, uri);
873 *buf = xmlStrcat(*buf, BAD_CAST "', '");
874 *buf = xmlStrcat(*buf, local);
875 }
876 *buf = xmlStrcat(*buf, BAD_CAST "'}");
877 return ((const xmlChar *) *buf);
878}
879
880/**
881 * xmlSchemaFormatNsPrefixLocal:
882 * @buf: the string buffer
883 * @ns: the namespace
884 * @local: the local name
885 *
886 * Returns a representation of the given URI used
887 * for error reports.
888 *
889 * Returns an empty string, if @ns is NULL, a formatted
890 * string otherwise.
891 */
892static const xmlChar*
893xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
894 xmlNsPtr ns, const xmlChar *local)
895{
896 if (*buf != NULL) {
897 xmlFree(*buf);
898 *buf = NULL;
899 }
900 if ((ns == NULL) || (ns->prefix == NULL))
901 return(local);
902 else {
903 *buf = xmlStrdup(ns->prefix);
904 *buf = xmlStrcat(*buf, BAD_CAST ":");
905 *buf = xmlStrcat(*buf, local);
906 }
907 return ((const xmlChar *) *buf);
908}
909
910/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000911 * xmlSchemaWildcardPCToString:
912 * @pc: the type of processContents
913 *
914 * Returns a string representation of the type of
915 * processContents.
916 */
917static const xmlChar *
918xmlSchemaWildcardPCToString(int pc)
919{
920 switch (pc) {
921 case XML_SCHEMAS_ANY_SKIP:
922 return (BAD_CAST "skip");
923 case XML_SCHEMAS_ANY_LAX:
924 return (BAD_CAST "lax");
925 case XML_SCHEMAS_ANY_STRICT:
926 return (BAD_CAST "strict");
927 default:
928 return (BAD_CAST "invalid process contents");
929 }
930}
931
932/**
Daniel Veillardc0826a72004-08-10 14:17:33 +0000933 * xmlSchemaFormatItemForReport:
934 * @buf: the string buffer
935 * @itemDes: the designation of the item
936 * @itemName: the name of the item
937 * @item: the item as an object
938 * @itemNode: the node of the item
939 * @local: the local name
940 * @parsing: if the function is used during the parse
941 *
942 * Returns a representation of the given item used
943 * for error reports.
944 *
945 * The following order is used to build the resulting
946 * designation if the arguments are not NULL:
947 * 1a. If itemDes not NULL -> itemDes
948 * 1b. If (itemDes not NULL) and (itemName not NULL)
949 * -> itemDes + itemName
950 * 2. If the preceding was NULL and (item not NULL) -> item
951 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
952 *
953 * If the itemNode is an attribute node, the name of the attribute
954 * will be appended to the result.
955 *
956 * Returns the formatted string and sets @buf to the resulting value.
957 */
958static xmlChar*
959xmlSchemaFormatItemForReport(xmlChar **buf,
960 const xmlChar *itemDes,
961 xmlSchemaTypePtr item,
962 xmlNodePtr itemNode,
963 int parsing)
964{
965 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +0000966 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000967
968 if (*buf != NULL) {
969 xmlFree(*buf);
970 *buf = NULL;
971 }
972
William M. Brack2f2a6632004-08-20 23:09:47 +0000973 if (itemDes != NULL) {
974 *buf = xmlStrdup(itemDes);
975 } else if (item != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000976 switch (item->type) {
977 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000978 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
979 *buf = xmlStrdup(BAD_CAST "'anyType'");
980 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
981 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
982 else {
983 /* *buf = xmlStrdup(BAD_CAST "bi "); */
984 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
985 *buf = xmlStrdup(BAD_CAST "'");
986 *buf = xmlStrcat(*buf, item->name);
987 *buf = xmlStrcat(*buf, BAD_CAST "'");
988 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000989 break;
990 case XML_SCHEMA_TYPE_SIMPLE:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000991 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
992 *buf = xmlStrdup(xmlSchemaElemDesST);
993 *buf = xmlStrcat(*buf, BAD_CAST " '");
994 *buf = xmlStrcat(*buf, item->name);
995 *buf = xmlStrcat(*buf, BAD_CAST "'");
996 } else {
997 *buf = xmlStrdup(xmlSchemaElemDesST);
Daniel Veillardc0826a72004-08-10 14:17:33 +0000998 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000999 break;
1000 case XML_SCHEMA_TYPE_COMPLEX:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001001 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1002 *buf = xmlStrdup(xmlSchemaElemDesCT);
1003 *buf = xmlStrcat(*buf, BAD_CAST " '");
1004 *buf = xmlStrcat(*buf, item->name);
1005 *buf = xmlStrcat(*buf, BAD_CAST "'");
1006 } else {
1007 *buf = xmlStrdup(xmlSchemaElemDesCT);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001008 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001009 break;
1010 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1011 xmlSchemaAttributePtr attr;
1012
1013 attr = (xmlSchemaAttributePtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001014 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001015 (attr->ref == NULL)) {
1016 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1017 *buf = xmlStrcat(*buf, BAD_CAST " '");
1018 *buf = xmlStrcat(*buf, attr->name);
1019 *buf = xmlStrcat(*buf, BAD_CAST "'");
1020 } else {
1021 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1022 *buf = xmlStrcat(*buf, BAD_CAST " '");
1023 *buf = xmlStrcat(*buf, attr->refPrefix);
1024 *buf = xmlStrcat(*buf, BAD_CAST ":");
1025 *buf = xmlStrcat(*buf, attr->ref);
1026 *buf = xmlStrcat(*buf, BAD_CAST "'");
1027 }
1028 }
1029 break;
1030 case XML_SCHEMA_TYPE_ELEMENT: {
1031 xmlSchemaElementPtr elem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001032
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001033 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001034 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001035 (elem->ref == NULL)) {
1036 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1037 *buf = xmlStrcat(*buf, BAD_CAST " '");
1038 *buf = xmlStrcat(*buf, elem->name);
1039 *buf = xmlStrcat(*buf, BAD_CAST "'");
1040 } else {
1041 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
1042 *buf = xmlStrcat(*buf, BAD_CAST " '");
1043 *buf = xmlStrcat(*buf, elem->refPrefix);
1044 *buf = xmlStrcat(*buf, BAD_CAST ":");
1045 *buf = xmlStrcat(*buf, elem->ref);
1046 *buf = xmlStrcat(*buf, BAD_CAST "'");
1047 }
1048 }
1049 break;
1050 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1051 case XML_SCHEMA_TYPE_IDC_KEY:
1052 case XML_SCHEMA_TYPE_IDC_KEYREF:
1053 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1054 *buf = xmlStrdup(BAD_CAST "unique '");
1055 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1056 *buf = xmlStrdup(BAD_CAST "key '");
1057 else
1058 *buf = xmlStrdup(BAD_CAST "keyRef '");
1059 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1060 *buf = xmlStrcat(*buf, BAD_CAST "'");
1061 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001062 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001063 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1064 ((xmlSchemaWildcardPtr) item)->processContents));
1065 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1066 break;
1067 case XML_SCHEMA_FACET_MININCLUSIVE:
1068 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1069 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1070 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1071 case XML_SCHEMA_FACET_TOTALDIGITS:
1072 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1073 case XML_SCHEMA_FACET_PATTERN:
1074 case XML_SCHEMA_FACET_ENUMERATION:
1075 case XML_SCHEMA_FACET_WHITESPACE:
1076 case XML_SCHEMA_FACET_LENGTH:
1077 case XML_SCHEMA_FACET_MAXLENGTH:
1078 case XML_SCHEMA_FACET_MINLENGTH:
1079 *buf = xmlStrdup(BAD_CAST "facet '");
1080 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1081 *buf = xmlStrcat(*buf, BAD_CAST "'");
1082 break;
1083 case XML_SCHEMA_TYPE_NOTATION:
1084 *buf = xmlStrdup(BAD_CAST "notation");
1085 break;
1086 case XML_SCHEMA_TYPE_GROUP:
1087 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1088 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1089 *buf = xmlStrcat(*buf, BAD_CAST " '");
1090 *buf = xmlStrcat(*buf, item->name);
1091 *buf = xmlStrcat(*buf, BAD_CAST "'");
1092 } else {
1093 *buf = xmlStrdup(xmlSchemaElemModelGrRef);
1094 *buf = xmlStrcat(*buf, BAD_CAST " '");
1095 *buf = xmlStrcat(*buf, item->ref);
1096 *buf = xmlStrcat(*buf, BAD_CAST "'");
1097 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001098 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001099 default:
William M. Brack2f2a6632004-08-20 23:09:47 +00001100 named = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001101 }
William M. Brack2f2a6632004-08-20 23:09:47 +00001102 } else
1103 named = 0;
1104
1105 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00001106 xmlNodePtr elem;
1107
1108 if (itemNode->type == XML_ATTRIBUTE_NODE)
1109 elem = itemNode->parent;
1110 else
1111 elem = itemNode;
1112 *buf = xmlStrdup(BAD_CAST "Element '");
1113 if (parsing)
1114 *buf = xmlStrcat(*buf, elem->name);
1115 else
1116 *buf = xmlStrcat(*buf,
1117 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
1118 *buf = xmlStrcat(*buf, BAD_CAST "'");
1119 }
1120 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1121 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1122 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
1123 itemNode->ns, itemNode->name));
1124 *buf = xmlStrcat(*buf, BAD_CAST "'");
1125 }
1126 FREE_AND_NULL(str);
1127
1128 return (*buf);
1129}
1130
1131/**
1132 * xmlSchemaPFormatItemDes:
1133 * @buf: the string buffer
1134 * @item: the item as a schema object
1135 * @itemNode: the item as a node
1136 *
1137 * If the pointer to @buf is not NULL and @but holds no value,
1138 * the value is set to a item designation using
1139 * xmlSchemaFormatItemForReport. This one avoids adding
1140 * an attribute designation postfix.
1141 *
1142 * Returns a string of all enumeration elements.
1143 */
1144static void
1145xmlSchemaPRequestItemDes(xmlChar **buf,
1146 xmlSchemaTypePtr item,
1147 xmlNodePtr itemNode)
1148{
1149 if ((buf == 0) || (*buf != NULL))
1150 return;
1151 if (itemNode->type == XML_ATTRIBUTE_NODE)
1152 itemNode = itemNode->parent;
1153 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
1154}
1155
1156/**
1157 * xmlSchemaFormatFacetEnumSet:
1158 * @buf: the string buffer
1159 * @type: the type holding the enumeration facets
1160 *
1161 * Builds a string consisting of all enumeration elements.
1162 *
1163 * Returns a string of all enumeration elements.
1164 */
1165static const xmlChar *
1166xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
1167{
1168 xmlSchemaFacetLinkPtr link;
1169
1170 if (*buf != NULL)
1171 xmlFree(*buf);
1172 *buf = NULL;
1173 for (link = type->facetSet; link != NULL; link = link->next) {
1174 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
1175 if (*buf == NULL) {
1176 *buf = xmlStrdup(BAD_CAST "'");
1177 *buf = xmlStrcat(*buf, link->facet->value);
1178 *buf = xmlStrcat(*buf, BAD_CAST "'");
1179 } else {
1180 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1181 *buf = xmlStrcat(*buf, link->facet->value);
1182 *buf = xmlStrcat(*buf, BAD_CAST "'");
1183 }
1184 }
1185 }
1186 return ((const xmlChar *) *buf);
1187}
1188
1189/**
1190 * xmlSchemaVFacetErr:
1191 * @ctxt: the schema validation context
1192 * @error: the error code
1193 * @node: the node to be validated
1194 * @value: the value of the node
1195 * @type: the type holding the facet
1196 * @facet: the facet
1197 * @message: the error message of NULL
1198 * @str1: extra data
1199 * @str2: extra data
1200 * @str3: extra data
1201 *
1202 * Reports a facet validation error.
1203 * TODO: Should this report the value of an element as well?
1204 */
1205static void
1206xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
1207 xmlParserErrors error,
1208 xmlNodePtr node,
1209 const xmlChar *value,
1210 unsigned long length,
1211 xmlSchemaTypePtr type,
1212 xmlSchemaFacetPtr facet,
1213 const char *message,
1214 const xmlChar *str1,
1215 const xmlChar *str2,
1216 const xmlChar *str3)
1217{
1218 xmlChar *str = NULL, *msg = NULL;
1219 xmlSchemaTypeType facetType;
1220
1221 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1222 msg = xmlStrcat(msg, BAD_CAST " [");
1223 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1224 msg = xmlStrcat(msg, BAD_CAST ", facet '");
1225 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1226 facetType = XML_SCHEMA_FACET_ENUMERATION;
1227 /*
1228 * If enumerations are validated, one must not expect the
1229 * facet to be given.
1230 */
1231 } else
1232 facetType = facet->type;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001233 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001234 msg = xmlStrcat(msg, BAD_CAST "']: ");
1235 if (message == NULL) {
1236 /*
1237 * Use a default message.
1238 */
1239 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1240 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1241 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1242
1243 char len[25], actLen[25];
1244
1245 /* FIXME, TODO: What is the max expected string length of the
1246 * this value?
1247 */
1248 if (node->type == XML_ATTRIBUTE_NODE)
1249 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1250 else
1251 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1252
1253 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1254 snprintf(actLen, 24, "%lu", length);
1255
1256 if (facetType == XML_SCHEMA_FACET_LENGTH)
1257 msg = xmlStrcat(msg,
1258 BAD_CAST "this differs from the allowed length of '%s'.\n");
1259 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
1260 msg = xmlStrcat(msg,
1261 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
1262 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
1263 msg = xmlStrcat(msg,
1264 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
1265
1266 if (node->type == XML_ATTRIBUTE_NODE)
1267 xmlSchemaVErrExt(ctxt, node, error,
1268 (const char *) msg,
1269 value, (const xmlChar *) actLen, (const xmlChar *) len,
1270 NULL, NULL);
1271 else
1272 xmlSchemaVErr(ctxt, node, error,
1273 (const char *) msg,
1274 (const xmlChar *) actLen, (const xmlChar *) len);
1275
1276 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
1277 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
1278 "of the set {%s}.\n");
1279 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1280 xmlSchemaFormatFacetEnumSet(&str, type));
1281 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1282 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1283 "by the pattern '%s'.\n");
1284 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1285 facet->value);
1286 } else if (node->type == XML_ATTRIBUTE_NODE) {
1287 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1288 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1289 } else {
1290 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1291 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1292 }
1293 } else {
1294 msg = xmlStrcat(msg, (const xmlChar *) message);
1295 msg = xmlStrcat(msg, BAD_CAST ".\n");
1296 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1297 }
1298 FREE_AND_NULL(str)
1299 xmlFree(msg);
1300}
1301
1302/**
1303 * xmlSchemaVSimpleTypeErr:
1304 * @ctxt: the schema validation context
1305 * @error: the error code
1306 * @type: the type used for validation
1307 * @node: the node containing the validated value
1308 * @value: the validated value
1309 *
1310 * Reports a simple type validation error.
1311 * TODO: Should this report the value of an element as well?
1312 */
1313static void
1314xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1315 xmlParserErrors error,
1316 xmlNodePtr node,
1317 const xmlChar *value,
1318 xmlSchemaTypePtr type)
1319{
1320 xmlChar *str = NULL, *msg = NULL;
1321
1322 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1323 msg = xmlStrcat(msg, BAD_CAST " [");
1324 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1325 if (node->type == XML_ATTRIBUTE_NODE) {
1326 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1327 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1328 } else {
1329 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1330 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1331 }
1332 FREE_AND_NULL(str)
1333 xmlFree(msg);
1334}
1335
1336/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001337 * xmlSchemaVComplexTypeErr:
1338 * @ctxt: the schema validation context
1339 * @error: the error code
1340 * @node: the node containing the validated value
1341 * @type: the complex type used for validation
1342 * @message: the error message
1343 *
1344 * Reports a complex type validation error.
1345 */
1346static void
1347xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1348 xmlParserErrors error,
1349 xmlNodePtr node,
1350 xmlSchemaTypePtr type,
1351 const char *message)
1352{
1353 xmlChar *str = NULL, *msg = NULL;
1354
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001355 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001356 /* Specify the complex type only if it is global. */
1357 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001358 msg = xmlStrcat(msg, BAD_CAST " [");
1359 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1360 msg = xmlStrcat(msg, BAD_CAST "]");
1361 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001362 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1363 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001364 (const xmlChar *) message, NULL);
1365 FREE_AND_NULL(str)
1366 xmlFree(msg);
1367}
1368
1369/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001370 * xmlSchemaVComplexTypeElemErr:
1371 * @ctxt: the schema validation context
1372 * @error: the error code
1373 * @node: the node containing the validated value
1374 * @type: the complex type used for validation
1375 * @message: the error message
1376 *
1377 * Reports a complex type validation error.
1378 */
1379static void
1380xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1381 xmlParserErrors error,
1382 xmlNodePtr node,
1383 xmlSchemaTypePtr type,
1384 const char *message,
1385 int nbval,
1386 int nbneg,
1387 xmlChar **values)
1388{
1389 xmlChar *str = NULL, *msg = NULL;
1390 xmlChar *localName, *nsName;
1391 const xmlChar *cur, *end;
1392 int i;
1393
1394 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1395 /* Specify the complex type only if it is global. */
1396 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1397 msg = xmlStrcat(msg, BAD_CAST " [");
1398 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1399 msg = xmlStrcat(msg, BAD_CAST "]");
1400 FREE_AND_NULL(str)
1401 }
1402 msg = xmlStrcat(msg, BAD_CAST ": ");
1403 msg = xmlStrcat(msg, (const xmlChar *) message);
1404 /*
1405 * Note that is does not make sense to report that we have a
1406 * wildcard here, since the wildcard might be unfolded into
1407 * multiple transitions.
1408 */
1409 if (nbval + nbneg > 0) {
1410 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001411 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001412 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001413 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001414 nsName = NULL;
1415
1416 for (i = 0; i < nbval + nbneg; i++) {
1417 cur = values[i];
1418 /*
1419 * Get the local name.
1420 */
1421 localName = NULL;
1422
1423 end = cur;
1424 if (*end == '*') {
1425 localName = xmlStrdup(BAD_CAST "*");
1426 *end++;
1427 } else {
1428 while ((*end != 0) && (*end != '|'))
1429 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001430 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001431 }
1432 if (*end != 0) {
1433 *end++;
1434 /*
1435 * Skip "*|*" if they come with negated expressions, since
1436 * they represent the same negated wildcard.
1437 */
1438 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1439 /*
1440 * Get the namespace name.
1441 */
1442 cur = end;
1443 if (*end == '*') {
1444 nsName = xmlStrdup(BAD_CAST "{*}");
1445 } else {
1446 while (*end != 0)
1447 end++;
1448
1449 if (i >= nbval)
1450 nsName = xmlStrdup(BAD_CAST "{##other:");
1451 else
1452 nsName = xmlStrdup(BAD_CAST "{");
1453
1454 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1455 nsName = xmlStrcat(nsName, BAD_CAST "}");
1456 }
1457 str = xmlStrcat(str, BAD_CAST nsName);
1458 FREE_AND_NULL(nsName)
1459 } else {
1460 FREE_AND_NULL(localName);
1461 continue;
1462 }
1463 }
1464 str = xmlStrcat(str, BAD_CAST localName);
1465 FREE_AND_NULL(localName);
1466
1467 if (i < nbval + nbneg -1)
1468 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001469 }
1470 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001471 msg = xmlStrcat(msg, BAD_CAST str);
1472 FREE_AND_NULL(str)
1473 }
1474 msg = xmlStrcat(msg, BAD_CAST ".\n");
1475 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1476 xmlFree(msg);
1477}
1478
1479/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001480 * xmlSchemaPMissingAttrErr:
1481 * @ctxt: the schema validation context
1482 * @ownerDes: the designation of the owner
1483 * @ownerName: the name of the owner
1484 * @ownerItem: the owner as a schema object
1485 * @ownerElem: the owner as an element node
1486 * @node: the parent element node of the missing attribute node
1487 * @type: the corresponding type of the attribute node
1488 *
1489 * Reports an illegal attribute.
1490 */
1491static void
1492xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1493 xmlParserErrors error,
1494 xmlChar **ownerDes,
1495 xmlSchemaTypePtr ownerItem,
1496 xmlNodePtr ownerElem,
1497 const char *name,
1498 const char *message)
1499{
1500 xmlChar *des = NULL;
1501
1502 if (ownerDes == NULL)
1503 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1504 else if (*ownerDes == NULL) {
1505 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1506 des = *ownerDes;
1507 } else
1508 des = *ownerDes;
1509 if (message != NULL)
1510 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1511 else
1512 xmlSchemaPErr(ctxt, ownerElem, error,
1513 "%s: The attribute '%s' is required but missing.\n",
1514 BAD_CAST des, BAD_CAST name);
1515 if (ownerDes == NULL)
1516 FREE_AND_NULL(des);
1517}
1518
William M. Brack2f2a6632004-08-20 23:09:47 +00001519/**
1520 * xmlSchemaCompTypeToString:
1521 * @type: the type of the schema item
1522 *
1523 * Returns the component name of a schema item.
1524 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001525static const char *
1526xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1527{
1528 switch (type) {
1529 case XML_SCHEMA_TYPE_SIMPLE:
1530 return("simple type definition");
1531 case XML_SCHEMA_TYPE_COMPLEX:
1532 return("complex type definition");
1533 case XML_SCHEMA_TYPE_ELEMENT:
1534 return("element declaration");
1535 case XML_SCHEMA_TYPE_ATTRIBUTE:
1536 return("attribute declaration");
1537 case XML_SCHEMA_TYPE_GROUP:
1538 return("model group definition");
1539 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1540 return("attribute group definition");
1541 case XML_SCHEMA_TYPE_NOTATION:
1542 return("notation declaration");
1543 default:
1544 return("Not a schema component");
1545 }
1546}
1547/**
1548 * xmlSchemaPResCompAttrErr:
1549 * @ctxt: the schema validation context
1550 * @error: the error code
1551 * @ownerDes: the designation of the owner
1552 * @ownerItem: the owner as a schema object
1553 * @ownerElem: the owner as an element node
1554 * @name: the name of the attribute holding the QName
1555 * @refName: the referenced local name
1556 * @refURI: the referenced namespace URI
1557 * @message: optional message
1558 *
1559 * Used to report QName attribute values that failed to resolve
1560 * to schema components.
1561 */
1562static void
1563xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1564 xmlParserErrors error,
1565 xmlChar **ownerDes,
1566 xmlSchemaTypePtr ownerItem,
1567 xmlNodePtr ownerElem,
1568 const char *name,
1569 const xmlChar *refName,
1570 const xmlChar *refURI,
1571 xmlSchemaTypeType refType,
1572 const char *refTypeStr)
1573{
1574 xmlChar *des = NULL, *strA = NULL;
1575
1576 if (ownerDes == NULL)
1577 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1578 else if (*ownerDes == NULL) {
1579 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1580 des = *ownerDes;
1581 } else
1582 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001583 if (refTypeStr == NULL)
1584 refTypeStr = xmlSchemaCompTypeToString(refType);
1585 xmlSchemaPErrExt(ctxt, ownerElem, error,
1586 NULL, NULL, NULL,
1587 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1588 "%s.\n", BAD_CAST des, BAD_CAST name,
1589 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1590 BAD_CAST refTypeStr, NULL);
1591 if (ownerDes == NULL)
1592 FREE_AND_NULL(des)
1593 FREE_AND_NULL(strA)
1594}
1595
William M. Brack2f2a6632004-08-20 23:09:47 +00001596/**
1597 * xmlSchemaPCustomAttrErr:
1598 * @ctxt: the schema parser context
1599 * @error: the error code
1600 * @ownerDes: the designation of the owner
1601 * @ownerItem: the owner as a schema object
1602 * @attr: the illegal attribute node
1603 *
1604 * Reports an illegal attribute during the parse.
1605 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001606static void
1607xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001608 xmlParserErrors error,
1609 xmlChar **ownerDes,
1610 xmlSchemaTypePtr ownerItem,
1611 xmlAttrPtr attr,
1612 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001613{
1614 xmlChar *des = NULL;
1615
1616 if (ownerDes == NULL)
1617 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1618 else if (*ownerDes == NULL) {
1619 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1620 des = *ownerDes;
1621 } else
1622 des = *ownerDes;
1623 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1624 "%s, attribute '%s': %s.\n",
1625 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1626 if (ownerDes == NULL)
1627 FREE_AND_NULL(des);
1628}
1629
1630/**
1631 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001632 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001633 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001634 * @ownerDes: the designation of the attribute's owner
1635 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001636 * @attr: the illegal attribute node
1637 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001638 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001639 */
1640static void
1641xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1642 xmlParserErrors error,
1643 xmlChar **ownerDes,
1644 xmlSchemaTypePtr ownerItem,
1645 xmlAttrPtr attr)
1646{
1647 xmlChar *des = NULL, *strA = NULL;
1648
1649 if (ownerDes == NULL)
1650 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1651 else if (*ownerDes == NULL) {
1652 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1653 des = *ownerDes;
1654 } else
1655 des = *ownerDes;
1656 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1657 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1658 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1659 if (ownerDes == NULL)
1660 FREE_AND_NULL(des);
1661 FREE_AND_NULL(strA);
1662}
1663
William M. Brack2f2a6632004-08-20 23:09:47 +00001664/**
1665 * xmlSchemaPAquireDes:
1666 * @des: the first designation
1667 * @itemDes: the second designation
1668 * @item: the schema item
1669 * @itemElem: the node of the schema item
1670 *
1671 * Creates a designation for an item.
1672 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001673static void
1674xmlSchemaPAquireDes(xmlChar **des,
1675 xmlChar **itemDes,
1676 xmlSchemaTypePtr item,
1677 xmlNodePtr itemElem)
1678{
1679 if (itemDes == NULL)
1680 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1681 else if (*itemDes == NULL) {
1682 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1683 *des = *itemDes;
1684 } else
1685 *des = *itemDes;
1686}
1687
William M. Brack2f2a6632004-08-20 23:09:47 +00001688/**
1689 * xmlSchemaPCustomErr:
1690 * @ctxt: the schema parser context
1691 * @error: the error code
1692 * @itemDes: the designation of the schema item
1693 * @item: the schema item
1694 * @itemElem: the node of the schema item
1695 * @message: the error message
1696 * @str1: an optional param for the error message
1697 * @str2: an optional param for the error message
1698 * @str3: an optional param for the error message
1699 *
1700 * Reports an error during parsing.
1701 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001702static void
1703xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1704 xmlParserErrors error,
1705 xmlChar **itemDes,
1706 xmlSchemaTypePtr item,
1707 xmlNodePtr itemElem,
1708 const char *message,
1709 const xmlChar *str1,
1710 const xmlChar *str2,
1711 const xmlChar *str3)
1712{
1713 xmlChar *des = NULL, *msg = NULL;
1714
1715 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1716 msg = xmlStrdup(BAD_CAST "%s: ");
1717 msg = xmlStrcat(msg, (const xmlChar *) message);
1718 msg = xmlStrcat(msg, BAD_CAST ".\n");
1719 if ((itemElem == NULL) && (item != NULL))
1720 itemElem = item->node;
1721 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1722 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1723 if (itemDes == NULL)
1724 FREE_AND_NULL(des);
1725 FREE_AND_NULL(msg);
1726}
1727
William M. Brack2f2a6632004-08-20 23:09:47 +00001728/**
1729 * xmlSchemaPCustomErr:
1730 * @ctxt: the schema parser context
1731 * @error: the error code
1732 * @itemDes: the designation of the schema item
1733 * @item: the schema item
1734 * @itemElem: the node of the schema item
1735 * @message: the error message
1736 * @str1: the optional param for the error message
1737 *
1738 * Reports an error during parsing.
1739 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001740static void
1741xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1742 xmlParserErrors error,
1743 xmlChar **itemDes,
1744 xmlSchemaTypePtr item,
1745 xmlNodePtr itemElem,
1746 const char *message,
1747 const xmlChar *str1)
1748{
1749 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1750 str1, NULL, NULL);
1751}
1752
William M. Brack2f2a6632004-08-20 23:09:47 +00001753/**
1754 * xmlSchemaPAttrUseErr:
1755 * @ctxt: the schema parser context
1756 * @error: the error code
1757 * @itemDes: the designation of the schema type
1758 * @item: the schema type
1759 * @itemElem: the node of the schema type
1760 * @attr: the invalid schema attribute
1761 * @message: the error message
1762 * @str1: the optional param for the error message
1763 *
1764 * Reports an attribute use error during parsing.
1765 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001766static void
1767xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1768 xmlParserErrors error,
1769 xmlChar **itemDes,
1770 xmlSchemaTypePtr item,
1771 xmlNodePtr itemElem,
1772 const xmlSchemaAttributePtr attr,
1773 const char *message,
1774 const xmlChar *str1)
1775{
1776 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1777
1778 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1779 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1780 xmlSchemaGetAttrName(attr));
1781 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1782 msg = xmlStrcat(msg, (const xmlChar *) message);
1783 msg = xmlStrcat(msg, BAD_CAST ".\n");
1784 if ((itemElem == NULL) && (item != NULL))
1785 itemElem = item->node;
1786 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1787 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1788 if (itemDes == NULL)
1789 FREE_AND_NULL(des);
1790 FREE_AND_NULL(strA);
1791 xmlFree(msg);
1792}
1793
William M. Brack2f2a6632004-08-20 23:09:47 +00001794/**
1795 * xmlSchemaPIllegalFacetAtomicErr:
1796 * @ctxt: the schema parser context
1797 * @error: the error code
1798 * @itemDes: the designation of the type
1799 * @item: the schema type
1800 * @baseItem: the base type of type
1801 * @facet: the illegal facet
1802 *
1803 * Reports an illegal facet for atomic simple types.
1804 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001805static void
1806xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1807 xmlParserErrors error,
1808 xmlChar **itemDes,
1809 xmlSchemaTypePtr item,
1810 xmlSchemaTypePtr baseItem,
1811 xmlSchemaFacetPtr facet)
1812{
1813 xmlChar *des = NULL, *strT = NULL;
1814
1815 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1816 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1817 "%s: The facet '%s' is not allowed on types derived from the "
1818 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001819 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardc0826a72004-08-10 14:17:33 +00001820 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1821 NULL, NULL);
1822 if (itemDes == NULL)
1823 FREE_AND_NULL(des);
1824 FREE_AND_NULL(strT);
1825}
1826
William M. Brack2f2a6632004-08-20 23:09:47 +00001827/**
1828 * xmlSchemaPIllegalFacetListUnionErr:
1829 * @ctxt: the schema parser context
1830 * @error: the error code
1831 * @itemDes: the designation of the schema item involved
1832 * @item: the schema item involved
1833 * @facet: the illegal facet
1834 *
1835 * Reports an illegal facet for <list> and <union>.
1836 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001837static void
1838xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1839 xmlParserErrors error,
1840 xmlChar **itemDes,
1841 xmlSchemaTypePtr item,
1842 xmlSchemaFacetPtr facet)
1843{
1844 xmlChar *des = NULL, *strT = NULL;
1845
1846 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1847 xmlSchemaPErr(ctxt, item->node, error,
1848 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001849 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001850 if (itemDes == NULL)
1851 FREE_AND_NULL(des);
1852 FREE_AND_NULL(strT);
1853}
1854
1855/**
1856 * xmlSchemaPMutualExclAttrErr:
1857 * @ctxt: the schema validation context
1858 * @error: the error code
1859 * @elemDes: the designation of the parent element node
1860 * @attr: the bad attribute node
1861 * @type: the corresponding type of the attribute node
1862 *
1863 * Reports an illegal attribute.
1864 */
1865static void
1866xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1867 xmlParserErrors error,
1868 xmlChar **ownerDes,
1869 xmlSchemaTypePtr ownerItem,
1870 xmlAttrPtr attr,
1871 const char *name1,
1872 const char *name2)
1873{
1874 xmlChar *des = NULL;
1875
1876 if (ownerDes == NULL)
1877 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1878 else if (*ownerDes == NULL) {
1879 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1880 des = *ownerDes;
1881 } else
1882 des = *ownerDes;
1883 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1884 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1885 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1886 if (ownerDes == NULL)
1887 FREE_AND_NULL(des)
1888}
1889
1890/**
1891 * xmlSchemaPSimpleTypeErr:
1892 * @ctxt: the schema validation context
1893 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001894 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001895 * @ownerDes: the designation of the owner
1896 * @ownerItem: the schema object if existent
1897 * @node: the validated node
1898 * @value: the validated value
1899 *
1900 * Reports a simple type validation error.
1901 * TODO: Should this report the value of an element as well?
1902 */
1903static void
1904xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1905 xmlParserErrors error,
1906 xmlChar **ownerDes,
1907 xmlSchemaTypePtr ownerItem,
1908 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001909 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001910 const char *typeDes,
1911 const xmlChar *value,
1912 const char *message,
1913 const xmlChar *str1,
1914 const xmlChar *str2)
1915{
William M. Brack2f2a6632004-08-20 23:09:47 +00001916 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001917
1918 if (ownerDes == NULL)
1919 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1920 else if (*ownerDes == NULL) {
1921 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1922 des = *ownerDes;
1923 } else
1924 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001925 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001926 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001927 if (message == NULL) {
1928 /*
1929 * Use default messages.
1930 */
1931 if (node->type == XML_ATTRIBUTE_NODE) {
1932 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1933 "%s, attribute '%s' [%s]: The value '%s' is not "
1934 "valid.\n",
1935 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1936 node->name), BAD_CAST typeDes, value, NULL);
1937 } else {
1938 xmlSchemaPErr(ctxt, node, error,
1939 "%s [%s]: The character content is not valid.\n",
1940 BAD_CAST des, BAD_CAST typeDes);
1941 }
1942 } else {
1943 xmlChar *msg;
1944
1945 msg = xmlStrdup(BAD_CAST "%s");
1946 if (node->type == XML_ATTRIBUTE_NODE)
1947 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1948 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1949 msg = xmlStrcat(msg, (const xmlChar *) message);
1950 msg = xmlStrcat(msg, BAD_CAST ".\n");
1951 if (node->type == XML_ATTRIBUTE_NODE) {
1952 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1953 (const char *) msg,
1954 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1955 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1956 } else {
1957 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1958 (const char *) msg,
1959 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1960 }
1961 xmlFree(msg);
1962 }
1963 /* Cleanup. */
1964 FREE_AND_NULL(strA)
1965 FREE_AND_NULL(strT)
1966 if (ownerDes == NULL)
1967 FREE_AND_NULL(des)
1968}
1969
William M. Brack2f2a6632004-08-20 23:09:47 +00001970/**
1971 * xmlSchemaPContentErr:
1972 * @ctxt: the schema parser context
1973 * @error: the error code
1974 * @onwerDes: the designation of the holder of the content
1975 * @ownerItem: the owner item of the holder of the content
1976 * @ownerElem: the node of the holder of the content
1977 * @child: the invalid child node
1978 * @message: the optional error message
1979 * @content: the optional string describing the correct content
1980 *
1981 * Reports an error concerning the content of a schema element.
1982 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001983static void
1984xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1985 xmlParserErrors error,
1986 xmlChar **ownerDes,
1987 xmlSchemaTypePtr ownerItem,
1988 xmlNodePtr ownerElem,
1989 xmlNodePtr child,
1990 const char *message,
1991 const char *content)
1992{
1993 xmlChar *des = NULL;
1994
1995 if (ownerDes == NULL)
1996 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1997 else if (*ownerDes == NULL) {
1998 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1999 des = *ownerDes;
2000 } else
2001 des = *ownerDes;
2002 if (message != NULL)
2003 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2004 "%s: %s.\n",
2005 BAD_CAST des, BAD_CAST message);
2006 else {
2007 if (content != NULL) {
2008 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2009 "%s: The content is not valid. Expected is %s.\n",
2010 BAD_CAST des, BAD_CAST content);
2011 } else {
2012 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2013 "%s: The content is not valid.\n",
2014 BAD_CAST des, NULL);
2015 }
2016 }
2017 if (ownerDes == NULL)
2018 FREE_AND_NULL(des)
2019}
2020
2021/**
2022 * xmlSchemaVIllegalAttrErr:
2023 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002024 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00002025 * @attr: the illegal attribute node
2026 *
2027 * Reports an illegal attribute.
2028 */
2029static void
2030xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002031 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002032 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002033{
2034 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002035
2036 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
2037 error,
2038 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002039 "%s: The attribute '%s' is not allowed.\n",
2040 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
2041 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2042 FREE_AND_NULL(strE)
2043 FREE_AND_NULL(strA)
2044}
2045
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002046
2047static int
2048xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2049{
2050 switch (item->type) {
2051 case XML_SCHEMA_TYPE_COMPLEX:
2052 case XML_SCHEMA_TYPE_SIMPLE:
2053 case XML_SCHEMA_TYPE_GROUP:
2054 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2055 return(1);
2056 break;
2057 case XML_SCHEMA_TYPE_ELEMENT:
2058 if ( ((xmlSchemaElementPtr) item)->flags &
2059 XML_SCHEMAS_ELEM_GLOBAL)
2060 return(1);
2061 break;
2062 case XML_SCHEMA_TYPE_ATTRIBUTE:
2063 if ( ((xmlSchemaAttributePtr) item)->flags &
2064 XML_SCHEMAS_ATTR_GLOBAL)
2065 return(1);
2066 break;
2067 /* Note that attribute groups are always global. */
2068 default:
2069 return(1);
2070 }
2071 return (0);
2072}
2073
William M. Brack2f2a6632004-08-20 23:09:47 +00002074/**
2075 * xmlSchemaVCustomErr:
2076 * @ctxt: the schema validation context
2077 * @error: the error code
2078 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002079 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00002080 * @message: the error message
2081 * @str1: the optional param for the message
2082 *
2083 * Reports a validation error.
2084 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002085static void
2086xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
2087 xmlParserErrors error,
2088 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002089 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002090 const char *message,
2091 const xmlChar *str1)
2092{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002093 xmlChar *msg = NULL, *str = NULL;
2094
2095 if (node == NULL) {
2096 xmlSchemaVErr(ctxt, NULL,
2097 XML_SCHEMAV_INTERNAL,
2098 "Internal error: xmlSchemaVCustomErr, no node "
2099 "given.\n", NULL, NULL);
2100 return;
2101 }
2102 /* TODO: Are the HTML and DOCB doc nodes expected here? */
2103 if (node->type != XML_DOCUMENT_NODE) {
2104 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002105 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002106 msg = xmlStrcat(msg, BAD_CAST " [");
2107 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
2108 msg = xmlStrcat(msg, BAD_CAST "]");
2109 }
2110 msg = xmlStrcat(msg, BAD_CAST ": ");
2111 } else
2112 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002113 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002114 msg = xmlStrcat(msg, BAD_CAST ".\n");
2115 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
2116 FREE_AND_NULL(msg)
2117 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002118}
2119
William M. Brack2f2a6632004-08-20 23:09:47 +00002120/**
William M. Brack2f2a6632004-08-20 23:09:47 +00002121 * xmlSchemaVWildcardErr:
2122 * @ctxt: the schema validation context
2123 * @error: the error code
2124 * @node: the validated node
2125 * @wild: the wildcard used
2126 * @message: the error message
2127 *
2128 * Reports an validation-by-wildcard error.
2129 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002130static void
2131xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
2132 xmlParserErrors error,
2133 xmlNodePtr node,
2134 xmlSchemaWildcardPtr wild,
2135 const char *message)
2136{
2137 xmlChar *des = NULL, *msg = NULL;
2138
2139 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00002140 msg = xmlStrdup(BAD_CAST "%s [");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002141 msg = xmlStrcat(msg, xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002142 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002143 msg = xmlStrcat(msg, (const xmlChar *) message);
2144 msg = xmlStrcat(msg, BAD_CAST ".\n");
2145 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
2146 FREE_AND_NULL(des);
2147 FREE_AND_NULL(msg);
2148}
2149
2150/**
2151 * xmlSchemaVMissingAttrErr:
2152 * @ctxt: the schema validation context
2153 * @node: the parent element node of the missing attribute node
2154 * @type: the corresponding type of the attribute node
2155 *
2156 * Reports an illegal attribute.
2157 */
2158static void
2159xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
2160 xmlNodePtr elem,
2161 xmlSchemaAttributePtr type)
2162{
2163 const xmlChar *name, *uri;
2164 xmlChar *strE = NULL, *strA = NULL;
2165
2166 if (type->ref != NULL) {
2167 name = type->ref;
2168 uri = type->refNs;
2169 } else {
2170 name = type->name;
2171 uri = type->targetNamespace;
2172 }
2173 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002174 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
2175 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002176 "%s: The attribute %s is required but missing.\n",
2177 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
2178 xmlSchemaFormatNsUriLocal(&strA, uri, name));
2179 FREE_AND_NULL(strE)
2180 FREE_AND_NULL(strA)
2181}
2182
Daniel Veillard4255d502002-04-16 15:50:10 +00002183/************************************************************************
2184 * *
2185 * Allocation functions *
2186 * *
2187 ************************************************************************/
2188
2189/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002190 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002191 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002192 *
2193 * Allocate a new Schema structure.
2194 *
2195 * Returns the newly allocated structure or NULL in case or error
2196 */
2197static xmlSchemaPtr
2198xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2199{
2200 xmlSchemaPtr ret;
2201
2202 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2203 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002204 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002205 return (NULL);
2206 }
2207 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002208 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002209 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002210
2211 return (ret);
2212}
2213
2214/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002215 * xmlSchemaNewSchema:
2216 * @ctxt: a schema validation context
2217 *
2218 * Allocate a new Schema structure.
2219 *
2220 * Returns the newly allocated structure or NULL in case or error
2221 */
2222static xmlSchemaAssemblePtr
2223xmlSchemaNewAssemble(void)
2224{
2225 xmlSchemaAssemblePtr ret;
2226
2227 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2228 if (ret == NULL) {
2229 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2230 return (NULL);
2231 }
2232 memset(ret, 0, sizeof(xmlSchemaAssemble));
2233 ret->items = NULL;
2234 return (ret);
2235}
2236
2237/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002238 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002239 *
2240 * Allocate a new Facet structure.
2241 *
2242 * Returns the newly allocated structure or NULL in case or error
2243 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002244xmlSchemaFacetPtr
2245xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002246{
2247 xmlSchemaFacetPtr ret;
2248
2249 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2250 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002251 return (NULL);
2252 }
2253 memset(ret, 0, sizeof(xmlSchemaFacet));
2254
2255 return (ret);
2256}
2257
2258/**
2259 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002260 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002261 * @node: a node
2262 *
2263 * Allocate a new annotation structure.
2264 *
2265 * Returns the newly allocated structure or NULL in case or error
2266 */
2267static xmlSchemaAnnotPtr
2268xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2269{
2270 xmlSchemaAnnotPtr ret;
2271
2272 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2273 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002274 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002275 return (NULL);
2276 }
2277 memset(ret, 0, sizeof(xmlSchemaAnnot));
2278 ret->content = node;
2279 return (ret);
2280}
2281
2282/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002283 * xmlSchemaFreeAnnot:
2284 * @annot: a schema type structure
2285 *
2286 * Deallocate a annotation structure
2287 */
2288static void
2289xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2290{
2291 if (annot == NULL)
2292 return;
2293 xmlFree(annot);
2294}
2295
2296/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002297 * xmlSchemaFreeImport:
2298 * @import: a schema import structure
2299 *
2300 * Deallocate an import structure
2301 */
2302static void
2303xmlSchemaFreeImport(xmlSchemaImportPtr import)
2304{
2305 if (import == NULL)
2306 return;
2307
2308 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002309 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002310 xmlFree(import);
2311}
2312
2313/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002314 * xmlSchemaFreeInclude:
2315 * @include: a schema include structure
2316 *
2317 * Deallocate an include structure
2318 */
2319static void
2320xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2321{
2322 if (include == NULL)
2323 return;
2324
2325 xmlFreeDoc(include->doc);
2326 xmlFree(include);
2327}
2328
2329/**
2330 * xmlSchemaFreeIncludeList:
2331 * @includes: a schema include list
2332 *
2333 * Deallocate an include structure
2334 */
2335static void
2336xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2337{
2338 xmlSchemaIncludePtr next;
2339
2340 while (includes != NULL) {
2341 next = includes->next;
2342 xmlSchemaFreeInclude(includes);
2343 includes = next;
2344 }
2345}
2346
2347/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002348 * xmlSchemaFreeNotation:
2349 * @schema: a schema notation structure
2350 *
2351 * Deallocate a Schema Notation structure.
2352 */
2353static void
2354xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2355{
2356 if (nota == NULL)
2357 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002358 xmlFree(nota);
2359}
2360
2361/**
2362 * xmlSchemaFreeAttribute:
2363 * @schema: a schema attribute structure
2364 *
2365 * Deallocate a Schema Attribute structure.
2366 */
2367static void
2368xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2369{
2370 if (attr == NULL)
2371 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002372 if (attr->annot != NULL)
2373 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002374 if (attr->defVal != NULL)
2375 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002376 xmlFree(attr);
2377}
2378
2379/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002380 * xmlSchemaFreeWildcardNsSet:
2381 * set: a schema wildcard namespace
2382 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002383 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002384 */
2385static void
2386xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2387{
2388 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002389
Daniel Veillard3646d642004-06-02 19:19:14 +00002390 while (set != NULL) {
2391 next = set->next;
2392 xmlFree(set);
2393 set = next;
2394 }
2395}
2396
2397/**
2398 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002399 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002400 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002401 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002402 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002403void
Daniel Veillard3646d642004-06-02 19:19:14 +00002404xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2405{
2406 if (wildcard == NULL)
2407 return;
2408 if (wildcard->annot != NULL)
2409 xmlSchemaFreeAnnot(wildcard->annot);
2410 if (wildcard->nsSet != NULL)
2411 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2412 if (wildcard->negNsSet != NULL)
2413 xmlFree(wildcard->negNsSet);
2414 xmlFree(wildcard);
2415}
2416
2417/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002418 * xmlSchemaFreeAttributeGroup:
2419 * @schema: a schema attribute group structure
2420 *
2421 * Deallocate a Schema Attribute Group structure.
2422 */
2423static void
2424xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2425{
2426 if (attr == NULL)
2427 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002428 if (attr->annot != NULL)
2429 xmlSchemaFreeAnnot(attr->annot);
2430 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2431 (attr->attributeWildcard != NULL))
2432 xmlSchemaFreeWildcard(attr->attributeWildcard);
2433
Daniel Veillard4255d502002-04-16 15:50:10 +00002434 xmlFree(attr);
2435}
2436
2437/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002438 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002439 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002440 *
2441 * Deallocate a list of schema attribute uses.
2442 */
2443static void
2444xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2445{
2446 xmlSchemaAttributeLinkPtr next;
2447
2448 while (attrUse != NULL) {
2449 next = attrUse->next;
2450 xmlFree(attrUse);
2451 attrUse = next;
2452 }
2453}
2454
2455/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002456 * xmlSchemaFreeTypeLinkList:
2457 * @alink: a type link
2458 *
2459 * Deallocate a list of types.
2460 */
2461static void
2462xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2463{
2464 xmlSchemaTypeLinkPtr next;
2465
2466 while (link != NULL) {
2467 next = link->next;
2468 xmlFree(link);
2469 link = next;
2470 }
2471}
2472
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002473#ifdef IDC_ENABLED
2474static void
2475xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
2476{
2477 xmlSchemaIDCStateObjPtr next;
2478 while (sto != NULL) {
2479 next = sto->next;
2480 if (sto->history != NULL)
2481 xmlFree(sto->history);
2482 if (sto->xpathCtxt != NULL)
2483 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
2484 xmlFree(sto);
2485 sto = next;
2486 }
2487}
2488
2489/**
2490 * xmlSchemaFreeIDC:
2491 * @idc: a identity-constraint definition
2492 *
2493 * Deallocates an identity-constraint definition.
2494 */
2495static void
2496xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
2497{
2498 xmlSchemaIDCSelectPtr cur, prev;
2499
2500 if (idcDef == NULL)
2501 return;
2502 if (idcDef->annot != NULL)
2503 xmlSchemaFreeAnnot(idcDef->annot);
2504 if (idcDef->ref != NULL)
2505 xmlFree(idcDef->ref);
2506 /* Selector */
2507 if (idcDef->selector != NULL) {
2508 if (idcDef->selector->xpathComp != NULL)
2509 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
2510 xmlFree(idcDef->selector);
2511 }
2512 /* Fields */
2513 if (idcDef->fields != NULL) {
2514 cur = idcDef->fields;
2515 do {
2516 prev = cur;
2517 cur = cur->next;
2518 if (prev->xpathComp != NULL)
2519 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
2520 xmlFree(prev);
2521 } while (cur != NULL);
2522 }
2523 xmlFree(idcDef);
2524}
2525#endif /* IDC_ENABLED */
2526
Daniel Veillard01fa6152004-06-29 17:04:39 +00002527/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002528 * xmlSchemaFreeElement:
2529 * @schema: a schema element structure
2530 *
2531 * Deallocate a Schema Element structure.
2532 */
2533static void
2534xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2535{
2536 if (elem == NULL)
2537 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002538 if (elem->annot != NULL)
2539 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002540 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002541 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002542 if (elem->defVal != NULL)
2543 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002544 xmlFree(elem);
2545}
2546
2547/**
2548 * xmlSchemaFreeFacet:
2549 * @facet: a schema facet structure
2550 *
2551 * Deallocate a Schema Facet structure.
2552 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002553void
Daniel Veillard4255d502002-04-16 15:50:10 +00002554xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2555{
2556 if (facet == NULL)
2557 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002558 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002559 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002560 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002561 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002562 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002563 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002564 xmlFree(facet);
2565}
2566
2567/**
2568 * xmlSchemaFreeType:
2569 * @type: a schema type structure
2570 *
2571 * Deallocate a Schema Type structure.
2572 */
2573void
2574xmlSchemaFreeType(xmlSchemaTypePtr type)
2575{
2576 if (type == NULL)
2577 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002578 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002579 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002580 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002581 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002582
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002583 facet = type->facets;
2584 while (facet != NULL) {
2585 next = facet->next;
2586 xmlSchemaFreeFacet(facet);
2587 facet = next;
2588 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002589 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002590 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2591 if (type->attributeUses != NULL)
2592 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002593 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002594 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002595 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2596 /*
2597 * NOTE: The only case where an attribute wildcard
2598 * is not owned, is if a complex type inherits it
2599 * from a base type.
2600 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002601 xmlSchemaFreeWildcard(type->attributeWildcard);
2602 }
2603 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002604 if (type->memberTypes != NULL)
2605 xmlSchemaFreeTypeLinkList(type->memberTypes);
2606 if (type->facetSet != NULL) {
2607 xmlSchemaFacetLinkPtr next, link;
2608
2609 link = type->facetSet;
2610 do {
2611 next = link->next;
2612 xmlFree(link);
2613 link = next;
2614 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002615 }
2616 if (type->contModel != NULL)
2617 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002618 xmlFree(type);
2619}
2620
2621/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002622 * xmlSchemaFreeTypeList:
2623 * @type: a schema type structure
2624 *
2625 * Deallocate a Schema Type structure.
2626 */
2627static void
2628xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2629{
2630 xmlSchemaTypePtr next;
2631
2632 while (type != NULL) {
2633 next = type->redef;
2634 xmlSchemaFreeType(type);
2635 type = next;
2636 }
2637}
2638
2639/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002640 * xmlSchemaFree:
2641 * @schema: a schema structure
2642 *
2643 * Deallocate a Schema structure.
2644 */
2645void
2646xmlSchemaFree(xmlSchemaPtr schema)
2647{
2648 if (schema == NULL)
2649 return;
2650
Daniel Veillard4255d502002-04-16 15:50:10 +00002651 if (schema->notaDecl != NULL)
2652 xmlHashFree(schema->notaDecl,
2653 (xmlHashDeallocator) xmlSchemaFreeNotation);
2654 if (schema->attrDecl != NULL)
2655 xmlHashFree(schema->attrDecl,
2656 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2657 if (schema->attrgrpDecl != NULL)
2658 xmlHashFree(schema->attrgrpDecl,
2659 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2660 if (schema->elemDecl != NULL)
2661 xmlHashFree(schema->elemDecl,
2662 (xmlHashDeallocator) xmlSchemaFreeElement);
2663 if (schema->typeDecl != NULL)
2664 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002665 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002666 if (schema->groupDecl != NULL)
2667 xmlHashFree(schema->groupDecl,
2668 (xmlHashDeallocator) xmlSchemaFreeType);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002669#ifdef IDC_ENABLED
2670 if (schema->idcDef != NULL)
2671 xmlHashFree(schema->idcDef,
2672 (xmlHashDeallocator) xmlSchemaFreeIDC);
2673#endif
Daniel Veillard1d913862003-11-21 00:28:39 +00002674 if (schema->schemasImports != NULL)
2675 xmlHashFree(schema->schemasImports,
2676 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002677 if (schema->includes != NULL) {
2678 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2679 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002680 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002681 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002682 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002683 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002684 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002685 xmlFree(schema);
2686}
2687
2688/************************************************************************
2689 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002690 * Debug functions *
2691 * *
2692 ************************************************************************/
2693
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002694#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002695
Daniel Veillard4255d502002-04-16 15:50:10 +00002696/**
2697 * xmlSchemaElementDump:
2698 * @elem: an element
2699 * @output: the file output
2700 *
2701 * Dump the element
2702 */
2703static void
2704xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002705 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002706 const xmlChar * namespace ATTRIBUTE_UNUSED,
2707 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002708{
2709 if (elem == NULL)
2710 return;
2711
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002712 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
2713 fprintf(output, "Particle: %s", name);
2714 fprintf(output, ", term element: %s", elem->ref);
2715 if (elem->refNs != NULL)
2716 fprintf(output, " ns %s", elem->refNs);
2717 } else {
2718 fprintf(output, "Element");
2719 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2720 fprintf(output, " (global)");
2721 fprintf(output, ": %s ", elem->name);
2722 if (namespace != NULL)
2723 fprintf(output, "ns %s", namespace);
2724 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002725 fprintf(output, "\n");
2726 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002727 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002728 if (elem->maxOccurs >= UNBOUNDED)
2729 fprintf(output, "max: unbounded\n");
2730 else if (elem->maxOccurs != 1)
2731 fprintf(output, "max: %d\n", elem->maxOccurs);
2732 else
2733 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002734 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002735 /*
2736 * Misc other properties.
2737 */
2738 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
2739 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
2740 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
2741 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
2742 (elem->id != NULL)) {
2743 fprintf(output, " props: ");
2744 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
2745 fprintf(output, "[fixed] ");
2746 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
2747 fprintf(output, "[default] ");
2748 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
2749 fprintf(output, "[abstract] ");
2750 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
2751 fprintf(output, "[nillable] ");
2752 if (elem->id != NULL)
2753 fprintf(output, "[id: '%s'] ", elem->id);
2754 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002755 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002756 /*
2757 * Default/fixed value.
2758 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002759 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002760 fprintf(output, " value: '%s'\n", elem->value);
2761 /*
2762 * Type.
2763 */
2764 if (elem->namedType != NULL) {
2765 fprintf(output, " type: %s ", elem->namedType);
2766 if (elem->namedTypeNs != NULL)
2767 fprintf(output, "ns %s\n", elem->namedTypeNs);
2768 else
2769 fprintf(output, "\n");
2770 }
2771 /*
2772 * Substitution group.
2773 */
2774 if (elem->substGroup != NULL) {
2775 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
2776 if (elem->substGroupNs != NULL)
2777 fprintf(output, "ns %s\n", elem->substGroupNs);
2778 else
2779 fprintf(output, "\n");
2780 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002781}
2782
2783/**
2784 * xmlSchemaAnnotDump:
2785 * @output: the file output
2786 * @annot: a annotation
2787 *
2788 * Dump the annotation
2789 */
2790static void
2791xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2792{
2793 xmlChar *content;
2794
2795 if (annot == NULL)
2796 return;
2797
2798 content = xmlNodeGetContent(annot->content);
2799 if (content != NULL) {
2800 fprintf(output, " Annot: %s\n", content);
2801 xmlFree(content);
2802 } else
2803 fprintf(output, " Annot: empty\n");
2804}
2805
2806/**
2807 * xmlSchemaTypeDump:
2808 * @output: the file output
2809 * @type: a type structure
2810 *
2811 * Dump a SchemaType structure
2812 */
2813static void
2814xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2815{
2816 if (type == NULL) {
2817 fprintf(output, "Type: NULL\n");
2818 return;
2819 }
2820 fprintf(output, "Type: ");
2821 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002822 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002823 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002824 fprintf(output, "no name ");
2825 if (type->targetNamespace != NULL)
2826 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002827 switch (type->type) {
2828 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002829 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002830 break;
2831 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002832 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002833 break;
2834 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002835 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002836 break;
2837 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002838 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002839 break;
2840 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002841 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002842 break;
2843 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002844 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002845 break;
2846 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002847 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002848 break;
2849 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002850 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002851 break;
2852 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002853 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002854 break;
2855 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002856 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00002857 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002858 }
2859 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002860 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002861 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002862 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002863 break;
2864 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002865 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002866 break;
2867 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002868 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002869 break;
2870 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002871 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002872 break;
2873 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002874 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002875 break;
2876 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002877 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002878 break;
2879 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002880 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002881 break;
2882 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002883 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002884 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002885 }
2886 fprintf(output, "\n");
2887 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002888 fprintf(output, " min: %d ", type->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002889 if (type->maxOccurs >= UNBOUNDED)
2890 fprintf(output, "max: unbounded\n");
2891 else if (type->maxOccurs != 1)
2892 fprintf(output, "max: %d\n", type->maxOccurs);
2893 else
2894 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002895 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002896 if (type->base != NULL) {
2897 fprintf(output, " base type: %s", type->base);
2898 if (type->baseNs != NULL)
2899 fprintf(output, " ns %s\n", type->baseNs);
2900 else
2901 fprintf(output, "\n");
2902 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002903 if (type->annot != NULL)
2904 xmlSchemaAnnotDump(output, type->annot);
2905 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002906 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002907
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002908 fprintf(output, " subtypes: ");
2909 while (sub != NULL) {
2910 fprintf(output, "%s ", sub->name);
2911 sub = sub->next;
2912 }
2913 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002914 }
2915
2916}
2917
2918/**
2919 * xmlSchemaDump:
2920 * @output: the file output
2921 * @schema: a schema structure
2922 *
2923 * Dump a Schema structure.
2924 */
2925void
2926xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2927{
Daniel Veillardce682bc2004-11-05 17:22:25 +00002928 if (output == NULL)
2929 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002930 if (schema == NULL) {
2931 fprintf(output, "Schemas: NULL\n");
2932 return;
2933 }
2934 fprintf(output, "Schemas: ");
2935 if (schema->name != NULL)
2936 fprintf(output, "%s, ", schema->name);
2937 else
2938 fprintf(output, "no name, ");
2939 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002940 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002941 else
2942 fprintf(output, "no target namespace");
2943 fprintf(output, "\n");
2944 if (schema->annot != NULL)
2945 xmlSchemaAnnotDump(output, schema->annot);
2946
2947 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2948 output);
2949 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002950 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002951}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002952
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002953#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00002954#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002955/**
2956 * xmlSchemaDebugDumpIDCTable:
2957 * @vctxt: the WXS validation context
2958 *
2959 * Displays the current IDC table for debug purposes.
2960 */
2961static void
2962xmlSchemaDebugDumpIDCTable(FILE * output,
2963 const xmlChar *namespaceName,
2964 const xmlChar *localName,
2965 xmlSchemaPSVIIDCBindingPtr bind)
2966{
2967 xmlChar *str = NULL, *value;
2968 xmlSchemaPSVIIDCNodePtr tab;
2969 xmlSchemaPSVIIDCKeyPtr key;
2970 int i, j, res;
2971
2972 fprintf(output, "IDC: TABLES on %s\n",
2973 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
2974 FREE_AND_NULL(str)
2975
2976 if (bind == NULL)
2977 return;
2978 do {
2979 fprintf(output, "IDC: BINDING %s\n",
2980 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
2981 bind->definition->name));
2982 FREE_AND_NULL(str)
2983 for (i = 0; i < bind->nbNodes; i++) {
2984 tab = bind->nodeTable[i];
2985 fprintf(output, " ( ");
2986 for (j = 0; j < bind->definition->nbFields; j++) {
2987 key = tab->keys[j];
2988 if ((key != NULL) && (key->compValue != NULL)) {
2989#ifdef IDC_VALUE_SUPPORT
2990 res = xmlSchemaGetCanonValue(key->compValue, &value);
2991#else
2992 value = xmlStrdup(BAD_CAST "dummy-value");
2993 res = 0;
2994#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002995 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002996 fprintf(output, "\"%s\" ", value);
2997 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002998 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002999 if (res == 0)
3000 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003001 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003002 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003003 else
3004 fprintf(output, "(key missing), ");
3005 }
3006 fprintf(output, ")\n");
3007 }
3008 bind = bind->next;
3009 } while (bind != NULL);
3010}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003011#endif /* DEBUG_IDC */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003012#endif /* IDC_ENABLED */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003013#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003014
3015/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003016 * *
3017 * Utilities *
3018 * *
3019 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003020
Daniel Veillardc0826a72004-08-10 14:17:33 +00003021/**
3022 * xmlSchemaGetPropNode:
3023 * @node: the element node
3024 * @name: the name of the attribute
3025 *
3026 * Seeks an attribute with a name of @name in
3027 * no namespace.
3028 *
3029 * Returns the attribute or NULL if not present.
3030 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003031static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003032xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003033{
3034 xmlAttrPtr prop;
3035
Daniel Veillardc0826a72004-08-10 14:17:33 +00003036 if ((node == NULL) || (name == NULL))
3037 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003038 prop = node->properties;
3039 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003040 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3041 return(prop);
3042 prop = prop->next;
3043 }
3044 return (NULL);
3045}
3046
3047/**
3048 * xmlSchemaGetPropNodeNs:
3049 * @node: the element node
3050 * @uri: the uri
3051 * @name: the name of the attribute
3052 *
3053 * Seeks an attribute with a local name of @name and
3054 * a namespace URI of @uri.
3055 *
3056 * Returns the attribute or NULL if not present.
3057 */
3058static xmlAttrPtr
3059xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3060{
3061 xmlAttrPtr prop;
3062
3063 if ((node == NULL) || (name == NULL))
3064 return(NULL);
3065 prop = node->properties;
3066 while (prop != NULL) {
3067 if ((prop->ns != NULL) &&
3068 xmlStrEqual(prop->name, BAD_CAST name) &&
3069 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003070 return(prop);
3071 prop = prop->next;
3072 }
3073 return (NULL);
3074}
3075
3076static const xmlChar *
3077xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3078{
3079 xmlChar *val;
3080 const xmlChar *ret;
3081
3082 val = xmlNodeGetContent(node);
3083 if (val == NULL)
3084 return(NULL);
3085 ret = xmlDictLookup(ctxt->dict, val, -1);
3086 xmlFree(val);
3087 return(ret);
3088}
3089
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003090/**
3091 * xmlSchemaGetProp:
3092 * @ctxt: the parser context
3093 * @node: the node
3094 * @name: the property name
3095 *
3096 * Read a attribute value and internalize the string
3097 *
3098 * Returns the string or NULL if not present.
3099 */
3100static const xmlChar *
3101xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3102 const char *name)
3103{
3104 xmlChar *val;
3105 const xmlChar *ret;
3106
3107 val = xmlGetProp(node, BAD_CAST name);
3108 if (val == NULL)
3109 return(NULL);
3110 ret = xmlDictLookup(ctxt->dict, val, -1);
3111 xmlFree(val);
3112 return(ret);
3113}
3114
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003115/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003116 * *
3117 * Parsing functions *
3118 * *
3119 ************************************************************************/
3120
3121/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003122 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003123 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003124 * @name: the element name
3125 * @ns: the element namespace
3126 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003127 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003128 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003129 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003130 */
3131static xmlSchemaElementPtr
3132xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003133 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003134{
3135 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003136
3137 if ((name == NULL) || (schema == NULL))
3138 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003139
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003140 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003141 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003142 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003143 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003144 } else
3145 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003146 /*
3147 * This one was removed, since top level element declarations have
3148 * the target namespace specified in targetNamespace of the <schema>
3149 * information element, even if elementFormDefault is "unqualified".
3150 */
3151
3152 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003153 if (xmlStrEqual(namespace, schema->targetNamespace))
3154 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3155 else
3156 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003157 if ((ret != NULL) &&
3158 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003159 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003160 }
William M. Bracke7091952004-05-11 15:09:58 +00003161 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003162
William M. Brack2f2a6632004-08-20 23:09:47 +00003163 /*
3164 * Removed since imported components will be hold by the main schema only.
3165 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003166 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003167 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003168 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003169 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003170 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003171 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003172 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3173 return (ret);
3174 } else
3175 ret = NULL;
3176 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003177 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003178#ifdef DEBUG
3179 if (ret == NULL) {
3180 if (namespace == NULL)
3181 fprintf(stderr, "Unable to lookup type %s", name);
3182 else
3183 fprintf(stderr, "Unable to lookup type %s:%s", name,
3184 namespace);
3185 }
3186#endif
3187 return (ret);
3188}
3189
3190/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003191 * xmlSchemaGetType:
3192 * @schema: the schemas context
3193 * @name: the type name
3194 * @ns: the type namespace
3195 *
3196 * Lookup a type in the schemas or the predefined types
3197 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003198 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003199 */
3200static xmlSchemaTypePtr
3201xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003202 const xmlChar * namespace)
3203{
Daniel Veillard4255d502002-04-16 15:50:10 +00003204 xmlSchemaTypePtr ret;
3205
3206 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003207 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003208 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003209 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003210 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003211 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003212 }
3213 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003214 if (ret != NULL)
3215 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003216 /*
3217 * Removed, since the imported components will be grafted on the
3218 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003219 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003220 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003221 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003222 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003223 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003224 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003225 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3226 return (ret);
3227 } else
3228 ret = NULL;
3229 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003230 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003231#ifdef DEBUG
3232 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003233 if (namespace == NULL)
3234 fprintf(stderr, "Unable to lookup type %s", name);
3235 else
3236 fprintf(stderr, "Unable to lookup type %s:%s", name,
3237 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003238 }
3239#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003240 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003241}
3242
Daniel Veillard3646d642004-06-02 19:19:14 +00003243/**
3244 * xmlSchemaGetAttribute:
3245 * @schema: the context of the schema
3246 * @name: the name of the attribute
3247 * @ns: the target namespace of the attribute
3248 *
3249 * Lookup a an attribute in the schema or imported schemas
3250 *
3251 * Returns the attribute declaration or NULL if not found.
3252 */
3253static xmlSchemaAttributePtr
3254xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
3255 const xmlChar * namespace)
3256{
3257 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003258
3259 if ((name == NULL) || (schema == NULL))
3260 return (NULL);
3261
3262
3263 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
3264 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
3265 return (ret);
3266 else
3267 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003268 /*
3269 * Removed, since imported components will be hold by the main schema only.
3270 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003271 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003272 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003273 else
3274 import = xmlHashLookup(schema->schemasImports, namespace);
3275 if (import != NULL) {
3276 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
3277 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
3278 return (ret);
3279 } else
3280 ret = NULL;
3281 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003282 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003283#ifdef DEBUG
3284 if (ret == NULL) {
3285 if (namespace == NULL)
3286 fprintf(stderr, "Unable to lookup attribute %s", name);
3287 else
3288 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
3289 namespace);
3290 }
3291#endif
3292 return (ret);
3293}
3294
3295/**
3296 * xmlSchemaGetAttributeGroup:
3297 * @schema: the context of the schema
3298 * @name: the name of the attribute group
3299 * @ns: the target namespace of the attribute group
3300 *
3301 * Lookup a an attribute group in the schema or imported schemas
3302 *
3303 * Returns the attribute group definition or NULL if not found.
3304 */
3305static xmlSchemaAttributeGroupPtr
3306xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
3307 const xmlChar * namespace)
3308{
3309 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003310
3311 if ((name == NULL) || (schema == NULL))
3312 return (NULL);
3313
3314
3315 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
3316 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3317 return (ret);
3318 else
3319 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003320 /*
3321 * Removed since imported components will be hold by the main schema only.
3322 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003323 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003324 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003325 else
3326 import = xmlHashLookup(schema->schemasImports, namespace);
3327 if (import != NULL) {
3328 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
3329 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3330 return (ret);
3331 else
3332 ret = NULL;
3333 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003334 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003335#ifdef DEBUG
3336 if (ret == NULL) {
3337 if (namespace == NULL)
3338 fprintf(stderr, "Unable to lookup attribute group %s", name);
3339 else
3340 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
3341 namespace);
3342 }
3343#endif
3344 return (ret);
3345}
3346
3347/**
3348 * xmlSchemaGetGroup:
3349 * @schema: the context of the schema
3350 * @name: the name of the group
3351 * @ns: the target namespace of the group
3352 *
3353 * Lookup a group in the schema or imported schemas
3354 *
3355 * Returns the group definition or NULL if not found.
3356 */
3357static xmlSchemaTypePtr
3358xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
3359 const xmlChar * namespace)
3360{
3361 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003362
3363 if ((name == NULL) || (schema == NULL))
3364 return (NULL);
3365
3366
3367 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
3368 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3369 return (ret);
3370 else
3371 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003372 /*
3373 * Removed since imported components will be hold by the main schema only.
3374 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003375 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003376 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003377 else
3378 import = xmlHashLookup(schema->schemasImports, namespace);
3379 if (import != NULL) {
3380 ret = xmlSchemaGetGroup(import->schema, name, namespace);
3381 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3382 return (ret);
3383 else
3384 ret = NULL;
3385 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003386 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003387#ifdef DEBUG
3388 if (ret == NULL) {
3389 if (namespace == NULL)
3390 fprintf(stderr, "Unable to lookup group %s", name);
3391 else
3392 fprintf(stderr, "Unable to lookup group %s:%s", name,
3393 namespace);
3394 }
3395#endif
3396 return (ret);
3397}
3398
Daniel Veillard4255d502002-04-16 15:50:10 +00003399/************************************************************************
3400 * *
3401 * Parsing functions *
3402 * *
3403 ************************************************************************/
3404
3405#define IS_BLANK_NODE(n) \
3406 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
3407
3408/**
3409 * xmlSchemaIsBlank:
3410 * @str: a string
3411 *
3412 * Check if a string is ignorable
3413 *
3414 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
3415 */
3416static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003417xmlSchemaIsBlank(xmlChar * str)
3418{
Daniel Veillard4255d502002-04-16 15:50:10 +00003419 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003420 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003421 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00003422 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003423 return (0);
3424 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003425 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003426 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003427}
3428
3429/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003430 * xmlSchemaAddAssembledItem:
3431 * @ctxt: a schema parser context
3432 * @schema: the schema being built
3433 * @item: the item
3434 *
3435 * Add a item to the schema's list of current items.
3436 * This is used if the schema was already constructed and
3437 * new schemata need to be added to it.
3438 * *WARNING* this interface is highly subject to change.
3439 *
3440 * Returns 0 if suceeds and -1 if an internal error occurs.
3441 */
3442static int
3443xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
3444 xmlSchemaTypePtr item)
3445{
3446 static int growSize = 100;
3447 xmlSchemaAssemblePtr ass;
3448
3449 ass = ctxt->assemble;
3450 if (ass->sizeItems < 0) {
3451 /* If disabled. */
3452 return (0);
3453 }
3454 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003455 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003456 if (ass->items == NULL) {
3457 xmlSchemaPErrMemory(ctxt,
3458 "allocating new item buffer", NULL);
3459 return (-1);
3460 }
3461 ass->sizeItems = growSize;
3462 } else if (ass->sizeItems <= ass->nbItems) {
3463 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003464 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003465 ass->sizeItems * sizeof(xmlSchemaTypePtr));
3466 if (ass->items == NULL) {
3467 xmlSchemaPErrMemory(ctxt,
3468 "growing item buffer", NULL);
3469 ass->sizeItems = 0;
3470 return (-1);
3471 }
3472 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003473 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003474 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
3475 return (0);
3476}
3477
3478/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003479 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003480 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003481 * @schema: the schema being built
3482 * @name: the item name
3483 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003484 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003485 * *WARNING* this interface is highly subject to change
3486 *
3487 * Returns the new struture or NULL in case of error
3488 */
3489static xmlSchemaNotationPtr
3490xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003491 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003492{
3493 xmlSchemaNotationPtr ret = NULL;
3494 int val;
3495
3496 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3497 return (NULL);
3498
3499 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003500 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003501 if (schema->notaDecl == NULL)
3502 return (NULL);
3503
3504 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
3505 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003506 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003507 return (NULL);
3508 }
3509 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003510 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003511 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
3512 ret);
3513 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003514 /*
3515 * TODO: This should never happen, since a unique name will be computed.
3516 * If it fails, then an other internal error must have occured.
3517 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003518 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3519 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003520 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003521 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003522 xmlFree(ret);
3523 return (NULL);
3524 }
3525 return (ret);
3526}
3527
3528
3529/**
3530 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003531 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003532 * @schema: the schema being built
3533 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003534 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003535 *
3536 * Add an XML schema Attrribute declaration
3537 * *WARNING* this interface is highly subject to change
3538 *
3539 * Returns the new struture or NULL in case of error
3540 */
3541static xmlSchemaAttributePtr
3542xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003543 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003544 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003545{
3546 xmlSchemaAttributePtr ret = NULL;
3547 int val;
3548
3549 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3550 return (NULL);
3551
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003552#ifdef DEBUG
3553 fprintf(stderr, "Adding attribute %s\n", name);
3554 if (namespace != NULL)
3555 fprintf(stderr, " target namespace %s\n", namespace);
3556#endif
3557
Daniel Veillard4255d502002-04-16 15:50:10 +00003558 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003559 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003560 if (schema->attrDecl == NULL)
3561 return (NULL);
3562
3563 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3564 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003565 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003566 return (NULL);
3567 }
3568 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003569 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003570 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00003571 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003572 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003573 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003574 if (topLevel) {
3575 xmlSchemaPCustomErr(ctxt,
3576 XML_SCHEMAP_REDEFINED_ATTR,
3577 NULL, NULL, node,
3578 "A global attribute declaration with the name '%s' does "
3579 "already exist", name);
3580 xmlFree(ret);
3581 return (NULL);
3582 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003583 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003584 /*
3585 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
3586 * in the scenario:
3587 * 1. multiple top-level complex types have different target
3588 * namespaces but have the SAME NAME; this can happen if
3589 * schemata are imported
3590 * 2. those complex types contain attributes with an equal name
3591 * 3. those attributes are in no namespace
3592 * We will compute a new context string.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003593 */
3594 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003595 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00003596 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003597
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003598 if (val != 0) {
3599 xmlSchemaPCustomErr(ctxt,
3600 XML_SCHEMAP_INTERNAL,
3601 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003602 "Internal error: xmlSchemaAddAttribute, "
3603 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003604 "could not be added to the hash.", name);
3605 xmlFree(ret);
3606 return (NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003607 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003608 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003609 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003610 if (ctxt->assemble != NULL)
3611 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003612 return (ret);
3613}
3614
3615/**
3616 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003617 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003618 * @schema: the schema being built
3619 * @name: the item name
3620 *
3621 * Add an XML schema Attrribute Group declaration
3622 *
3623 * Returns the new struture or NULL in case of error
3624 */
3625static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003626xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003627 xmlSchemaPtr schema, const xmlChar * name,
3628 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003629{
3630 xmlSchemaAttributeGroupPtr ret = NULL;
3631 int val;
3632
3633 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3634 return (NULL);
3635
3636 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003637 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003638 if (schema->attrgrpDecl == NULL)
3639 return (NULL);
3640
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003641 ret =
3642 (xmlSchemaAttributeGroupPtr)
3643 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003644 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003645 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003646 return (NULL);
3647 }
3648 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003649 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003650 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003651 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003652 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003653 xmlSchemaPCustomErr(ctxt,
3654 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3655 NULL, NULL, node,
3656 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003657 xmlFree(ret);
3658 return (NULL);
3659 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003660 if (ctxt->assemble != NULL)
3661 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003662 return (ret);
3663}
3664
3665/**
3666 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003667 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003668 * @schema: the schema being built
3669 * @name: the type name
3670 * @namespace: the type namespace
3671 *
3672 * Add an XML schema Element declaration
3673 * *WARNING* this interface is highly subject to change
3674 *
3675 * Returns the new struture or NULL in case of error
3676 */
3677static xmlSchemaElementPtr
3678xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003679 const xmlChar * name, const xmlChar * namespace,
3680 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003681{
3682 xmlSchemaElementPtr ret = NULL;
3683 int val;
3684
3685 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3686 return (NULL);
3687
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003688#ifdef DEBUG
3689 fprintf(stderr, "Adding element %s\n", name);
3690 if (namespace != NULL)
3691 fprintf(stderr, " target namespace %s\n", namespace);
3692#endif
3693
Daniel Veillard4255d502002-04-16 15:50:10 +00003694 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003695 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003696 if (schema->elemDecl == NULL)
3697 return (NULL);
3698
3699 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3700 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003701 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003702 return (NULL);
3703 }
3704 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003705 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003706 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003707 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003708 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003709 if (topLevel) {
3710 xmlSchemaPCustomErr(ctxt,
3711 XML_SCHEMAP_REDEFINED_ELEMENT,
3712 NULL, NULL, node,
3713 "A global element declaration with the name '%s' does "
3714 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003715 xmlFree(ret);
3716 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003717 } else {
3718 char buf[30];
3719
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003720 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003721 val = xmlHashAddEntry3(schema->elemDecl, name,
3722 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003723 if (val != 0) {
3724 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003725 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003726 NULL, NULL, node,
3727 "Internal error: xmlSchemaAddElement, "
3728 "a dublicate element declaration with the name '%s' "
3729 "could not be added to the hash.", name);
3730 xmlFree(ret);
3731 return (NULL);
3732 }
3733 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003734
Daniel Veillard4255d502002-04-16 15:50:10 +00003735 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003736 if (ctxt->assemble != NULL)
3737 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003738 return (ret);
3739}
3740
3741/**
3742 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003743 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003744 * @schema: the schema being built
3745 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003746 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003747 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003748 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003749 * *WARNING* this interface is highly subject to change
3750 *
3751 * Returns the new struture or NULL in case of error
3752 */
3753static xmlSchemaTypePtr
3754xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003755 const xmlChar * name, const xmlChar * namespace,
3756 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003757{
3758 xmlSchemaTypePtr ret = NULL;
3759 int val;
3760
3761 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3762 return (NULL);
3763
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003764#ifdef DEBUG
3765 fprintf(stderr, "Adding type %s\n", name);
3766 if (namespace != NULL)
3767 fprintf(stderr, " target namespace %s\n", namespace);
3768#endif
3769
Daniel Veillard4255d502002-04-16 15:50:10 +00003770 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003771 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003772 if (schema->typeDecl == NULL)
3773 return (NULL);
3774
3775 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3776 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003777 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003778 return (NULL);
3779 }
3780 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003781 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003782 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003783 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003784 if (val != 0) {
3785 if (ctxt->includes == 0) {
3786 xmlSchemaPCustomErr(ctxt,
3787 XML_SCHEMAP_REDEFINED_TYPE,
3788 NULL, NULL, node,
3789 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003790 xmlFree(ret);
3791 return (NULL);
3792 } else {
3793 xmlSchemaTypePtr prev;
3794
3795 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3796 if (prev == NULL) {
3797 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003798 XML_ERR_INTERNAL_ERROR,
3799 "Internal error: xmlSchemaAddType, on type "
3800 "'%s'.\n",
3801 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003802 xmlFree(ret);
3803 return (NULL);
3804 }
3805 ret->redef = prev->redef;
3806 prev->redef = ret;
3807 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003808 }
3809 ret->minOccurs = 1;
3810 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003811 ret->attributeUses = NULL;
3812 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003813 if (ctxt->assemble != NULL)
3814 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003815 return (ret);
3816}
3817
3818/**
3819 * xmlSchemaAddGroup:
3820 * @ctxt: a schema validation context
3821 * @schema: the schema being built
3822 * @name: the group name
3823 *
3824 * Add an XML schema Group definition
3825 *
3826 * Returns the new struture or NULL in case of error
3827 */
3828static xmlSchemaTypePtr
3829xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003830 const xmlChar *name, const xmlChar *namespaceName,
3831 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003832{
3833 xmlSchemaTypePtr ret = NULL;
3834 int val;
3835
3836 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3837 return (NULL);
3838
3839 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003840 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003841 if (schema->groupDecl == NULL)
3842 return (NULL);
3843
3844 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3845 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003846 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003847 return (NULL);
3848 }
3849 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003850 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003851 val =
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003852 xmlHashAddEntry2(schema->groupDecl, name, namespaceName,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003853 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003854 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003855 xmlSchemaPCustomErr(ctxt,
3856 XML_SCHEMAP_REDEFINED_GROUP,
3857 NULL, NULL, node,
3858 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003859 xmlFree(ret);
3860 return (NULL);
3861 }
3862 ret->minOccurs = 1;
3863 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003864 if (ctxt->assemble != NULL)
3865 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003866 return (ret);
3867}
3868
Daniel Veillard3646d642004-06-02 19:19:14 +00003869/**
3870 * xmlSchemaNewWildcardNs:
3871 * @ctxt: a schema validation context
3872 *
3873 * Creates a new wildcard namespace constraint.
3874 *
3875 * Returns the new struture or NULL in case of error
3876 */
3877static xmlSchemaWildcardNsPtr
3878xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3879{
3880 xmlSchemaWildcardNsPtr ret;
3881
3882 ret = (xmlSchemaWildcardNsPtr)
3883 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3884 if (ret == NULL) {
3885 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3886 return (NULL);
3887 }
3888 ret->value = NULL;
3889 ret->next = NULL;
3890 return (ret);
3891}
3892
3893/**
3894 * xmlSchemaAddWildcard:
3895 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003896 * Adds a wildcard. It corresponds to a
3897 * xsd:anyAttribute and is used as storage for namespace
3898 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003899 *
3900 * Returns the new struture or NULL in case of error
3901 */
3902static xmlSchemaWildcardPtr
3903xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3904{
3905 xmlSchemaWildcardPtr ret = NULL;
3906
3907 if (ctxt == NULL)
3908 return (NULL);
3909
3910 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3911 if (ret == NULL) {
3912 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3913 return (NULL);
3914 }
3915 memset(ret, 0, sizeof(xmlSchemaWildcard));
3916 ret->minOccurs = 1;
3917 ret->maxOccurs = 1;
3918
3919 return (ret);
3920}
3921
Daniel Veillard4255d502002-04-16 15:50:10 +00003922/************************************************************************
3923 * *
3924 * Utilities for parsing *
3925 * *
3926 ************************************************************************/
3927
3928/**
3929 * xmlGetQNameProp:
3930 * @ctxt: a schema validation context
3931 * @node: a subtree containing XML Schema informations
3932 * @name: the attribute name
3933 * @namespace: the result namespace if any
3934 *
3935 * Extract a QName Attribute value
3936 *
3937 * Returns the NCName or NULL if not found, and also update @namespace
3938 * with the namespace URI
3939 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003940static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003941xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003942 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003943{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003944 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003945 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003946 const xmlChar *ret, *prefix;
3947 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003948 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003949
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003950 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003951 attr = xmlSchemaGetPropNode(node, name);
3952 if (attr == NULL)
3953 return (NULL);
3954 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003955
Daniel Veillard4255d502002-04-16 15:50:10 +00003956 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003957 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003958
Daniel Veillardba0153a2004-04-01 10:42:31 +00003959 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003960 ns = xmlSearchNs(node->doc, node, 0);
3961 if (ns) {
3962 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3963 return (val);
3964 }
3965 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003966 ret = xmlSplitQName3(val, &len);
3967 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003968 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003969 }
3970 ret = xmlDictLookup(ctxt->dict, ret, -1);
3971 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003972
3973 ns = xmlSearchNs(node->doc, node, prefix);
3974 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003975 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3976 NULL, NULL, (xmlNodePtr) attr,
3977 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003978 "The QName value '%s' has no corresponding namespace "
3979 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003980 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003981 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003982 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003983 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003984}
3985
3986/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003987 * xmlSchemaPValAttrNodeQNameValue:
3988 * @ctxt: a schema parser context
3989 * @schema: the schema context
3990 * @ownerDes: the designation of the parent element
3991 * @ownerItem: the parent as a schema object
3992 * @value: the QName value
3993 * @local: the resulting local part if found, the attribute value otherwise
3994 * @uri: the resulting namespace URI if found
3995 *
3996 * Extracts the local name and the URI of a QName value and validates it.
3997 * This one is intended to be used on attribute values that
3998 * should resolve to schema components.
3999 *
4000 * Returns 0, in case the QName is valid, a positive error code
4001 * if not valid and -1 if an internal error occurs.
4002 */
4003static int
4004xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
4005 xmlSchemaPtr schema,
4006 xmlChar **ownerDes,
4007 xmlSchemaTypePtr ownerItem,
4008 xmlAttrPtr attr,
4009 const xmlChar *value,
4010 const xmlChar **uri,
4011 const xmlChar **prefix,
4012 const xmlChar **local)
4013{
4014 const xmlChar *pref;
4015 xmlNsPtr ns;
4016 int len, ret;
4017
4018 *uri = NULL;
4019 *local = NULL;
4020 if (prefix != 0)
4021 *prefix = NULL;
4022 ret = xmlValidateQName(value, 1);
4023 if (ret > 0) {
4024 xmlSchemaPSimpleTypeErr(ctxt,
4025 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4026 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004027 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4028 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004029 NULL, NULL, NULL);
4030 *local = value;
4031 return (ctxt->err);
4032 } else if (ret < 0)
4033 return (-1);
4034
4035 if (!strchr((char *) value, ':')) {
4036 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4037 if (ns)
4038 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4039 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4040 /*
4041 * This one takes care of included schemas with no
4042 * target namespace.
4043 */
4044 *uri = schema->targetNamespace;
4045 }
4046 *local = value;
4047 return (0);
4048 }
4049 /*
4050 * At this point xmlSplitQName3 has to return a local name.
4051 */
4052 *local = xmlSplitQName3(value, &len);
4053 *local = xmlDictLookup(ctxt->dict, *local, -1);
4054 pref = xmlDictLookup(ctxt->dict, value, len);
4055 if (prefix != 0)
4056 *prefix = pref;
4057 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4058 if (ns == NULL) {
4059 xmlSchemaPSimpleTypeErr(ctxt,
4060 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4061 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004062 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
4063 "The QName value '%s' has no corresponding namespace "
4064 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004065 return (ctxt->err);
4066 } else {
4067 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4068 }
4069 return (0);
4070}
4071
4072/**
4073 * xmlSchemaPValAttrNodeQName:
4074 * @ctxt: a schema parser context
4075 * @schema: the schema context
4076 * @ownerDes: the designation of the owner element
4077 * @ownerItem: the owner as a schema object
4078 * @attr: the attribute node
4079 * @local: the resulting local part if found, the attribute value otherwise
4080 * @uri: the resulting namespace URI if found
4081 *
4082 * Extracts and validates the QName of an attribute value.
4083 * This one is intended to be used on attribute values that
4084 * should resolve to schema components.
4085 *
4086 * Returns 0, in case the QName is valid, a positive error code
4087 * if not valid and -1 if an internal error occurs.
4088 */
4089static int
4090xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
4091 xmlSchemaPtr schema,
4092 xmlChar **ownerDes,
4093 xmlSchemaTypePtr ownerItem,
4094 xmlAttrPtr attr,
4095 const xmlChar **uri,
4096 const xmlChar **prefix,
4097 const xmlChar **local)
4098{
4099 const xmlChar *value;
4100
4101 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4102 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
4103 ownerDes, ownerItem, attr, value, uri, prefix, local));
4104}
4105
4106/**
4107 * xmlSchemaPValAttrQName:
4108 * @ctxt: a schema parser context
4109 * @schema: the schema context
4110 * @ownerDes: the designation of the parent element
4111 * @ownerItem: the owner as a schema object
4112 * @ownerElem: the parent node of the attribute
4113 * @name: the name of the attribute
4114 * @local: the resulting local part if found, the attribute value otherwise
4115 * @uri: the resulting namespace URI if found
4116 *
4117 * Extracts and validates the QName of an attribute value.
4118 *
4119 * Returns 0, in case the QName is valid, a positive error code
4120 * if not valid and -1 if an internal error occurs.
4121 */
4122static int
4123xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
4124 xmlSchemaPtr schema,
4125 xmlChar **ownerDes,
4126 xmlSchemaTypePtr ownerItem,
4127 xmlNodePtr ownerElem,
4128 const char *name,
4129 const xmlChar **uri,
4130 const xmlChar **prefix,
4131 const xmlChar **local)
4132{
4133 xmlAttrPtr attr;
4134
4135 attr = xmlSchemaGetPropNode(ownerElem, name);
4136 if (attr == NULL) {
4137 *local = NULL;
4138 *uri = NULL;
4139 return (0);
4140 }
4141 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
4142 ownerDes, ownerItem, attr, uri, prefix, local));
4143}
4144
4145/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004146 * xmlSchemaPValAttrID:
4147 * @ctxt: a schema parser context
4148 * @schema: the schema context
4149 * @ownerDes: the designation of the parent element
4150 * @ownerItem: the owner as a schema object
4151 * @ownerElem: the parent node of the attribute
4152 * @name: the name of the attribute
4153 *
4154 * Extracts and validates the ID of an attribute value.
4155 *
4156 * Returns 0, in case the ID is valid, a positive error code
4157 * if not valid and -1 if an internal error occurs.
4158 */
4159static int
4160xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
4161 xmlChar **ownerDes,
4162 xmlSchemaTypePtr ownerItem,
4163 xmlNodePtr ownerElem,
4164 const xmlChar *name)
4165{
4166 int ret;
4167 xmlChar *value;
4168 xmlAttrPtr attr;
4169
4170 value = xmlGetNoNsProp(ownerElem, name);
4171 if (value == NULL)
4172 return (0);
4173
4174 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
4175 if (attr == NULL)
4176 return (-1);
4177
4178 ret = xmlValidateNCName(BAD_CAST value, 1);
4179 if (ret == 0) {
4180 /*
4181 * NOTE: the IDness might have already be declared in the DTD
4182 */
4183 if (attr->atype != XML_ATTRIBUTE_ID) {
4184 xmlIDPtr res;
4185 xmlChar *strip;
4186
4187 /*
4188 * TODO: Use xmlSchemaStrip here; it's not exported at this
4189 * moment.
4190 */
4191 strip = xmlSchemaCollapseString(BAD_CAST value);
4192 if (strip != NULL)
4193 value = strip;
4194 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
4195 if (res == NULL) {
4196 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
4197 xmlSchemaPSimpleTypeErr(ctxt,
4198 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4199 ownerDes, ownerItem, (xmlNodePtr) attr,
4200 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
4201 NULL, NULL, "The ID '%s' already defined",
4202 BAD_CAST value, NULL);
4203 } else
4204 attr->atype = XML_ATTRIBUTE_ID;
4205 if (strip != NULL)
4206 xmlFree(strip);
4207 }
4208 } else if (ret > 0) {
4209 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
4210 xmlSchemaPSimpleTypeErr(ctxt,
4211 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4212 ownerDes, ownerItem, (xmlNodePtr) attr,
4213 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
4214 NULL, BAD_CAST value, NULL, NULL, NULL);
4215 }
4216 xmlFree(value);
4217
4218 return (ret);
4219}
4220
4221/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004222 * xmlGetMaxOccurs:
4223 * @ctxt: a schema validation context
4224 * @node: a subtree containing XML Schema informations
4225 *
4226 * Get the maxOccurs property
4227 *
4228 * Returns the default if not found, or the value
4229 */
4230static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004231xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4232 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004233{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004234 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004235 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004236 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004237
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004238 attr = xmlSchemaGetPropNode(node, "maxOccurs");
4239 if (attr == NULL)
4240 return (def);
4241 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004242
4243 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004244 if (max != UNBOUNDED) {
4245 xmlSchemaPSimpleTypeErr(ctxt,
4246 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4247 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4248 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4249 val, NULL, NULL, NULL);
4250 return (def);
4251 } else
4252 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00004253 }
4254
4255 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004256 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004257 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004258 if (*cur == 0) {
4259 xmlSchemaPSimpleTypeErr(ctxt,
4260 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4261 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4262 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4263 val, NULL, NULL, NULL);
4264 return (def);
4265 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004266 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004267 ret = ret * 10 + (*cur - '0');
4268 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004269 }
William M. Brack76e95df2003-10-18 16:20:14 +00004270 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004271 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004272 /*
4273 * TODO: Restrict the maximal value to Integer.
4274 */
4275 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4276 xmlSchemaPSimpleTypeErr(ctxt,
4277 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4278 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4279 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4280 val, NULL, NULL, NULL);
4281 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004282 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004283 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004284}
4285
4286/**
4287 * xmlGetMinOccurs:
4288 * @ctxt: a schema validation context
4289 * @node: a subtree containing XML Schema informations
4290 *
4291 * Get the minOccurs property
4292 *
4293 * Returns the default if not found, or the value
4294 */
4295static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004296xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4297 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004298{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004299 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004300 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004301 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004302
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004303 attr = xmlSchemaGetPropNode(node, "minOccurs");
4304 if (attr == NULL)
4305 return (def);
4306 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004307 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004308 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004309 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004310 if (*cur == 0) {
4311 xmlSchemaPSimpleTypeErr(ctxt,
4312 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4313 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4314 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4315 val, NULL, NULL, NULL);
4316 return (def);
4317 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004318 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004319 ret = ret * 10 + (*cur - '0');
4320 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004321 }
William M. Brack76e95df2003-10-18 16:20:14 +00004322 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004323 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004324 /*
4325 * TODO: Restrict the maximal value to Integer.
4326 */
4327 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4328 xmlSchemaPSimpleTypeErr(ctxt,
4329 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4330 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4331 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4332 val, NULL, NULL, NULL);
4333 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004334 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004335 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004336}
4337
4338/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004339 * xmlSchemaPGetBoolNodeValue:
4340 * @ctxt: a schema validation context
4341 * @ownerDes: owner designation
4342 * @ownerItem: the owner as a schema item
4343 * @node: the node holding the value
4344 *
4345 * Converts a boolean string value into 1 or 0.
4346 *
4347 * Returns 0 or 1.
4348 */
4349static int
4350xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
4351 xmlChar **ownerDes,
4352 xmlSchemaTypePtr ownerItem,
4353 xmlNodePtr node)
4354{
4355 xmlChar *value = NULL;
4356 int res = 0;
4357
4358 value = xmlNodeGetContent(node);
4359 /*
4360 * 3.2.2.1 Lexical representation
4361 * An instance of a datatype that is defined as ·boolean·
4362 * can have the following legal literals {true, false, 1, 0}.
4363 */
4364 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
4365 res = 1;
4366 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
4367 res = 0;
4368 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
4369 res = 1;
4370 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
4371 res = 0;
4372 else {
4373 xmlSchemaPSimpleTypeErr(ctxt,
4374 XML_SCHEMAP_INVALID_BOOLEAN,
4375 ownerDes, ownerItem, node,
4376 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4377 "(1 | 0 | true | false)", BAD_CAST value,
4378 NULL, NULL, NULL);
4379 }
4380 if (value != NULL)
4381 xmlFree(value);
4382 return (res);
4383}
4384
4385/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004386 * xmlGetBooleanProp:
4387 * @ctxt: a schema validation context
4388 * @node: a subtree containing XML Schema informations
4389 * @name: the attribute name
4390 * @def: the default value
4391 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004392 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00004393 *
4394 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004395 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00004396 */
4397static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004398xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
4399 xmlChar **ownerDes,
4400 xmlSchemaTypePtr ownerItem,
4401 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004402 const char *name, int def)
4403{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004404 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004405
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004406 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004407 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004408 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004409 /*
4410 * 3.2.2.1 Lexical representation
4411 * An instance of a datatype that is defined as ·boolean·
4412 * can have the following legal literals {true, false, 1, 0}.
4413 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004414 if (xmlStrEqual(val, BAD_CAST "true"))
4415 def = 1;
4416 else if (xmlStrEqual(val, BAD_CAST "false"))
4417 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004418 else if (xmlStrEqual(val, BAD_CAST "1"))
4419 def = 1;
4420 else if (xmlStrEqual(val, BAD_CAST "0"))
4421 def = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004422 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004423 xmlSchemaPSimpleTypeErr(ctxt,
4424 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004425 ownerDes, ownerItem,
4426 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
William M. Brack2f2a6632004-08-20 23:09:47 +00004427 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4428 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004429 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004430 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004431}
4432
4433/************************************************************************
4434 * *
4435 * Shema extraction from an Infoset *
4436 * *
4437 ************************************************************************/
4438static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
4439 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004440 xmlNodePtr node,
4441 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004442static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
4443 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004444 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004445 xmlNodePtr node,
4446 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004447static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
4448 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004449 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004450 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004451static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
4452 xmlSchemaPtr schema,
4453 xmlNodePtr node);
4454static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
4455 xmlSchemaPtr schema,
4456 xmlNodePtr node);
4457static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
4458 ctxt,
4459 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004460 xmlNodePtr node,
4461 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004462static xmlSchemaAttributeGroupPtr
4463xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004464 xmlSchemaPtr schema, xmlNodePtr node,
4465 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004466static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
4467 xmlSchemaPtr schema,
4468 xmlNodePtr node);
4469static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
4470 xmlSchemaPtr schema,
4471 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00004472static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004473xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4474 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004475
4476/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004477 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004478 *
4479 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00004480 * @ownerDes: the designation of the parent element
4481 * @ownerItem: the schema object owner if existent
4482 * @attr: the schema attribute node being validated
4483 * @value: the value
4484 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00004485 *
4486 * Validates a value against the given built-in type.
4487 * This one is intended to be used internally for validation
4488 * of schema attribute values during parsing of the schema.
4489 *
4490 * Returns 0 if the value is valid, a positive error code
4491 * number otherwise and -1 in case of an internal or API error.
4492 */
4493static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004494xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
4495 xmlChar **ownerDes,
4496 xmlSchemaTypePtr ownerItem,
4497 xmlAttrPtr attr,
4498 const xmlChar *value,
4499 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004500{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004501
Daniel Veillardc0826a72004-08-10 14:17:33 +00004502 int ret = 0;
4503
4504 /*
4505 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
4506 * one is really meant to be used internally, so better not.
4507 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004508 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004509 return (-1);
4510 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4511 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004512 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004513 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004514 "type '%s' is not a built-in type.\n",
4515 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004516 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004517 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004518 switch (type->builtInType) {
4519 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004520 case XML_SCHEMAS_QNAME:
4521 case XML_SCHEMAS_ANYURI:
4522 case XML_SCHEMAS_TOKEN:
4523 case XML_SCHEMAS_LANGUAGE:
4524 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
4525 break;
4526
4527 /*
4528 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004529 ret = xmlValidateNCName(value, 1);
4530 break;
4531 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00004532 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004533 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004534 "Internal error: xmlSchemaPvalueAttrNode, use "
4535 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
4536 "for extracting QName valueues instead.\n",
4537 NULL, NULL);
4538 return (-1);
4539 case XML_SCHEMAS_ANYURI:
4540 if (value != NULL) {
4541 xmlURIPtr uri = xmlParseURI((const char *) value);
4542 if (uri == NULL)
4543 ret = 1;
4544 else
4545 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004546 }
4547 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004548 case XML_SCHEMAS_TOKEN: {
4549 const xmlChar *cur = value;
4550
4551 if (IS_BLANK_CH(*cur)) {
4552 ret = 1;
4553 } else while (*cur != 0) {
4554 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
4555 ret = 1;
4556 break;
4557 } else if (*cur == ' ') {
4558 cur++;
4559 if ((*cur == 0) || (*cur == ' ')) {
4560 ret = 1;
4561 break;
4562 }
4563 } else {
4564 cur++;
4565 }
4566 }
4567 }
4568 break;
4569 case XML_SCHEMAS_LANGUAGE:
4570 if (xmlCheckLanguageID(value) != 1)
4571 ret = 1;
4572 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004573 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004574 default: {
4575 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004576 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004577 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004578 "valueidation using the type '%s' is not implemented "
4579 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00004580 type->name, NULL);
4581 return (-1);
4582 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004583 }
4584 /*
4585 * TODO: Should we use the S4S error codes instead?
4586 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004587 if (ret < 0) {
4588 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
4589 XML_SCHEMAP_INTERNAL,
4590 "Internal error: xmlSchemaPValAttrNodeValue, "
4591 "failed to validate a schema attribute value.\n",
4592 NULL, NULL);
4593 return (-1);
4594 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004595 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
4596 xmlSchemaPSimpleTypeErr(ctxt,
4597 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
4598 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004599 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004600 NULL, NULL, NULL);
4601 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
4602 } else {
4603 xmlSchemaPSimpleTypeErr(ctxt,
4604 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
4605 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004606 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004607 NULL, NULL, NULL);
4608 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
4609 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004610 }
4611 return (ret);
4612}
4613
4614/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004615 * xmlSchemaPValAttrNode:
4616 *
4617 * @ctxt: a schema parser context
4618 * @ownerDes: the designation of the parent element
4619 * @ownerItem: the schema object owner if existent
4620 * @attr: the schema attribute node being validated
4621 * @type: the built-in type to be validated against
4622 * @value: the resulting value if any
4623 *
4624 * Extracts and validates a value against the given built-in type.
4625 * This one is intended to be used internally for validation
4626 * of schema attribute values during parsing of the schema.
4627 *
4628 * Returns 0 if the value is valid, a positive error code
4629 * number otherwise and -1 in case of an internal or API error.
4630 */
4631static int
4632xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4633 xmlChar **ownerDes,
4634 xmlSchemaTypePtr ownerItem,
4635 xmlAttrPtr attr,
4636 xmlSchemaTypePtr type,
4637 const xmlChar **value)
4638{
4639 const xmlChar *val;
4640
4641 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4642 return (-1);
4643
4644 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4645 if (value != NULL)
4646 *value = val;
4647
4648 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4649 val, type));
4650}
4651
4652/**
4653 * xmlSchemaPValAttr:
4654 *
4655 * @ctxt: a schema parser context
4656 * @node: the element node of the attribute
4657 * @ownerDes: the designation of the parent element
4658 * @ownerItem: the schema object owner if existent
4659 * @ownerElem: the owner element node
4660 * @name: the name of the schema attribute node
4661 * @type: the built-in type to be validated against
4662 * @value: the resulting value if any
4663 *
4664 * Extracts and validates a value against the given built-in type.
4665 * This one is intended to be used internally for validation
4666 * of schema attribute values during parsing of the schema.
4667 *
4668 * Returns 0 if the value is valid, a positive error code
4669 * number otherwise and -1 in case of an internal or API error.
4670 */
4671static int
4672xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4673 xmlChar **ownerDes,
4674 xmlSchemaTypePtr ownerItem,
4675 xmlNodePtr ownerElem,
4676 const char *name,
4677 xmlSchemaTypePtr type,
4678 const xmlChar **value)
4679{
4680 xmlAttrPtr attr;
4681
4682 if ((ctxt == NULL) || (type == NULL)) {
4683 if (value != NULL)
4684 *value = NULL;
4685 return (-1);
4686 }
4687 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4688 if (value != NULL)
4689 *value = NULL;
4690 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004691 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004692 "Internal error: xmlSchemaPValAttr, the given "
4693 "type '%s' is not a built-in type.\n",
4694 type->name, NULL);
4695 return (-1);
4696 }
4697 attr = xmlSchemaGetPropNode(ownerElem, name);
4698 if (attr == NULL) {
4699 if (value != NULL)
4700 *value = NULL;
4701 return (0);
4702 }
4703 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4704 type, value));
4705}
4706/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004707 * xmlSchemaParseAttrDecls:
4708 * @ctxt: a schema validation context
4709 * @schema: the schema being built
4710 * @node: a subtree containing XML Schema informations
4711 * @type: the hosting type
4712 *
4713 * parse a XML schema attrDecls declaration corresponding to
4714 * <!ENTITY % attrDecls
4715 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4716 */
4717static xmlNodePtr
4718xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4719 xmlNodePtr child, xmlSchemaTypePtr type)
4720{
4721 xmlSchemaAttributePtr lastattr, attr;
4722
4723 lastattr = NULL;
4724 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004725 (IS_SCHEMA(child, "attributeGroup"))) {
4726 attr = NULL;
4727 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004728 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004729 } else if (IS_SCHEMA(child, "attributeGroup")) {
4730 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004731 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004732 }
4733 if (attr != NULL) {
4734 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004735 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4736 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4737 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004738 type->attributes = attr;
4739 lastattr = attr;
4740 } else {
4741 lastattr->next = attr;
4742 lastattr = attr;
4743 }
4744 }
4745 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004746 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004747 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004748}
4749
4750/**
4751 * xmlSchemaParseAnnotation:
4752 * @ctxt: a schema validation context
4753 * @schema: the schema being built
4754 * @node: a subtree containing XML Schema informations
4755 *
4756 * parse a XML schema Attrribute declaration
4757 * *WARNING* this interface is highly subject to change
4758 *
William M. Bracke7091952004-05-11 15:09:58 +00004759 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004760 * 1 in case of success.
4761 */
4762static xmlSchemaAnnotPtr
4763xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4764 xmlNodePtr node)
4765{
4766 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004767 xmlNodePtr child = NULL;
4768 xmlAttrPtr attr;
4769 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004770
Daniel Veillardc0826a72004-08-10 14:17:33 +00004771 /*
4772 * INFO: S4S completed.
4773 */
4774 /*
4775 * id = ID
4776 * {any attributes with non-schema namespace . . .}>
4777 * Content: (appinfo | documentation)*
4778 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004779 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4780 return (NULL);
4781 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004782 attr = node->properties;
4783 while (attr != NULL) {
4784 if (((attr->ns == NULL) &&
4785 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4786 ((attr->ns != NULL) &&
4787 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4788
4789 xmlSchemaPIllegalAttrErr(ctxt,
4790 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4791 NULL, NULL, attr);
4792 }
4793 attr = attr->next;
4794 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004795 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00004796 /*
4797 * And now for the children...
4798 */
4799 child = node->children;
4800 while (child != NULL) {
4801 if (IS_SCHEMA(child, "appinfo")) {
4802 /* TODO: make available the content of "appinfo". */
4803 /*
4804 * source = anyURI
4805 * {any attributes with non-schema namespace . . .}>
4806 * Content: ({any})*
4807 */
4808 attr = child->properties;
4809 while (attr != NULL) {
4810 if (((attr->ns == NULL) &&
4811 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4812 ((attr->ns != NULL) &&
4813 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004814
Daniel Veillardc0826a72004-08-10 14:17:33 +00004815 xmlSchemaPIllegalAttrErr(ctxt,
4816 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4817 NULL, NULL, attr);
4818 }
4819 attr = attr->next;
4820 }
4821 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4822 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4823 child = child->next;
4824 } else if (IS_SCHEMA(child, "documentation")) {
4825 /* TODO: make available the content of "documentation". */
4826 /*
4827 * source = anyURI
4828 * {any attributes with non-schema namespace . . .}>
4829 * Content: ({any})*
4830 */
4831 attr = child->properties;
4832 while (attr != NULL) {
4833 if (attr->ns == NULL) {
4834 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4835 xmlSchemaPIllegalAttrErr(ctxt,
4836 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4837 NULL, NULL, attr);
4838 }
4839 } else {
4840 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4841 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4842 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4843
4844 xmlSchemaPIllegalAttrErr(ctxt,
4845 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4846 NULL, NULL, attr);
4847 }
4848 }
4849 attr = attr->next;
4850 }
4851 /*
4852 * Attribute "xml:lang".
4853 */
4854 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4855 if (attr != NULL)
4856 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4857 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4858 child = child->next;
4859 } else {
4860 if (!barked)
4861 xmlSchemaPContentErr(ctxt,
4862 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4863 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4864 barked = 1;
4865 child = child->next;
4866 }
4867 }
4868
Daniel Veillard4255d502002-04-16 15:50:10 +00004869 return (ret);
4870}
4871
4872/**
4873 * xmlSchemaParseFacet:
4874 * @ctxt: a schema validation context
4875 * @schema: the schema being built
4876 * @node: a subtree containing XML Schema informations
4877 *
4878 * parse a XML schema Facet declaration
4879 * *WARNING* this interface is highly subject to change
4880 *
4881 * Returns the new type structure or NULL in case of error
4882 */
4883static xmlSchemaFacetPtr
4884xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004885 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004886{
4887 xmlSchemaFacetPtr facet;
4888 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004889 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004890
4891 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4892 return (NULL);
4893
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004894 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004895 if (facet == NULL) {
4896 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4897 return (NULL);
4898 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004899 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004900 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004901 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004902 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4903 "Facet %s has no value\n", node->name, NULL);
4904 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004905 return (NULL);
4906 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004907 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004908 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004909 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004910 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004911 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004912 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004913 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004914 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004915 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004916 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004917 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004918 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004919 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004920 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004921 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004922 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004923 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004924 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004925 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004926 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004927 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004928 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4929 } else if (IS_SCHEMA(node, "minLength")) {
4930 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4931 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004932 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4933 "Unknown facet type %s\n", node->name, NULL);
4934 xmlSchemaFreeFacet(facet);
4935 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004936 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004937 xmlSchemaPValAttrID(ctxt, NULL,
4938 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004939 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004940 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4941 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4942 const xmlChar *fixed;
4943
4944 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4945 if (fixed != NULL) {
4946 if (xmlStrEqual(fixed, BAD_CAST "true"))
4947 facet->fixed = 1;
4948 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004949 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004950 child = node->children;
4951
4952 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004953 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4954 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004955 }
4956 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004957 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4958 "Facet %s has unexpected child content\n",
4959 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004960 }
4961 return (facet);
4962}
4963
4964/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004965 * xmlSchemaParseWildcardNs:
4966 * @ctxt: a schema parser context
4967 * @wildc: the wildcard, already created
4968 * @node: a subtree containing XML Schema informations
4969 *
4970 * Parses the attribute "processContents" and "namespace"
4971 * of a xsd:anyAttribute and xsd:any.
4972 * *WARNING* this interface is highly subject to change
4973 *
4974 * Returns 0 if everything goes fine, a positive error code
4975 * if something is not valid and -1 if an internal error occurs.
4976 */
4977static int
4978xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4979 xmlSchemaPtr schema,
4980 xmlSchemaWildcardPtr wildc,
4981 xmlNodePtr node)
4982{
4983 const xmlChar *pc, *ns, *dictnsItem;
4984 int ret = 0;
4985 xmlChar *nsItem;
4986 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4987 xmlAttrPtr attr;
4988
4989 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4990 if ((pc == NULL)
4991 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4992 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4993 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4994 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4995 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4996 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4997 } else {
4998 xmlSchemaPSimpleTypeErr(ctxt,
4999 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
5000 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00005001 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005002 NULL, NULL, NULL);
5003 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5004 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
5005 }
5006 /*
5007 * Build the namespace constraints.
5008 */
5009 attr = xmlSchemaGetPropNode(node, "namespace");
5010 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5011 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
5012 wildc->any = 1;
5013 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5014 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5015 if (wildc->negNsSet == NULL) {
5016 return (-1);
5017 }
5018 wildc->negNsSet->value = schema->targetNamespace;
5019 } else {
5020 const xmlChar *end, *cur;
5021
5022 cur = ns;
5023 do {
5024 while (IS_BLANK_CH(*cur))
5025 cur++;
5026 end = cur;
5027 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5028 end++;
5029 if (end == cur)
5030 break;
5031 nsItem = xmlStrndup(cur, end - cur);
5032 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5033 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
5034 xmlSchemaPSimpleTypeErr(ctxt,
5035 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
5036 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005037 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005038 "((##any | ##other) | List of (anyURI | "
5039 "(##targetNamespace | ##local)))",
5040 nsItem, NULL, NULL, NULL);
5041 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5042 } else {
5043 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5044 dictnsItem = schema->targetNamespace;
5045 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5046 dictnsItem = NULL;
5047 } else {
5048 /*
5049 * Validate the item (anyURI).
5050 */
5051 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
5052 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5053 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5054 }
5055 /*
5056 * Avoid dublicate namespaces.
5057 */
5058 tmp = wildc->nsSet;
5059 while (tmp != NULL) {
5060 if (dictnsItem == tmp->value)
5061 break;
5062 tmp = tmp->next;
5063 }
5064 if (tmp == NULL) {
5065 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5066 if (tmp == NULL) {
5067 xmlFree(nsItem);
5068 return (-1);
5069 }
5070 tmp->value = dictnsItem;
5071 tmp->next = NULL;
5072 if (wildc->nsSet == NULL)
5073 wildc->nsSet = tmp;
5074 else
5075 lastNs->next = tmp;
5076 lastNs = tmp;
5077 }
5078
5079 }
5080 xmlFree(nsItem);
5081 cur = end;
5082 } while (*cur != 0);
5083 }
5084 return (ret);
5085}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005086
5087static int
5088xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
5089 xmlSchemaTypePtr item,
5090 xmlNodePtr node,
5091 int minOccurs,
5092 int maxOccurs) {
5093
5094 if (maxOccurs != UNBOUNDED) {
5095 /*
5096 * TODO: Maby we should better not create the particle,
5097 * if min/max is invalid, since it could confuse the build of the
5098 * content model.
5099 */
5100 /*
5101 * 3.9.6 Schema Component Constraint: Particle Correct
5102 *
5103 */
5104 if (maxOccurs < 1) {
5105 /*
5106 * 2.2 {max occurs} must be greater than or equal to 1.
5107 */
5108 xmlSchemaPCustomAttrErr(ctxt,
5109 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
5110 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
5111 "The value must be greater than or equal to 1");
5112 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
5113 } else if (minOccurs > maxOccurs) {
5114 /*
5115 * 2.1 {min occurs} must not be greater than {max occurs}.
5116 */
5117 xmlSchemaPCustomAttrErr(ctxt,
5118 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
5119 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
5120 "The value must not be greater than the value of 'maxOccurs'");
5121 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
5122 }
5123 }
5124 return (0);
5125}
5126
Daniel Veillardc0826a72004-08-10 14:17:33 +00005127/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005128 * xmlSchemaParseAny:
5129 * @ctxt: a schema validation context
5130 * @schema: the schema being built
5131 * @node: a subtree containing XML Schema informations
5132 *
5133 * parse a XML schema Any declaration
5134 * *WARNING* this interface is highly subject to change
5135 *
5136 * Returns the new type structure or NULL in case of error
5137 */
5138static xmlSchemaTypePtr
5139xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5140 xmlNodePtr node)
5141{
5142 xmlSchemaTypePtr type;
5143 xmlNodePtr child = NULL;
5144 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005145 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005146 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005147
5148 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5149 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005150 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
5151 "(nonNegativeInteger | unbounded)");
5152 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
5153 "nonNegativeInteger");
5154 if ((minOccurs == 0) && (maxOccurs == 0))
5155 return (NULL);
5156
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005157 snprintf((char *) name, 30, "#any%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005158 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005159 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005160 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005161 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005162 type->type = XML_SCHEMA_TYPE_ANY;
5163
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005164 /*
5165 * TODO: Use a particle component here.
5166 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005167 wildc = xmlSchemaAddWildcard(ctxt);
5168 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005169 * Check min/max sanity.
5170 */
5171 type->maxOccurs = maxOccurs;
5172 type->minOccurs = minOccurs;
5173 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
5174 node, type->minOccurs, type->maxOccurs);
5175 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005176 * This is not nice, since it is won't be used as a attribute wildcard,
5177 * but better than adding a field to the structure.
5178 */
5179 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005180 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005181 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005182 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005183 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5184 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005185 }
5186 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005187 xmlSchemaPErr2(ctxt, node, child,
5188 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
5189 "Sequence %s has unexpected content\n", type->name,
5190 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005191 }
5192
5193 return (type);
5194}
5195
5196/**
5197 * xmlSchemaParseNotation:
5198 * @ctxt: a schema validation context
5199 * @schema: the schema being built
5200 * @node: a subtree containing XML Schema informations
5201 *
5202 * parse a XML schema Notation declaration
5203 *
5204 * Returns the new structure or NULL in case of error
5205 */
5206static xmlSchemaNotationPtr
5207xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005208 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005209{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005210 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005211 xmlSchemaNotationPtr ret;
5212 xmlNodePtr child = NULL;
5213
5214 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5215 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005216 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005217 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005218 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
5219 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005220 return (NULL);
5221 }
5222 ret = xmlSchemaAddNotation(ctxt, schema, name);
5223 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005224 return (NULL);
5225 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005226 ret->targetNamespace = schema->targetNamespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00005227 child = node->children;
5228 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005229 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5230 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005231 }
5232 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005233 xmlSchemaPErr2(ctxt, node, child,
5234 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
5235 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005236 }
5237
5238 return (ret);
5239}
5240
5241/**
5242 * xmlSchemaParseAnyAttribute:
5243 * @ctxt: a schema validation context
5244 * @schema: the schema being built
5245 * @node: a subtree containing XML Schema informations
5246 *
5247 * parse a XML schema AnyAttrribute declaration
5248 * *WARNING* this interface is highly subject to change
5249 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005250 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00005251 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005252static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005253xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5254 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005255{
Daniel Veillard3646d642004-06-02 19:19:14 +00005256 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005257 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005258 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005259
5260 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5261 return (NULL);
5262
Daniel Veillard3646d642004-06-02 19:19:14 +00005263 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005264 if (ret == NULL) {
5265 return (NULL);
5266 }
William M. Bracke7091952004-05-11 15:09:58 +00005267 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005268 /*
5269 * Check for illegal attributes.
5270 */
5271 attr = node->properties;
5272 while (attr != NULL) {
5273 if (attr->ns == NULL) {
5274 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5275 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
5276 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
5277 xmlSchemaPIllegalAttrErr(ctxt,
5278 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5279 NULL, NULL, attr);
5280 }
5281 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5282 xmlSchemaPIllegalAttrErr(ctxt,
5283 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5284 NULL, NULL, attr);
5285 }
5286 attr = attr->next;
5287 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005288 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5289 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005290 /*
5291 * Parse the namespace list.
5292 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005293 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
5294 xmlSchemaFreeWildcard(ret);
5295 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005296 }
5297 /*
5298 * And now for the children...
5299 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005300 child = node->children;
5301 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005302 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5303 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005304 }
5305 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005306 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005307 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5308 NULL, NULL, node, child,
5309 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005310 }
5311
5312 return (ret);
5313}
5314
5315
5316/**
5317 * xmlSchemaParseAttribute:
5318 * @ctxt: a schema validation context
5319 * @schema: the schema being built
5320 * @node: a subtree containing XML Schema informations
5321 *
5322 * parse a XML schema Attrribute declaration
5323 * *WARNING* this interface is highly subject to change
5324 *
William M. Bracke7091952004-05-11 15:09:58 +00005325 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005326 */
5327static xmlSchemaAttributePtr
5328xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005329 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005330{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005331 const xmlChar *name, *attrValue;
5332 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00005333 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005334 xmlNodePtr child = NULL;
5335 xmlAttrPtr attr, nameAttr;
5336 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005337
5338 /*
5339 * Note that the w3c spec assumes the schema to be validated with schema
5340 * for schemas beforehand.
5341 *
5342 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00005343 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005344
5345 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5346 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005347 attr = xmlSchemaGetPropNode(node, "ref");
5348 nameAttr = xmlSchemaGetPropNode(node, "name");
5349
5350 if ((attr == NULL) && (nameAttr == NULL)) {
5351 /*
5352 * 3.2.3 : 3.1
5353 * One of ref or name must be present, but not both
5354 */
5355 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5356 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
5357 "One of the attributes 'ref' or 'name' must be present");
5358 return (NULL);
5359 }
5360 if ((topLevel) || (attr == NULL)) {
5361 if (nameAttr == NULL) {
5362 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
5363 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5364 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005365 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005366 }
5367 } else
5368 isRef = 1;
5369
5370 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005371 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005372 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
5373
5374 /*
5375 * Parse as attribute reference.
5376 */
5377 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
5378 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
5379 &refPrefix, &ref) != 0) {
5380 return (NULL);
5381 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005382 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005383 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005384 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005385 if (ret == NULL) {
5386 if (repName != NULL)
5387 xmlFree(repName);
5388 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005389 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005390 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5391 ret->node = node;
5392 ret->refNs = refNs;
5393 ret->refPrefix = refPrefix;
5394 ret->ref = ref;
5395 /*
5396 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
5397 */
5398 if (nameAttr != NULL)
5399 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5400 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5401 "ref", "name");
5402 /*
5403 * Check for illegal attributes.
5404 */
5405 attr = node->properties;
5406 while (attr != NULL) {
5407 if (attr->ns == NULL) {
5408 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
5409 xmlStrEqual(attr->name, BAD_CAST "form")) {
5410 /*
5411 * 3.2.3 : 3.2
5412 * If ref is present, then all of <simpleType>,
5413 * form and type must be absent.
5414 */
5415 xmlSchemaPIllegalAttrErr(ctxt,
5416 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
5417 (xmlSchemaTypePtr) ret, attr);
5418 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
5419 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
5420 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5421 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5422 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5423 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
5424 xmlSchemaPIllegalAttrErr(ctxt,
5425 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5426 &repName, (xmlSchemaTypePtr) ret, attr);
5427 }
5428 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5429 xmlSchemaPIllegalAttrErr(ctxt,
5430 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5431 &repName, (xmlSchemaTypePtr) ret, attr);
5432 }
5433 attr = attr->next;
5434 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005435 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005436 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005437
5438 /*
5439 * Parse as attribute declaration.
5440 */
5441 if (xmlSchemaPValAttrNode(ctxt,
5442 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
5443 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5444 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005445 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005446 /*
5447 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
5448 */
5449 /*
5450 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
5451 */
5452 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
5453 xmlSchemaPSimpleTypeErr(ctxt,
5454 XML_SCHEMAP_NO_XMLNS,
5455 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005456 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005457 "The value must not match 'xmlns'",
5458 NULL, NULL);
5459 if (repName != NULL)
5460 xmlFree(repName);
5461 return (NULL);
5462 }
5463 /*
5464 * Evaluate the target namespace
5465 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005466 if (topLevel) {
5467 ns = schema->targetNamespace;
5468 } else {
5469 attr = xmlSchemaGetPropNode(node, "form");
5470 if (attr != NULL) {
5471 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5472 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
5473 ns = schema->targetNamespace;
5474 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5475 xmlSchemaPSimpleTypeErr(ctxt,
5476 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5477 &repName, NULL, (xmlNodePtr) attr,
5478 NULL, "(qualified | unqualified)",
5479 attrValue, NULL, NULL, NULL);
5480 }
5481 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
5482 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005483 }
5484 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005485 if (ret == NULL) {
5486 if (repName != NULL)
5487 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00005488 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005489 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005490 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005491 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005492 if (topLevel)
5493 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
5494 /*
5495 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
5496 */
5497 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
5498 xmlSchemaPCustomErr(ctxt,
5499 XML_SCHEMAP_NO_XSI,
5500 &repName, (xmlSchemaTypePtr) ret, node,
5501 "The target namespace must not match '%s'",
5502 xmlSchemaInstanceNs);
5503 }
5504 /*
5505 * Check for illegal attributes.
5506 */
5507 attr = node->properties;
5508 while (attr != NULL) {
5509 if (attr->ns == NULL) {
5510 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5511 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5512 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5513 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5514 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
5515 if ((topLevel) ||
5516 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
5517 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
5518 xmlSchemaPIllegalAttrErr(ctxt,
5519 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5520 &repName, (xmlSchemaTypePtr) ret, attr);
5521 }
5522 }
5523 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5524 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5525 &repName, (xmlSchemaTypePtr) ret, attr);
5526 }
5527 attr = attr->next;
5528 }
5529 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
5530 node, "type", &ret->typeNs, NULL, &ret->typeName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005531 }
5532 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5533 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00005534 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005535 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00005536 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005537 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
5538 if (ret->defValue != NULL)
5539 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
5540 /*
5541 * Attribute "default".
5542 */
5543 attr = xmlSchemaGetPropNode(node, "default");
5544 if (attr != NULL) {
5545 /*
5546 * 3.2.3 : 1
5547 * default and fixed must not both be present.
5548 */
5549 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
5550 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
5551 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
5552 } else
5553 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5554 }
5555 if (topLevel == 0) {
5556 /*
5557 * Attribute "use".
5558 */
5559 attr = xmlSchemaGetPropNode(node, "use");
5560 if (attr != NULL) {
5561 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5562 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
5563 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5564 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
5565 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
5566 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
5567 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
5568 else
5569 xmlSchemaPSimpleTypeErr(ctxt,
5570 XML_SCHEMAP_INVALID_ATTR_USE,
5571 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005572 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005573 attrValue, NULL, NULL, NULL);
5574 } else
5575 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5576 /*
5577 * 3.2.3 : 2
5578 * If default and use are both present, use must have
5579 * the actual value optional.
5580 */
5581 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
5582 (ret->defValue != NULL) &&
5583 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
5584 xmlSchemaPSimpleTypeErr(ctxt,
5585 XML_SCHEMAP_SRC_ATTRIBUTE_2,
5586 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005587 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005588 "The value must be 'optional' if the attribute "
5589 "'default' is present as well", NULL, NULL);
5590 }
5591 }
5592 /*
5593 * And now for the children...
5594 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005595 child = node->children;
5596 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005597 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5598 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005599 }
5600 if (isRef) {
5601 if (child != NULL) {
5602 if (IS_SCHEMA(child, "simpleType"))
5603 /*
5604 * 3.2.3 : 3.2
5605 * If ref is present, then all of <simpleType>,
5606 * form and type must be absent.
5607 */
5608 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
5609 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5610 "(annotation?)");
5611 else
5612 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5613 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5614 "(annotation?)");
5615 }
5616 } else {
5617 if (IS_SCHEMA(child, "simpleType")) {
5618 if (ret->typeName != NULL) {
5619 /*
5620 * 3.2.3 : 4
5621 * type and <simpleType> must not both be present.
5622 */
5623 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
5624 &repName, (xmlSchemaTypePtr) ret, node, child,
5625 "The attribute 'type' and the <simpleType> child "
5626 "are mutually exclusive", NULL);
5627 } else
5628 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5629 child = child->next;
5630 }
5631 if (child != NULL)
5632 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5633 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5634 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005635 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005636 /*
5637 * Cleanup.
5638 */
5639 if (repName != NULL)
5640 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005641 return (ret);
5642}
5643
5644/**
5645 * xmlSchemaParseAttributeGroup:
5646 * @ctxt: a schema validation context
5647 * @schema: the schema being built
5648 * @node: a subtree containing XML Schema informations
5649 *
5650 * parse a XML schema Attribute Group declaration
5651 * *WARNING* this interface is highly subject to change
5652 *
5653 * Returns the attribute group or NULL in case of error.
5654 */
5655static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005656xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005657 xmlSchemaPtr schema, xmlNodePtr node,
5658 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005659{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005660 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005661 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005662 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005663 const xmlChar *oldcontainer;
5664 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005665
5666 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5667 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005668
5669 nameAttr = xmlSchemaGetPropNode(node, "name");
5670 attr = xmlSchemaGetPropNode(node, "ref");
5671 if ((topLevel) || (attr == NULL)) {
5672 /*
5673 * Parse as an attribute group definition.
5674 * Note that those are allowed at top level only.
5675 */
5676 if (nameAttr == NULL) {
5677 xmlSchemaPMissingAttrErr(ctxt,
5678 XML_SCHEMAP_S4S_ATTR_MISSING,
5679 NULL, NULL, node, "name", NULL);
5680 return (NULL);
5681 }
5682 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5683 /*
5684 * The name is crucial, exit if invalid.
5685 */
5686 if (xmlSchemaPValAttrNode(ctxt,
5687 NULL, NULL, nameAttr,
5688 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5689 return (NULL);
5690 }
5691 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5692 if (ret == NULL)
5693 return (NULL);
5694 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5695 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5696 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005697 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005698 } else {
5699 char buf[50];
5700 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5701
5702 /*
5703 * Parse as an attribute group definition reference.
5704 */
5705 if (attr == NULL) {
5706 xmlSchemaPMissingAttrErr(ctxt,
5707 XML_SCHEMAP_S4S_ATTR_MISSING,
5708 NULL, NULL, node, "ref", NULL);
5709 }
5710 xmlSchemaPValAttrNodeQName(ctxt, schema,
5711 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5712
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005713 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005714 name = (const xmlChar *) buf;
5715 if (name == NULL) {
5716 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5717 "attribute group definition reference", node);
5718 return (NULL);
5719 }
5720 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5721 if (ret == NULL)
5722 return (NULL);
5723 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5724 ret->ref = ref;
5725 ret->refNs = refNs;
5726 /* TODO: Is @refPrefix currently used? */
5727 ret->refPrefix = refPrefix;
5728 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005729 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005730 /*
5731 * Check for illegal attributes.
5732 */
5733 attr = node->properties;
5734 while (attr != NULL) {
5735 if (attr->ns == NULL) {
5736 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5737 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5738 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5739 {
5740 xmlSchemaPIllegalAttrErr(ctxt,
5741 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5742 NULL, NULL, attr);
5743 }
5744 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5745 xmlSchemaPIllegalAttrErr(ctxt,
5746 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5747 NULL, NULL, attr);
5748 }
5749 attr = attr->next;
5750 }
5751 /* TODO: Validate "id" ? */
5752 /*
5753 * And now for the children...
5754 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005755 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005756 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005757 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005758 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005759 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5760 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005761 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005762 if (topLevel) {
5763 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5764 if (IS_SCHEMA(child, "anyAttribute")) {
5765 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5766 child = child->next;
5767 }
5768 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005769 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005770 xmlSchemaPContentErr(ctxt,
5771 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5772 NULL, NULL, node, child, NULL,
5773 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005774 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005775 ctxt->container = oldcontainer;
5776 return (ret);
5777}
5778
5779/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005780 * xmlSchemaPValAttrFormDefault:
5781 * @value: the value
5782 * @flags: the flags to be modified
5783 * @flagQualified: the specific flag for "qualified"
5784 *
5785 * Returns 0 if the value is valid, 1 otherwise.
5786 */
5787static int
5788xmlSchemaPValAttrFormDefault(const xmlChar *value,
5789 int *flags,
5790 int flagQualified)
5791{
5792 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5793 if ((*flags & flagQualified) == 0)
5794 *flags |= flagQualified;
5795 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5796 return (1);
5797
5798 return (0);
5799}
5800
5801/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005802 * xmlSchemaPValAttrBlockFinal:
5803 * @value: the value
5804 * @flags: the flags to be modified
5805 * @flagAll: the specific flag for "#all"
5806 * @flagExtension: the specific flag for "extension"
5807 * @flagRestriction: the specific flag for "restriction"
5808 * @flagSubstitution: the specific flag for "substitution"
5809 * @flagList: the specific flag for "list"
5810 * @flagUnion: the specific flag for "union"
5811 *
5812 * Validates the value of the attribute "final" and "block". The value
5813 * is converted into the specified flag values and returned in @flags.
5814 *
5815 * Returns 0 if the value is valid, 1 otherwise.
5816 */
5817
5818static int
5819xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5820 int *flags,
5821 int flagAll,
5822 int flagExtension,
5823 int flagRestriction,
5824 int flagSubstitution,
5825 int flagList,
5826 int flagUnion)
5827{
5828 int ret = 0;
5829
5830 /*
5831 * TODO: This does not check for dublicate entries.
5832 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005833 if (value == NULL)
5834 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005835 if (xmlStrEqual(value, BAD_CAST "#all")) {
5836 if (flagAll != -1)
5837 *flags |= flagAll;
5838 else {
5839 if (flagExtension != -1)
5840 *flags |= flagExtension;
5841 if (flagRestriction != -1)
5842 *flags |= flagRestriction;
5843 if (flagSubstitution != -1)
5844 *flags |= flagSubstitution;
5845 if (flagList != -1)
5846 *flags |= flagList;
5847 if (flagUnion != -1)
5848 *flags |= flagUnion;
5849 }
5850 } else {
5851 const xmlChar *end, *cur = value;
5852 xmlChar *item;
5853
5854 do {
5855 while (IS_BLANK_CH(*cur))
5856 cur++;
5857 end = cur;
5858 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5859 end++;
5860 if (end == cur)
5861 break;
5862 item = xmlStrndup(cur, end - cur);
5863 if (xmlStrEqual(item, BAD_CAST "extension")) {
5864 if (flagExtension != -1) {
5865 if ((*flags & flagExtension) == 0)
5866 *flags |= flagExtension;
5867 } else
5868 ret = 1;
5869 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5870 if (flagRestriction != -1) {
5871 if ((*flags & flagRestriction) == 0)
5872 *flags |= flagRestriction;
5873 } else
5874 ret = 1;
5875 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5876 if (flagSubstitution != -1) {
5877 if ((*flags & flagSubstitution) == 0)
5878 *flags |= flagSubstitution;
5879 } else
5880 ret = 1;
5881 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5882 if (flagList != -1) {
5883 if ((*flags & flagList) == 0)
5884 *flags |= flagList;
5885 } else
5886 ret = 1;
5887 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5888 if (flagUnion != -1) {
5889 if ((*flags & flagUnion) == 0)
5890 *flags |= flagUnion;
5891 } else
5892 ret = 1;
5893 } else
5894 ret = 1;
5895 if (item != NULL)
5896 xmlFree(item);
5897 cur = end;
5898 } while ((ret == 0) && (*cur != 0));
5899 }
5900
5901 return (ret);
5902}
5903
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005904#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005905static int
5906xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005907 xmlSchemaIDCPtr idc,
5908 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005909 xmlAttrPtr attr,
5910 int isField)
5911{
5912 xmlNodePtr node;
5913
5914 /*
5915 * c-selector-xpath:
5916 * Schema Component Constraint: Selector Value OK
5917 *
5918 * TODO: 1 The {selector} must be a valid XPath expression, as defined
5919 * in [XPath].
5920 */
5921 if (selector == NULL) {
5922 xmlSchemaPErr(ctxt, idc->node,
5923 XML_SCHEMAP_INTERNAL,
5924 "Internal error: xmlSchemaCheckCSelectorXPath, "
5925 "the selector is not specified.\n", NULL, NULL);
5926 return (-1);
5927 }
5928 if (attr == NULL)
5929 node = idc->node;
5930 else
5931 node = (xmlNodePtr) attr;
5932 if (selector->xpath == NULL) {
5933 xmlSchemaPCustomErr(ctxt,
5934 /* TODO: Adjust error code. */
5935 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5936 NULL, NULL, node,
5937 "The XPath expression of the selector is not valid", NULL);
5938 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
5939 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00005940 const xmlChar **nsArray = NULL;
5941 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005942 /*
5943 * Compile the XPath expression.
5944 */
5945 /*
5946 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00005947 * TODO: Call xmlPatterncompile with different options for selector/
5948 * field.
5949 */
5950 nsList = xmlGetNsList(attr->doc, attr->parent);
5951 /*
5952 * Build an array of prefixes and namespaces.
5953 */
5954 if (nsList != NULL) {
5955 int i, count = 0;
5956 xmlNsPtr ns;
5957
5958 for (i = 0; nsList[i] != NULL; i++)
5959 count++;
5960
5961 nsArray = (const xmlChar **) xmlMalloc(
5962 (count * 2 + 1) * sizeof(const xmlChar *));
5963 if (nsArray == NULL) {
5964 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
5965 NULL);
5966 return (-1);
5967 }
5968 for (i = 0; i < count; i++) {
5969 ns = nsList[i];
5970 nsArray[2 * i] = nsList[i]->href;
5971 nsArray[2 * i + 1] = nsList[i]->prefix;
5972 }
5973 nsArray[count * 2] = NULL;
5974 xmlFree(nsList);
5975 }
5976 if (isField)
5977 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
5978 NULL, 0, nsArray);
5979 else
5980 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
5981 NULL, 0, nsArray);
5982 if (nsArray != NULL)
5983 xmlFree((xmlChar **) nsArray);
5984
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005985#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00005986 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005987 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005988 /* TODO: Adjust error code? */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005989 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5990 NULL, NULL, node,
5991 "The XPath expression '%s' could not be "
5992 "compiled", selector->xpath);
5993 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
5994 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00005995#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005996 }
5997 return (0);
5998}
5999
6000/**
6001 * xmlSchemaAssignAnnotation:
6002 * @item: the schema component
6003 * @annot: the annotation
6004 *
6005 * Adds the annotation to the given schema component.
6006 *
6007 * Returns the given annotaion.
6008 */
6009static xmlSchemaAnnotPtr
6010xmlSchemaAssignAnnotation(xmlSchemaBasicItemPtr item,
6011 xmlSchemaAnnotPtr annot)
6012{
6013 xmlSchemaAnnotPtr cur = item->annot;
6014
6015 if (item->annot == NULL) {
6016 item->annot = annot;
6017 return (annot);
6018 }
6019 cur = item->annot;
6020 if (cur->next != NULL) {
6021 cur = cur->next;
6022 }
6023 cur->next = annot;
6024 return (annot);
6025}
6026
6027/**
6028 * xmlSchemaParseIDCSelectorAndField:
6029 * @ctxt: a schema validation context
6030 * @schema: the schema being built
6031 * @node: a subtree containing XML Schema informations
6032 *
6033 * Parses a XML Schema identity-contraint definition's
6034 * <selector> and <field> elements.
6035 *
6036 * Returns the parsed identity-constraint definition.
6037 */
6038static xmlSchemaIDCSelectPtr
6039xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
6040 xmlSchemaPtr schema,
6041 xmlSchemaIDCPtr idc,
6042 xmlNodePtr node,
6043 int isField)
6044{
6045 xmlSchemaIDCSelectPtr item;
6046 xmlNodePtr child = NULL;
6047 xmlAttrPtr attr;
6048
6049 /*
6050 * Check for illegal attributes.
6051 */
6052 attr = node->properties;
6053 while (attr != NULL) {
6054 if (attr->ns == NULL) {
6055 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6056 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
6057 xmlSchemaPIllegalAttrErr(ctxt,
6058 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6059 NULL, NULL, attr);
6060 }
6061 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6062 xmlSchemaPIllegalAttrErr(ctxt,
6063 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6064 NULL, NULL, attr);
6065 }
6066 attr = attr->next;
6067 }
6068 /*
6069 * Create the item.
6070 */
6071 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
6072 if (item == NULL) {
6073 xmlSchemaPErrMemory(ctxt,
6074 "allocating a 'selector' of an identity-constraint definition",
6075 NULL);
6076 return (NULL);
6077 }
6078 memset(item, 0, sizeof(xmlSchemaIDCSelect));
6079 /*
6080 * Attribute "xpath" (mandatory).
6081 */
6082 attr = xmlSchemaGetPropNode(node, "xpath");
6083 if (attr == NULL) {
6084 xmlSchemaPMissingAttrErr(ctxt,
6085 XML_SCHEMAP_S4S_ATTR_MISSING,
6086 NULL, NULL, node,
6087 "name", NULL);
6088 } else {
6089 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6090 /*
6091 * URGENT TODO: "field"s have an other syntax than "selector"s.
6092 */
6093
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006094 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
6095 isField) == -1) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006096 xmlSchemaPErr(ctxt,
6097 (xmlNodePtr) attr,
6098 XML_SCHEMAP_INTERNAL,
6099 "Internal error: xmlSchemaParseIDCSelectorAndField, "
6100 "validating the XPath expression of a IDC selector.\n",
6101 NULL, NULL);
6102 }
6103
6104 }
6105 /*
6106 * And now for the children...
6107 */
6108 child = node->children;
6109 if (IS_SCHEMA(child, "annotation")) {
6110 /*
6111 * Add the annotation to the parent IDC.
6112 */
6113 xmlSchemaAssignAnnotation((xmlSchemaBasicItemPtr) idc,
6114 xmlSchemaParseAnnotation(ctxt, schema, child));
6115 child = child->next;
6116 }
6117 if (child != NULL) {
6118 xmlSchemaPContentErr(ctxt,
6119 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6120 NULL, NULL, node, child,
6121 NULL, "(annotation?)");
6122 }
6123
6124 return (item);
6125}
6126
6127/**
6128 * xmlSchemaParseIDC:
6129 * @ctxt: a schema validation context
6130 * @schema: the schema being built
6131 * @node: a subtree containing XML Schema informations
6132 *
6133 * Parses a XML Schema identity-contraint definition.
6134 *
6135 * Returns the parsed identity-constraint definition.
6136 */
6137static xmlSchemaIDCPtr
6138xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
6139 xmlSchemaPtr schema,
6140 xmlNodePtr node,
6141 xmlSchemaTypeType idcCategory,
6142 const xmlChar *targetNamespace)
6143{
6144 xmlSchemaIDCPtr item = NULL;
6145 xmlNodePtr child = NULL;
6146 xmlAttrPtr attr;
6147 const xmlChar *name = NULL;
6148 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
6149 int resAdd;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006150
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006151 /*
6152 * Check for illegal attributes.
6153 */
6154 attr = node->properties;
6155 while (attr != NULL) {
6156 if (attr->ns == NULL) {
6157 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6158 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6159 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
6160 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
6161 xmlSchemaPIllegalAttrErr(ctxt,
6162 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6163 NULL, NULL, attr);
6164 }
6165 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6166 xmlSchemaPIllegalAttrErr(ctxt,
6167 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6168 NULL, NULL, attr);
6169 }
6170 attr = attr->next;
6171 }
6172 /*
6173 * Attribute "name" (mandatory).
6174 */
6175 attr = xmlSchemaGetPropNode(node, "name");
6176 if (attr == NULL) {
6177 xmlSchemaPMissingAttrErr(ctxt,
6178 XML_SCHEMAP_S4S_ATTR_MISSING,
6179 NULL, NULL, node,
6180 "name", NULL);
6181 return (NULL);
6182 } else if (xmlSchemaPValAttrNode(ctxt,
6183 NULL, NULL, attr,
6184 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6185 return (NULL);
6186 }
6187 /*
6188 * Create the component.
6189 */
6190 if (schema->idcDef == NULL)
6191 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
6192 if (schema->idcDef == NULL)
6193 return (NULL);
6194
6195 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
6196 if (item == NULL) {
6197 xmlSchemaPErrMemory(ctxt,
6198 "allocating an identity-constraint definition", NULL);
6199 return (NULL);
6200 }
6201 /*
6202 * Add the IDC to the list of IDCs on the schema component.
6203 */
6204 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
6205 if (resAdd != 0) {
6206 xmlSchemaPCustomErrExt(ctxt,
6207 XML_SCHEMAP_REDEFINED_TYPE,
6208 NULL, NULL, node,
6209 "An identity-constraint definition with the name '%s' "
6210 "and targetNamespace '%s' does already exist",
6211 name, targetNamespace, NULL);
6212 xmlFree(item);
6213 return (NULL);
6214 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006215 memset(item, 0, sizeof(xmlSchemaIDC));
6216 item->name = name;
6217 item->type = idcCategory;
6218 item->node = node;
6219 /*
6220 * The target namespace of the parent element declaration.
6221 */
6222 item->targetNamespace = targetNamespace;
6223 /* TODO: Handle attribute "id". */
6224 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
6225 /*
6226 * Attribute "refer" (mandatory).
6227 */
6228 attr = xmlSchemaGetPropNode(node, "refer");
6229 if (attr == NULL) {
6230 xmlSchemaPMissingAttrErr(ctxt,
6231 XML_SCHEMAP_S4S_ATTR_MISSING,
6232 NULL, NULL, node,
6233 "refer", NULL);
6234 } else {
6235 /*
6236 * Create a reference item.
6237 */
6238 item->ref = (xmlSchemaItemQNRefPtr) xmlMalloc(
6239 sizeof(xmlSchemaItemQNRef));
6240 if (item->ref == NULL) {
6241 xmlSchemaPErrMemory(ctxt,
6242 "allocating a QName reference item", NULL);
6243 return (NULL);
6244 }
6245 memset(item->ref, 0, sizeof(xmlSchemaItemQNRef));
6246 xmlSchemaPValAttrNodeQName(ctxt, schema,
6247 NULL, NULL, attr,
6248 &(item->ref->targetNamespace), 0,
6249 &(item->ref->name));
6250 }
6251 }
6252 /*
6253 * And now for the children...
6254 */
6255 child = node->children;
6256 if (IS_SCHEMA(child, "annotation")) {
6257 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6258 child = child->next;
6259 }
6260 /*
6261 * Child element <selector>.
6262 */
6263 if (IS_SCHEMA(child, "selector")) {
6264 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6265 item, child, 0);
6266 child = child->next;
6267 /*
6268 * Child elements <field>.
6269 */
6270 if (IS_SCHEMA(child, "field")) {
6271 do {
6272 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6273 item, child, 1);
6274 if (field != NULL) {
6275 field->index = item->nbFields;
6276 item->nbFields++;
6277 if (lastField != NULL)
6278 lastField->next = field;
6279 else
6280 item->fields = field;
6281 lastField = field;
6282 }
6283 child = child->next;
6284 } while (IS_SCHEMA(child, "field"));
6285 } else {
6286 xmlSchemaPContentErr(ctxt,
6287 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6288 NULL, NULL, node, child,
6289 NULL, "(annotation?, (selector, field+))");
6290 }
6291 }
6292 if (child != NULL) {
6293 xmlSchemaPContentErr(ctxt,
6294 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6295 NULL, NULL, node, child,
6296 NULL, "(annotation?, (selector, field+))");
6297 }
6298
6299 return (item);
6300}
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006301#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006302
Daniel Veillardc0826a72004-08-10 14:17:33 +00006303/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006304 * xmlSchemaParseElement:
6305 * @ctxt: a schema validation context
6306 * @schema: the schema being built
6307 * @node: a subtree containing XML Schema informations
6308 *
6309 * parse a XML schema Element declaration
6310 * *WARNING* this interface is highly subject to change
6311 *
William M. Bracke7091952004-05-11 15:09:58 +00006312 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006313 */
6314static xmlSchemaElementPtr
6315xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006316 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006317{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006318 const xmlChar *name = NULL;
6319 const xmlChar *attrValue;
6320 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006321 xmlSchemaElementPtr ret;
6322 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006323 const xmlChar *oldcontainer;
6324 xmlAttrPtr attr, nameAttr;
6325 int minOccurs, maxOccurs;
6326 int isRef = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006327#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006328 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006329#endif
William M. Bracke7091952004-05-11 15:09:58 +00006330
6331 /* 3.3.3 Constraints on XML Representations of Element Declarations */
6332 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006333
Daniel Veillard4255d502002-04-16 15:50:10 +00006334 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6335 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006336
Daniel Veillardc0826a72004-08-10 14:17:33 +00006337 oldcontainer = ctxt->container;
6338
6339 nameAttr = xmlSchemaGetPropNode(node, "name");
6340 attr = xmlSchemaGetPropNode(node, "ref");
6341 if ((topLevel) || (attr == NULL)) {
6342 if (nameAttr == NULL) {
6343 xmlSchemaPMissingAttrErr(ctxt,
6344 XML_SCHEMAP_S4S_ATTR_MISSING,
6345 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
6346 "name", NULL);
6347 return (NULL);
6348 }
6349 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
6350 } else {
6351 isRef = 1;
6352
6353 }
6354 /*
6355 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
6356 * to no component at all
6357 * TODO: It might be better to validate the element, even if it won't be
6358 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006359 */
6360 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6361 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006362 if ((minOccurs == 0) && (maxOccurs == 0))
6363 return (NULL);
6364 /*
6365 * If we get a "ref" attribute on a local <element> we will assume it's
6366 * a reference - even if there's a "name" attribute; this seems to be more
6367 * robust.
6368 */
6369 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006370 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006371 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6372
6373 /*
6374 * Parse as a particle.
6375 */
6376 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006377 (xmlChar **) &xmlSchemaElemDesElemRef,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006378 NULL, attr, &refNs, &refPrefix, &ref);
6379
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006380 snprintf(buf, 49, "#eRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006381 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006382 if (ret == NULL) {
6383 if (repName != NULL)
6384 xmlFree(repName);
6385 return (NULL);
6386 }
6387 ret->type = XML_SCHEMA_TYPE_ELEMENT;
6388 ret->node = node;
6389 ret->ref = ref;
6390 ret->refNs = refNs;
6391 ret->refPrefix = refPrefix;
6392 ret->flags |= XML_SCHEMAS_ELEM_REF;
6393 /*
6394 * Check for illegal attributes.
6395 */
6396 /*
6397 * 3.3.3 : 2.1
6398 * One of ref or name must be present, but not both
6399 */
6400 if (nameAttr != NULL) {
6401 xmlSchemaPMutualExclAttrErr(ctxt,
6402 XML_SCHEMAP_SRC_ELEMENT_2_1,
6403 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6404 "ref", "name");
6405 }
6406 /* 3.3.3 : 2.2 */
6407 attr = node->properties;
6408 while (attr != NULL) {
6409 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006410 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
6411 xmlStrEqual(attr->name, BAD_CAST "name") ||
6412 xmlStrEqual(attr->name, BAD_CAST "id") ||
6413 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
6414 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
6415 {
6416 attr = attr->next;
6417 continue;
6418 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006419 xmlSchemaPCustomAttrErr(ctxt,
6420 XML_SCHEMAP_SRC_ELEMENT_2_2,
6421 &repName, (xmlSchemaTypePtr) ret, attr,
6422 "Only the attributes 'minOccurs', 'maxOccurs' and "
6423 "'id' are allowed in addition to 'ref'");
6424 break;
6425 }
6426 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6427 xmlSchemaPIllegalAttrErr(ctxt,
6428 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6429 &repName, (xmlSchemaTypePtr) ret, attr);
6430 }
6431 attr = attr->next;
6432 }
6433 } else {
6434 const xmlChar *ns = NULL, *fixed;
6435
6436 /*
6437 * Parse as an element declaration.
6438 */
6439 if (xmlSchemaPValAttrNode(ctxt,
6440 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
6441 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
6442 return (NULL);
6443 /*
6444 * Evaluate the target namespace.
6445 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006446 if (topLevel) {
6447 ns = schema->targetNamespace;
6448 } else {
6449 attr = xmlSchemaGetPropNode(node, "form");
6450 if (attr != NULL) {
6451 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6452 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00006453 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006454 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6455 xmlSchemaPSimpleTypeErr(ctxt,
6456 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6457 &repName, NULL, (xmlNodePtr) attr,
6458 NULL, "(qualified | unqualified)",
6459 attrValue, NULL, NULL, NULL);
6460 }
6461 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6462 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00006463 }
6464 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006465 if (ret == NULL) {
6466 if (repName != NULL)
6467 xmlFree(repName);
6468 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006469 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006470 ret->type = XML_SCHEMA_TYPE_ELEMENT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006471 ret->node = node;
6472 ret->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006473 /*
6474 * Check for illegal attributes.
6475 */
William M. Bracke7091952004-05-11 15:09:58 +00006476 attr = node->properties;
6477 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006478 if (attr->ns == NULL) {
6479 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6480 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6481 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6482 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6483 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6484 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006485 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
6486 {
6487 if (topLevel == 0) {
6488 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006489 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006490 (!xmlStrEqual(attr->name, BAD_CAST "form")))
6491 {
6492 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
6493 /*
6494 * 3.3.6 : 3 If there is a non-·absent· {substitution
6495 * group affiliation}, then {scope} must be global.
6496 * TODO: This one is redundant, since the S4S does
6497 * prohibit this attribute on local declarations already;
6498 * so why an explicit error code? Weird spec.
6499 * TODO: Move this to the proper constraint layer.
6500 * TODO: Or better wait for spec 1.1 to come.
6501 */
6502 xmlSchemaPIllegalAttrErr(ctxt,
6503 XML_SCHEMAP_E_PROPS_CORRECT_3,
6504 &repName, (xmlSchemaTypePtr) ret, attr);
6505 } else {
6506 xmlSchemaPIllegalAttrErr(ctxt,
6507 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6508 &repName, (xmlSchemaTypePtr) ret, attr);
6509 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006510 }
6511 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
6512 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
6513 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
6514
6515 xmlSchemaPIllegalAttrErr(ctxt,
6516 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6517 &repName, (xmlSchemaTypePtr) ret, attr);
6518 }
6519 }
6520 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6521
6522 xmlSchemaPIllegalAttrErr(ctxt,
6523 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6524 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00006525 }
6526 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006527 }
William M. Bracke7091952004-05-11 15:09:58 +00006528 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006529 * Extract/validate attributes.
6530 */
6531 if (topLevel) {
6532 /*
6533 * Process top attributes of global element declarations here.
6534 */
6535 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
6536 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
6537 xmlSchemaPValAttrQName(ctxt, schema, &repName,
6538 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
6539 &(ret->substGroupNs), NULL, &(ret->substGroup));
6540 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6541 node, "abstract", 0))
6542 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
6543 /*
6544 * Attribute "final".
6545 */
6546 attr = xmlSchemaGetPropNode(node, "final");
6547 if (attr == NULL) {
6548 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
6549 } else {
6550 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6551 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6552 -1,
6553 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
6554 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
6555 xmlSchemaPSimpleTypeErr(ctxt,
6556 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6557 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006558 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006559 attrValue, NULL, NULL, NULL);
6560 }
6561 }
6562 }
6563 /*
6564 * Attribute "block".
6565 */
6566 attr = xmlSchemaGetPropNode(node, "block");
6567 if (attr == NULL) {
6568 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
6569 } else {
6570 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6571 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6572 -1,
6573 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
6574 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
6575 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
6576 xmlSchemaPSimpleTypeErr(ctxt,
6577 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6578 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006579 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00006580 "restriction | substitution))", attrValue,
6581 NULL, NULL, NULL);
6582 }
6583 }
6584 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6585 node, "nillable", 0))
6586 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006587
Daniel Veillardc0826a72004-08-10 14:17:33 +00006588 xmlSchemaPValAttrQName(ctxt, schema,
6589 &repName, (xmlSchemaTypePtr) ret, node,
6590 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00006591
Daniel Veillardc0826a72004-08-10 14:17:33 +00006592 ret->value = xmlSchemaGetProp(ctxt, node, "default");
6593 attr = xmlSchemaGetPropNode(node, "fixed");
6594 if (attr != NULL) {
6595 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6596 if (ret->value != NULL) {
6597 /*
6598 * 3.3.3 : 1
6599 * default and fixed must not both be present.
6600 */
6601 xmlSchemaPMutualExclAttrErr(ctxt,
6602 XML_SCHEMAP_SRC_ELEMENT_1,
6603 &repName, (xmlSchemaTypePtr) ret, attr,
6604 "default", "fixed");
6605 } else {
6606 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
6607 ret->value = fixed;
6608 }
6609 }
6610 }
6611 /*
6612 * Extract/validate common attributes.
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006613 */
6614 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6615 node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006616 ret->minOccurs = minOccurs;
6617 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006618 if (topLevel != 1)
6619 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
6620 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006621 /*
6622 * And now for the children...
6623 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006624 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006625 child = node->children;
6626 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006627 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6628 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006629 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006630 if (isRef) {
6631 if (child != NULL) {
6632 xmlSchemaPContentErr(ctxt,
6633 XML_SCHEMAP_SRC_ELEMENT_2_2,
6634 &repName, (xmlSchemaTypePtr) ret, node, child,
6635 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00006636 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006637 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006638 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006639 /*
6640 * 3.3.3 : 3
6641 * "type" and either <simpleType> or <complexType> are mutually
6642 * exclusive
6643 */
William M. Bracke7091952004-05-11 15:09:58 +00006644 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006645 xmlSchemaPContentErr(ctxt,
6646 XML_SCHEMAP_SRC_ELEMENT_3,
6647 &repName, (xmlSchemaTypePtr) ret, node, child,
6648 "The attribute 'type' and the <complexType> child are "
6649 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006650 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006651 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006652 child = child->next;
6653 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006654 /*
6655 * 3.3.3 : 3
6656 * "type" and either <simpleType> or <complexType> are
6657 * mutually exclusive
6658 */
William M. Bracke7091952004-05-11 15:09:58 +00006659 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006660 xmlSchemaPContentErr(ctxt,
6661 XML_SCHEMAP_SRC_ELEMENT_3,
6662 &repName, (xmlSchemaTypePtr) ret, node, child,
6663 "The attribute 'type' and the <simpleType> child are "
6664 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006665 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006666 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006667 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006668 }
William M. Bracke7091952004-05-11 15:09:58 +00006669 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006670 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006671#ifdef IDC_ENABLED
6672 if (IS_SCHEMA(child, "unique")) {
6673 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6674 XML_SCHEMA_TYPE_IDC_UNIQUE, ret->targetNamespace);
6675 } else if (IS_SCHEMA(child, "key")) {
6676 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6677 XML_SCHEMA_TYPE_IDC_KEY, ret->targetNamespace);
6678 } else if (IS_SCHEMA(child, "keyref")) {
6679 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6680 XML_SCHEMA_TYPE_IDC_KEYREF, ret->targetNamespace);
6681 }
6682 if (lastIDC != NULL)
6683 lastIDC->next = curIDC;
6684 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006685 ret->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006686 lastIDC = curIDC;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006687#else
6688 TODO
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006689#endif
6690 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00006691 }
6692 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006693 xmlSchemaPContentErr(ctxt,
6694 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6695 &repName, (xmlSchemaTypePtr) ret, node, child,
6696 NULL, "(annotation?, ((simpleType | complexType)?, "
6697 "(unique | key | keyref)*))");
6698 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006699
Daniel Veillardc0826a72004-08-10 14:17:33 +00006700 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006701 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006702 /*
6703 * Cleanup.
6704 */
6705 if (repName != NULL)
6706 xmlFree(repName);
6707 /*
6708 * NOTE: Element Declaration Representation OK 4. will be checked at a
6709 * different layer.
6710 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006711 return (ret);
6712}
6713
6714/**
6715 * xmlSchemaParseUnion:
6716 * @ctxt: a schema validation context
6717 * @schema: the schema being built
6718 * @node: a subtree containing XML Schema informations
6719 *
6720 * parse a XML schema Union definition
6721 * *WARNING* this interface is highly subject to change
6722 *
William M. Bracke7091952004-05-11 15:09:58 +00006723 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006724 * 1 in case of success.
6725 */
6726static xmlSchemaTypePtr
6727xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006728 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006729{
6730 xmlSchemaTypePtr type, subtype, last = NULL;
6731 xmlNodePtr child = NULL;
6732 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006733 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006734
6735 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6736 return (NULL);
6737
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006738 snprintf((char *) name, 30, "#union%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006739 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006740 if (type == NULL)
6741 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006742 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00006743 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00006744 /*
6745 * Check for illegal attributes.
6746 */
6747 attr = node->properties;
6748 while (attr != NULL) {
6749 if (attr->ns == NULL) {
6750 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6751 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
6752 xmlSchemaPIllegalAttrErr(ctxt,
6753 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6754 NULL, type, attr);
6755 }
6756 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6757 xmlSchemaPIllegalAttrErr(ctxt,
6758 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6759 NULL, type, attr);
6760 }
6761 attr = attr->next;
6762 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006763 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006764 /*
6765 * Attribute "memberTypes". This is a list of QNames.
6766 * TODO: Validate the QNames.
6767 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00006768 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00006769 /*
6770 * And now for the children...
6771 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006772 child = node->children;
6773 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006774 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6775 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006776 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006777 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006778 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00006779 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006780 if (subtype != NULL) {
6781 if (last == NULL) {
6782 type->subtypes = subtype;
6783 last = subtype;
6784 } else {
6785 last->next = subtype;
6786 last = subtype;
6787 }
6788 last->next = NULL;
6789 }
6790 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006791 }
6792 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006793 /* TODO: Think about the error code. */
6794 xmlSchemaPContentErr(ctxt,
6795 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
6796 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006797 }
6798 return (type);
6799}
6800
6801/**
6802 * xmlSchemaParseList:
6803 * @ctxt: a schema validation context
6804 * @schema: the schema being built
6805 * @node: a subtree containing XML Schema informations
6806 *
6807 * parse a XML schema List definition
6808 * *WARNING* this interface is highly subject to change
6809 *
William M. Bracke7091952004-05-11 15:09:58 +00006810 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006811 * 1 in case of success.
6812 */
6813static xmlSchemaTypePtr
6814xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006815 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006816{
6817 xmlSchemaTypePtr type, subtype;
6818 xmlNodePtr child = NULL;
6819 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006820 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006821
6822 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6823 return (NULL);
6824
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006825 snprintf((char *) name, 30, "#list%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006826 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006827 if (type == NULL)
6828 return (NULL);
6829 type->node = node;
6830 type->type = XML_SCHEMA_TYPE_LIST;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006831 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006832 /*
6833 * Check for illegal attributes.
6834 */
6835 attr = node->properties;
6836 while (attr != NULL) {
6837 if (attr->ns == NULL) {
6838 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6839 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
6840 xmlSchemaPIllegalAttrErr(ctxt,
6841 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6842 NULL, type, attr);
6843 }
6844 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6845 xmlSchemaPIllegalAttrErr(ctxt,
6846 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6847 NULL, type, attr);
6848 }
6849 attr = attr->next;
6850 }
6851 /*
6852 * Attribute "itemType".
6853 */
6854 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
6855 node, "itemType", &(type->baseNs), NULL, &(type->base));
6856 /*
6857 * And now for the children...
6858 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006859 child = node->children;
6860 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006861 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6862 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00006863 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006864 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006865 if (IS_SCHEMA(child, "simpleType")) {
6866 if (type->base != NULL) {
6867 xmlSchemaPCustomErr(ctxt,
6868 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
6869 NULL, type, node,
6870 "The attribute 'itemType' and the <simpleType> child "
6871 "are mutually exclusive", NULL);
6872 } else {
6873 subtype = (xmlSchemaTypePtr)
6874 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6875 type->subtypes = subtype;
6876 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006877 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006878 }
6879 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006880 /* TODO: Think about the error code. */
6881 xmlSchemaPContentErr(ctxt,
6882 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
6883 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006884 }
6885 return (type);
6886}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006887
Daniel Veillard4255d502002-04-16 15:50:10 +00006888/**
6889 * xmlSchemaParseSimpleType:
6890 * @ctxt: a schema validation context
6891 * @schema: the schema being built
6892 * @node: a subtree containing XML Schema informations
6893 *
6894 * parse a XML schema Simple Type definition
6895 * *WARNING* this interface is highly subject to change
6896 *
William M. Bracke7091952004-05-11 15:09:58 +00006897 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00006898 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00006899 */
6900static xmlSchemaTypePtr
6901xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006902 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006903{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006904 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00006905 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006906 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006907 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006908 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006909
6910 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6911 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006912
Daniel Veillardc0826a72004-08-10 14:17:33 +00006913 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006914 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006915 if (attr == NULL) {
6916 xmlSchemaPMissingAttrErr(ctxt,
6917 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006918 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006919 "name", NULL);
6920 return (NULL);
6921 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006922 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006923 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00006924 return (NULL);
6925 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006926 }
6927
6928 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006929 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006930
Daniel Veillard01fa6152004-06-29 17:04:39 +00006931 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006932 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00006933 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006934 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006935 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006936 if (type == NULL)
6937 return (NULL);
6938 type->node = node;
6939 type->type = XML_SCHEMA_TYPE_SIMPLE;
6940 /*
6941 * Check for illegal attributes.
6942 */
6943 attr = node->properties;
6944 while (attr != NULL) {
6945 if (attr->ns == NULL) {
6946 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
6947 xmlSchemaPIllegalAttrErr(ctxt,
6948 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006949 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00006950 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006951 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6952 xmlSchemaPIllegalAttrErr(ctxt,
6953 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006954 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006955 }
6956 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006957 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006958 } else {
6959 /*
6960 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006961 *
6962 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006963 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006964 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006965 if (type == NULL)
6966 return (NULL);
6967 type->node = node;
6968 type->type = XML_SCHEMA_TYPE_SIMPLE;
6969 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
6970 /*
6971 * Check for illegal attributes.
6972 */
6973 attr = node->properties;
6974 while (attr != NULL) {
6975 if (attr->ns == NULL) {
6976 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6977 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006978 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006979 xmlSchemaPIllegalAttrErr(ctxt,
6980 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006981 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006982 }
6983 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6984 xmlSchemaPIllegalAttrErr(ctxt,
6985 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006986 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006987 }
6988 attr = attr->next;
6989 }
6990 /*
6991 * Attribute "final".
6992 */
6993 attr = xmlSchemaGetPropNode(node, "final");
6994 if (attr == NULL) {
6995 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
6996 } else {
6997 attrValue = xmlSchemaGetProp(ctxt, node, "final");
6998 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
6999 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
7000 XML_SCHEMAS_TYPE_FINAL_LIST,
7001 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
7002
7003 xmlSchemaPSimpleTypeErr(ctxt,
7004 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007005 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007006 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007007 attrValue, NULL, NULL, NULL);
7008 }
7009 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007010 }
7011 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007012 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007013 /*
7014 * And now for the children...
7015 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007016 oldCtxtType = ctxt->ctxtType;
7017 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007018 ctxt->ctxtType = type;
7019 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007020 child = node->children;
7021 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007022 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7023 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007024 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007025 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007026 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007027 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007028 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007029 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007030 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007031 subtype = (xmlSchemaTypePtr)
7032 xmlSchemaParseList(ctxt, schema, child);
7033 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007034 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007035 subtype = (xmlSchemaTypePtr)
7036 xmlSchemaParseUnion(ctxt, schema, child);
7037 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007038 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007039 type->subtypes = subtype;
7040 if ((child != NULL) || (subtype == NULL)) {
7041 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007042 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007043 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007044 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007045 ctxt->parentItem = oldParentItem;
7046 ctxt->ctxtType = oldCtxtType;
7047 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00007048
Daniel Veillard4255d502002-04-16 15:50:10 +00007049 return (type);
7050}
7051
7052
7053/**
7054 * xmlSchemaParseGroup:
7055 * @ctxt: a schema validation context
7056 * @schema: the schema being built
7057 * @node: a subtree containing XML Schema informations
7058 *
7059 * parse a XML schema Group definition
7060 * *WARNING* this interface is highly subject to change
7061 *
William M. Bracke7091952004-05-11 15:09:58 +00007062 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007063 * 1 in case of success.
7064 */
7065static xmlSchemaTypePtr
7066xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007067 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007068{
7069 xmlSchemaTypePtr type, subtype;
7070 xmlNodePtr child = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007071 const xmlChar *name, *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007072 const xmlChar *ref = NULL, *refNs = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007073 char buf[50];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00007074 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00007075
7076 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7077 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00007078 /*
7079 * TODO: Validate the element even if no item is created
7080 * (i.e. min/maxOccurs == 0).
7081 */
7082 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7083 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
7084 if ((minOccurs == 0) && (maxOccurs == 0)) {
7085 return (NULL);
7086 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007087 if (topLevel)
7088 ns = schema->targetNamespace;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007089 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00007090 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007091 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
7092 if (ref == NULL) {
7093 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007094 XML_SCHEMAP_GROUP_NONAME_NOREF,
7095 "Group definition or particle: One of the attributes \"name\" "
7096 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007097 return (NULL);
7098 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007099 if (refNs == NULL)
7100 refNs = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007101 snprintf(buf, 49, "#grRef%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007102 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00007103 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007104 type = xmlSchemaAddGroup(ctxt, schema, name, ns, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007105 if (type == NULL)
7106 return (NULL);
7107 type->node = node;
7108 type->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007109 if (topLevel)
7110 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007111 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007112 type->ref = ref;
7113 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00007114 type->minOccurs = minOccurs;
7115 type->maxOccurs = maxOccurs;
7116 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007117 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00007118
7119 child = node->children;
7120 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007121 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7122 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007123 }
7124 subtype = NULL;
7125 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007126 subtype = (xmlSchemaTypePtr)
7127 xmlSchemaParseAll(ctxt, schema, child);
7128 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007129 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007130 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7131 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007132 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007133 subtype = (xmlSchemaTypePtr)
7134 xmlSchemaParseSequence(ctxt, schema, child);
7135 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007136 }
7137 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007138 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007139 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007140 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007141 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007142 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007143 }
7144
7145 return (type);
7146}
7147
7148/**
7149 * xmlSchemaParseAll:
7150 * @ctxt: a schema validation context
7151 * @schema: the schema being built
7152 * @node: a subtree containing XML Schema informations
7153 *
7154 * parse a XML schema All definition
7155 * *WARNING* this interface is highly subject to change
7156 *
William M. Bracke7091952004-05-11 15:09:58 +00007157 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007158 * 1 in case of success.
7159 */
7160static xmlSchemaTypePtr
7161xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007162 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007163{
7164 xmlSchemaTypePtr type, subtype, last = NULL;
7165 xmlNodePtr child = NULL;
7166 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007167 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007168
7169 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7170 return (NULL);
7171
7172
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007173 snprintf((char *) name, 30, "#all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007174 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007175 if (type == NULL)
7176 return (NULL);
7177 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00007178 type->type = XML_SCHEMA_TYPE_ALL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007179
7180 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007181
7182 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
7183 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007184
7185 oldcontainer = ctxt->container;
7186 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007187 child = node->children;
7188 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007189 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7190 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007191 }
7192 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007193 subtype = (xmlSchemaTypePtr)
7194 xmlSchemaParseElement(ctxt, schema, child, 0);
7195 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00007196 if (subtype->minOccurs > 1)
7197 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007198 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007199 NULL, NULL);
7200 if (subtype->maxOccurs > 1)
7201 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007202 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007203 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007204 if (last == NULL) {
7205 type->subtypes = subtype;
7206 last = subtype;
7207 } else {
7208 last->next = subtype;
7209 last = subtype;
7210 }
7211 last->next = NULL;
7212 }
7213 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007214 }
7215 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007216 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007217 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007218 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007219 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007220 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007221 return (type);
7222}
7223
7224/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007225 * xmlSchemaCleanupDoc:
7226 * @ctxt: a schema validation context
7227 * @node: the root of the document.
7228 *
7229 * removes unwanted nodes in a schemas document tree
7230 */
7231static void
7232xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
7233{
7234 xmlNodePtr delete, cur;
7235
7236 if ((ctxt == NULL) || (root == NULL)) return;
7237
7238 /*
7239 * Remove all the blank text nodes
7240 */
7241 delete = NULL;
7242 cur = root;
7243 while (cur != NULL) {
7244 if (delete != NULL) {
7245 xmlUnlinkNode(delete);
7246 xmlFreeNode(delete);
7247 delete = NULL;
7248 }
7249 if (cur->type == XML_TEXT_NODE) {
7250 if (IS_BLANK_NODE(cur)) {
7251 if (xmlNodeGetSpacePreserve(cur) != 1) {
7252 delete = cur;
7253 }
7254 }
7255 } else if ((cur->type != XML_ELEMENT_NODE) &&
7256 (cur->type != XML_CDATA_SECTION_NODE)) {
7257 delete = cur;
7258 goto skip_children;
7259 }
7260
7261 /*
7262 * Skip to next node
7263 */
7264 if (cur->children != NULL) {
7265 if ((cur->children->type != XML_ENTITY_DECL) &&
7266 (cur->children->type != XML_ENTITY_REF_NODE) &&
7267 (cur->children->type != XML_ENTITY_NODE)) {
7268 cur = cur->children;
7269 continue;
7270 }
7271 }
7272 skip_children:
7273 if (cur->next != NULL) {
7274 cur = cur->next;
7275 continue;
7276 }
7277
7278 do {
7279 cur = cur->parent;
7280 if (cur == NULL)
7281 break;
7282 if (cur == root) {
7283 cur = NULL;
7284 break;
7285 }
7286 if (cur->next != NULL) {
7287 cur = cur->next;
7288 break;
7289 }
7290 } while (cur != NULL);
7291 }
7292 if (delete != NULL) {
7293 xmlUnlinkNode(delete);
7294 xmlFreeNode(delete);
7295 delete = NULL;
7296 }
7297}
7298
William M. Brack2f2a6632004-08-20 23:09:47 +00007299
7300/**
7301 * xmlSchemaImportSchema
7302 *
7303 * @ctxt: a schema validation context
7304 * @schemaLocation: an URI defining where to find the imported schema
7305 *
7306 * import a XML schema
7307 * *WARNING* this interface is highly subject to change
7308 *
7309 * Returns -1 in case of error and 1 in case of success.
7310 */
7311#if 0
7312static xmlSchemaImportPtr
7313xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
7314 const xmlChar *schemaLocation)
7315{
7316 xmlSchemaImportPtr import;
7317 xmlSchemaParserCtxtPtr newctxt;
7318
7319 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7320 if (newctxt == NULL) {
7321 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
7322 NULL);
7323 return (NULL);
7324 }
7325 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
7326 /* Keep the same dictionnary for parsing, really */
7327 xmlDictReference(ctxt->dict);
7328 newctxt->dict = ctxt->dict;
7329 newctxt->includes = 0;
7330 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
7331
7332 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
7333 ctxt->userData);
7334
7335 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7336 if (import == NULL) {
7337 xmlSchemaPErrMemory(NULL, "allocating imported schema",
7338 NULL);
7339 xmlSchemaFreeParserCtxt(newctxt);
7340 return (NULL);
7341 }
7342
7343 memset(import, 0, sizeof(xmlSchemaImport));
7344 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7345 import->schema = xmlSchemaParse(newctxt);
7346
7347 if (import->schema == NULL) {
7348 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00007349 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00007350 "Failed to import schema from location \"%s\".\n",
7351 schemaLocation, NULL);
7352
7353 xmlSchemaFreeParserCtxt(newctxt);
7354 /* The schemaLocation is held by the dictionary.
7355 if (import->schemaLocation != NULL)
7356 xmlFree((xmlChar *)import->schemaLocation);
7357 */
7358 xmlFree(import);
7359 return NULL;
7360 }
7361
7362 xmlSchemaFreeParserCtxt(newctxt);
7363 return import;
7364}
7365#endif
7366
7367static void
7368xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
7369{
7370 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7371 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
7372
7373 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
7374 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
7375
7376 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7377 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
7378 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7379 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
7380 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
7381 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
7382 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
7383 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
7384
7385 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7386 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
7387 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7388 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
7389 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7390 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
7391}
7392
7393static void
7394xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
7395 xmlSchemaPtr schema,
7396 xmlNodePtr node)
7397{
7398 xmlAttrPtr attr;
7399 const xmlChar *val;
7400
7401 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
7402 if (attr != NULL) {
7403 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7404 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7405 XML_SCHEMAS_QUALIF_ELEM) != 0) {
7406 xmlSchemaPSimpleTypeErr(ctxt,
7407 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
7408 NULL, NULL, (xmlNodePtr) attr, NULL,
7409 "(qualified | unqualified)", val, NULL, NULL, NULL);
7410 }
7411 }
7412
7413 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
7414 if (attr != NULL) {
7415 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7416 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7417 XML_SCHEMAS_QUALIF_ATTR) != 0) {
7418 xmlSchemaPSimpleTypeErr(ctxt,
7419 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
7420 NULL, NULL, (xmlNodePtr) attr, NULL,
7421 "(qualified | unqualified)", val, NULL, NULL, NULL);
7422 }
7423 }
7424
7425 attr = xmlSchemaGetPropNode(node, "finalDefault");
7426 if (attr != NULL) {
7427 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7428 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7429 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
7430 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
7431 -1,
7432 XML_SCHEMAS_FINAL_DEFAULT_LIST,
7433 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
7434 xmlSchemaPSimpleTypeErr(ctxt,
7435 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7436 NULL, NULL, (xmlNodePtr) attr, NULL,
7437 "(#all | List of (extension | restriction | list | union))",
7438 val, NULL, NULL, NULL);
7439 }
7440 }
7441
7442 attr = xmlSchemaGetPropNode(node, "blockDefault");
7443 if (attr != NULL) {
7444 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7445 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7446 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
7447 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
7448 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
7449 xmlSchemaPSimpleTypeErr(ctxt,
7450 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7451 NULL, NULL, (xmlNodePtr) attr, NULL,
7452 "(#all | List of (extension | restriction | substitution))",
7453 val, NULL, NULL, NULL);
7454 }
7455 }
7456}
7457
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007458/**
7459 * xmlSchemaParseSchemaTopLevel:
7460 * @ctxt: a schema validation context
7461 * @schema: the schemas
7462 * @nodes: the list of top level nodes
7463 *
7464 * Returns the internal XML Schema structure built from the resource or
7465 * NULL in case of error
7466 */
7467static void
7468xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
7469 xmlSchemaPtr schema, xmlNodePtr nodes)
7470{
7471 xmlNodePtr child;
7472 xmlSchemaAnnotPtr annot;
7473
7474 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
7475 return;
7476
7477 child = nodes;
7478 while ((IS_SCHEMA(child, "include")) ||
7479 (IS_SCHEMA(child, "import")) ||
7480 (IS_SCHEMA(child, "redefine")) ||
7481 (IS_SCHEMA(child, "annotation"))) {
7482 if (IS_SCHEMA(child, "annotation")) {
7483 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7484 if (schema->annot == NULL)
7485 schema->annot = annot;
7486 else
7487 xmlSchemaFreeAnnot(annot);
7488 } else if (IS_SCHEMA(child, "import")) {
7489 xmlSchemaParseImport(ctxt, schema, child);
7490 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007491 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007492 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007493 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007494 } else if (IS_SCHEMA(child, "redefine")) {
7495 TODO
7496 }
7497 child = child->next;
7498 }
7499 while (child != NULL) {
7500 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007501 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007502 child = child->next;
7503 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007504 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007505 child = child->next;
7506 } else if (IS_SCHEMA(child, "element")) {
7507 xmlSchemaParseElement(ctxt, schema, child, 1);
7508 child = child->next;
7509 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00007510 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007511 child = child->next;
7512 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007513 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007514 child = child->next;
7515 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007516 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007517 child = child->next;
7518 } else if (IS_SCHEMA(child, "notation")) {
7519 xmlSchemaParseNotation(ctxt, schema, child);
7520 child = child->next;
7521 } else {
7522 xmlSchemaPErr2(ctxt, NULL, child,
7523 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007524 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007525 child->name, NULL);
7526 child = child->next;
7527 }
7528 while (IS_SCHEMA(child, "annotation")) {
7529 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7530 if (schema->annot == NULL)
7531 schema->annot = annot;
7532 else
7533 xmlSchemaFreeAnnot(annot);
7534 child = child->next;
7535 }
7536 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007537 ctxt->parentItem = NULL;
7538 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007539}
7540
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007541static xmlSchemaImportPtr
7542xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
7543 xmlHashTablePtr *imports,
7544 const xmlChar *nsName)
7545{
7546 xmlSchemaImportPtr ret;
7547
7548 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00007549 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007550 if (*imports == NULL) {
7551 xmlSchemaPCustomErr(ctxt,
7552 XML_SCHEMAP_FAILED_BUILD_IMPORT,
7553 NULL, NULL, (xmlNodePtr) ctxt->doc,
7554 "Internal error: failed to build the import table",
7555 NULL);
7556 return (NULL);
7557 }
7558 }
7559 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7560 if (ret == NULL) {
7561 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
7562 return (NULL);
7563 }
7564 memset(ret, 0, sizeof(xmlSchemaImport));
7565 if (nsName == NULL)
7566 nsName = XML_SCHEMAS_NO_NAMESPACE;
7567 xmlHashAddEntry(*imports, nsName, ret);
7568
7569 return (ret);
7570}
7571
7572static int
7573xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007574 xmlSchemaPtr schema,
7575 xmlNodePtr node,
7576 const xmlChar *nsName,
7577 const xmlChar *location,
7578 xmlDocPtr *doc,
7579 const xmlChar **targetNamespace,
7580 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007581{
7582 xmlParserCtxtPtr parserCtxt;
7583 xmlSchemaImportPtr import;
7584 const xmlChar *ns;
7585 xmlNodePtr root;
7586
7587 /*
7588 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
7589 * <xsi:noNamespaceSchemaLocation>.
7590 */
7591 *doc = NULL;
7592 /*
7593 * Given that the schemaLocation [attribute] is only a hint, it is open
7594 * to applications to ignore all but the first <import> for a given
7595 * namespace, regardless of the ·actual value· of schemaLocation, but
7596 * such a strategy risks missing useful information when new
7597 * schemaLocations are offered.
7598 *
7599 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
7600 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
7601 * valid or not.
7602 * We will follow XSV here.
7603 */
7604 if (location == NULL) {
7605 /*
7606 * Schema Document Location Strategy:
7607 *
7608 * 3 Based on the namespace name, identify an existing schema document,
7609 * either as a resource which is an XML document or a <schema> element
7610 * information item, in some local schema repository;
7611 *
7612 * 5 Attempt to resolve the namespace name to locate such a resource.
7613 *
7614 * NOTE: Those stategies are not supported, so we will skip.
7615 */
7616 return (0);
7617 }
7618 if (nsName == NULL)
7619 ns = XML_SCHEMAS_NO_NAMESPACE;
7620 else
7621 ns = nsName;
7622
7623 import = xmlHashLookup(schema->schemasImports, ns);
7624 if (import != NULL) {
7625 /*
7626 * There was a valid resource for the specified namespace already
7627 * defined, so skip.
7628 * TODO: This might be changed someday to allow import of
7629 * components from multiple documents for a single target namespace.
7630 */
7631 return (0);
7632 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007633
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007634 /*
7635 * Schema Document Location Strategy:
7636 *
7637 * 2 Based on the location URI, identify an existing schema document,
7638 * either as a resource which is an XML document or a <schema> element
7639 * information item, in some local schema repository;
7640 *
7641 * 4 Attempt to resolve the location URI, to locate a resource on the
7642 * web which is or contains or references a <schema> element;
7643 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
7644 *
7645 */
7646 if ((absolute == 0) && (node != NULL)) {
7647 xmlChar *base, *URI;
7648
7649 base = xmlNodeGetBase(node->doc, node);
7650 if (base == NULL) {
7651 URI = xmlBuildURI(location, node->doc->URL);
7652 } else {
7653 URI = xmlBuildURI(location, base);
7654 xmlFree(base);
7655 }
7656 if (URI != NULL) {
7657 location = xmlDictLookup(ctxt->dict, URI, -1);
7658 xmlFree(URI);
7659 }
7660 }
7661 parserCtxt = xmlNewParserCtxt();
7662 if (parserCtxt == NULL) {
7663 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
7664 "allocating a parser context", NULL);
7665 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007666 }
7667
7668 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7669 xmlDictFree(parserCtxt->dict);
7670 parserCtxt->dict = ctxt->dict;
7671 xmlDictReference(parserCtxt->dict);
7672 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007673
7674 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
7675 NULL, SCHEMAS_PARSE_OPTIONS);
7676
7677 /*
7678 * 2.1 The referent is (a fragment of) a resource which is an
7679 * XML document (see clause 1.1), which in turn corresponds to
7680 * a <schema> element information item in a well-formed information
7681 * set, which in turn corresponds to a valid schema.
7682 * TODO: What to do with the "fragment" stuff?
7683 *
7684 * 2.2 The referent is a <schema> element information item in
7685 * a well-formed information set, which in turn corresponds
7686 * to a valid schema.
7687 * NOTE: 2.2 won't apply, since only XML documents will be processed
7688 * here.
7689 */
7690 if (*doc == NULL) {
7691 xmlErrorPtr lerr;
7692 /*
7693 * It is *not* an error for the application schema reference
7694 * strategy to fail.
7695 *
7696 * If the doc is NULL and the parser error is an IO error we
7697 * will assume that the resource could not be located or accessed.
7698 *
7699 * TODO: Try to find specific error codes to react only on
7700 * localisation failures.
7701 *
7702 * TODO, FIXME: Check the spec: is a namespace added to the imported
7703 * namespaces, even if the schemaLocation did not provide
7704 * a resource? I guess so, since omitting the "schemaLocation"
7705 * attribute, imports a namespace as well.
7706 */
7707 lerr = xmlGetLastError();
7708 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
7709 xmlFreeParserCtxt(parserCtxt);
7710 return(0);
7711 }
7712
7713 xmlSchemaPCustomErr(ctxt,
7714 XML_SCHEMAP_SRC_IMPORT_2_1,
7715 NULL, NULL, node,
7716 "Failed to parse the resource '%s' for import",
7717 location);
7718 xmlFreeParserCtxt(parserCtxt);
7719 return(XML_SCHEMAP_SRC_IMPORT_2_1);
7720 }
7721 xmlFreeParserCtxt(parserCtxt);
7722
7723 root = xmlDocGetRootElement(*doc);
7724 if (root == NULL) {
7725 xmlSchemaPCustomErr(ctxt,
7726 XML_SCHEMAP_SRC_IMPORT_2_1,
7727 NULL, NULL, node,
7728 "The XML document '%s' to be imported has no document "
7729 "element", location);
7730 xmlFreeDoc(*doc);
7731 *doc = NULL;
7732 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7733 }
7734
7735 xmlSchemaCleanupDoc(ctxt, root);
7736
7737 if (!IS_SCHEMA(root, "schema")) {
7738 xmlSchemaPCustomErr(ctxt,
7739 XML_SCHEMAP_SRC_IMPORT_2_1,
7740 NULL, NULL, node,
7741 "The XML document '%s' to be imported is not a XML schema document",
7742 location);
7743 xmlFreeDoc(*doc);
7744 *doc = NULL;
7745 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7746 }
7747 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
7748 /*
7749 * Schema Representation Constraint: Import Constraints and Semantics
7750 */
7751 if (nsName == NULL) {
7752 if (*targetNamespace != NULL) {
7753 xmlSchemaPCustomErr(ctxt,
7754 XML_SCHEMAP_SRC_IMPORT_3_2,
7755 NULL, NULL, node,
7756 "The XML schema to be imported is not expected "
7757 "to have a target namespace; this differs from "
7758 "its target namespace of '%s'", *targetNamespace);
7759 xmlFreeDoc(*doc);
7760 *doc = NULL;
7761 return (XML_SCHEMAP_SRC_IMPORT_3_2);
7762 }
7763 } else {
7764 if (*targetNamespace == NULL) {
7765 xmlSchemaPCustomErr(ctxt,
7766 XML_SCHEMAP_SRC_IMPORT_3_1,
7767 NULL, NULL, node,
7768 "The XML schema to be imported is expected to have a target "
7769 "namespace of '%s'", nsName);
7770 xmlFreeDoc(*doc);
7771 *doc = NULL;
7772 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7773 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
7774 xmlSchemaPCustomErrExt(ctxt,
7775 XML_SCHEMAP_SRC_IMPORT_3_1,
7776 NULL, NULL, node,
7777 "The XML schema to be imported is expected to have a "
7778 "target namespace of '%s'; this differs from "
7779 "its target namespace of '%s'",
7780 nsName, *targetNamespace, NULL);
7781 xmlFreeDoc(*doc);
7782 *doc = NULL;
7783 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7784 }
7785 }
7786
7787 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
7788 if (import == NULL) {
7789 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
7790 NULL, NULL, NULL,
7791 "Internal error: xmlSchemaAcquireSchemaDoc, "
7792 "failed to build import table", NULL);
7793 xmlFreeDoc(*doc);
7794 *doc = NULL;
7795 return (-1);
7796 }
7797 import->schemaLocation = location;
7798 import->doc = *doc;
7799 return (0);
7800}
William M. Brack2f2a6632004-08-20 23:09:47 +00007801
7802/**
7803 * xmlSchemaParseImport:
7804 * @ctxt: a schema validation context
7805 * @schema: the schema being built
7806 * @node: a subtree containing XML Schema informations
7807 *
7808 * parse a XML schema Import definition
7809 * *WARNING* this interface is highly subject to change
7810 *
7811 * Returns 0 in case of success, a positive error code if
7812 * not valid and -1 in case of an internal error.
7813 */
7814static int
7815xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7816 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007817{
7818 xmlNodePtr child;
7819 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007820 const xmlChar *schemaLocation = NULL;
7821 const xmlChar *targetNamespace, *oldTNS, *url;
7822 xmlAttrPtr attr;
7823 xmlDocPtr doc;
7824 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007825 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007826
7827
7828 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7829 return (-1);
7830
7831 /*
7832 * Check for illegal attributes.
7833 */
7834 attr = node->properties;
7835 while (attr != NULL) {
7836 if (attr->ns == NULL) {
7837 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7838 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7839 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7840 xmlSchemaPIllegalAttrErr(ctxt,
7841 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7842 NULL, NULL, attr);
7843 }
7844 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7845 xmlSchemaPIllegalAttrErr(ctxt,
7846 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7847 NULL, NULL, attr);
7848 }
7849 attr = attr->next;
7850 }
7851 /*
7852 * Extract and validate attributes.
7853 */
7854 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7855 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7856 &namespace) != 0) {
7857 xmlSchemaPSimpleTypeErr(ctxt,
7858 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
7859 NULL, NULL, node,
7860 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7861 NULL, namespace, NULL, NULL, NULL);
7862 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
7863 }
7864
7865 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7866 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7867 &schemaLocation) != 0) {
7868 xmlSchemaPSimpleTypeErr(ctxt,
7869 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
7870 NULL, NULL, node,
7871 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7872 NULL, namespace, NULL, NULL, NULL);
7873 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
7874 }
7875 /*
7876 * And now for the children...
7877 */
7878 child = node->children;
7879 if (IS_SCHEMA(child, "annotation")) {
7880 /*
7881 * the annotation here is simply discarded ...
7882 */
7883 child = child->next;
7884 }
7885 if (child != NULL) {
7886 xmlSchemaPContentErr(ctxt,
7887 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
7888 NULL, NULL, node, child, NULL,
7889 "(annotation?)");
7890 }
7891 /*
7892 * Apply additional constraints.
7893 */
7894 if (namespace != NULL) {
7895 /*
7896 * 1.1 If the namespace [attribute] is present, then its ·actual value·
7897 * must not match the ·actual value· of the enclosing <schema>'s
7898 * targetNamespace [attribute].
7899 */
7900 if (xmlStrEqual(schema->targetNamespace, namespace)) {
7901 xmlSchemaPCustomErr(ctxt,
7902 XML_SCHEMAP_SRC_IMPORT_1_1,
7903 NULL, NULL, node,
7904 "The value of the attribute 'namespace' must not match "
7905 "the target namespace '%s' of the importing schema",
7906 schema->targetNamespace);
7907 return (XML_SCHEMAP_SRC_IMPORT_1_1);
7908 }
7909 } else {
7910 /*
7911 * 1.2 If the namespace [attribute] is not present, then the enclosing
7912 * <schema> must have a targetNamespace [attribute].
7913 */
7914 if (schema->targetNamespace == NULL) {
7915 xmlSchemaPCustomErr(ctxt,
7916 XML_SCHEMAP_SRC_IMPORT_1_2,
7917 NULL, NULL, node,
7918 "The attribute 'namespace' must be existent if "
7919 "the importing schema has no target namespace",
7920 NULL);
7921 return (XML_SCHEMAP_SRC_IMPORT_1_2);
7922 }
7923 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007924 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007925 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00007926 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007927 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
7928 schemaLocation, &doc, &targetNamespace, 0);
7929 if (ret != 0) {
7930 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00007931 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007932 return (ret);
7933 } else if (doc != NULL) {
7934 /*
7935 * Save and reset the context & schema.
7936 */
7937 url = ctxt->URL;
7938 /* TODO: Is using the doc->URL here correct? */
7939 ctxt->URL = doc->URL;
7940 flags = schema->flags;
7941 oldTNS = schema->targetNamespace;
7942 /*
7943 * Parse the schema.
7944 */
7945 root = xmlDocGetRootElement(doc);
7946 xmlSchemaClearSchemaDefaults(schema);
7947 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
7948 schema->targetNamespace = targetNamespace;
7949 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
7950 /*
7951 * Restore the context & schema.
7952 */
7953 schema->flags = flags;
7954 schema->targetNamespace = oldTNS;
7955 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00007956 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007957
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007958 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007959}
7960
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007961/**
7962 * xmlSchemaParseInclude:
7963 * @ctxt: a schema validation context
7964 * @schema: the schema being built
7965 * @node: a subtree containing XML Schema informations
7966 *
7967 * parse a XML schema Include definition
7968 *
William M. Bracke7091952004-05-11 15:09:58 +00007969 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007970 * 1 in case of success.
7971 */
7972static int
7973xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7974 xmlNodePtr node)
7975{
7976 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007977 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007978 xmlDocPtr doc;
7979 xmlNodePtr root;
7980 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007981 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007982 xmlAttrPtr attr;
7983 int saveFlags;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007984 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007985
7986
7987 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7988 return (-1);
7989
7990 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007991 * Check for illegal attributes.
7992 */
7993 attr = node->properties;
7994 while (attr != NULL) {
7995 if (attr->ns == NULL) {
7996 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7997 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7998 xmlSchemaPIllegalAttrErr(ctxt,
7999 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8000 NULL, NULL, attr);
8001 }
8002 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8003 xmlSchemaPIllegalAttrErr(ctxt,
8004 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8005 NULL, NULL, attr);
8006 }
8007 attr = attr->next;
8008 }
8009 /*
8010 * Extract and validate attributes.
8011 */
8012 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008013 * Preliminary step, extract the URI-Reference for the include and
8014 * make an URI from the base.
8015 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008016 attr = xmlSchemaGetPropNode(node, "schemaLocation");
8017 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008018 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008019 xmlChar *uri = NULL;
8020
8021 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8022 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
8023 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008024 base = xmlNodeGetBase(node->doc, node);
8025 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008026 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008027 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00008028 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008029 xmlFree(base);
8030 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008031 if (uri != NULL) {
8032 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
8033 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008034 }
8035 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00008036 xmlSchemaPMissingAttrErr(ctxt,
8037 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
8038 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008039 return (-1);
8040 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008041 /*
8042 * And now for the children...
8043 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008044 child = node->children;
8045 while (IS_SCHEMA(child, "annotation")) {
8046 /*
8047 * the annotations here are simply discarded ...
8048 */
8049 child = child->next;
8050 }
8051 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008052 xmlSchemaPContentErr(ctxt,
8053 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
8054 NULL, NULL, node, child, NULL,
8055 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008056 }
8057
8058 /*
8059 * First step is to parse the input document into an DOM/Infoset
8060 */
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008061 /*
8062 * TODO: Use xmlCtxtReadFile to share the dictionary.
8063 */
8064 parserCtxt = xmlNewParserCtxt();
8065 if (parserCtxt == NULL) {
8066 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
8067 "allocating a parser context", NULL);
8068 return(-1);
8069 }
8070
8071 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
8072 xmlDictFree(parserCtxt->dict);
8073 parserCtxt->dict = ctxt->dict;
8074 xmlDictReference(parserCtxt->dict);
8075 }
8076
8077 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
8078 NULL, SCHEMAS_PARSE_OPTIONS);
8079 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008080 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008081 /*
8082 * TODO: It is not an error for the ·actual value· of the
8083 * schemaLocation [attribute] to fail to resolve it all, in which
8084 * case no corresponding inclusion is performed.
8085 * So do we need a warning report here?
8086 */
8087 xmlSchemaPCustomErr(ctxt,
8088 XML_SCHEMAP_FAILED_LOAD,
8089 NULL, NULL, node,
8090 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008091 return(-1);
8092 }
8093
8094 /*
8095 * Then extract the root of the schema
8096 */
8097 root = xmlDocGetRootElement(doc);
8098 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008099 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008100 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00008101 NULL, NULL, node,
8102 "The included document '%s' has no document "
8103 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008104 xmlFreeDoc(doc);
8105 return (-1);
8106 }
8107
8108 /*
8109 * Remove all the blank text nodes
8110 */
8111 xmlSchemaCleanupDoc(ctxt, root);
8112
8113 /*
8114 * Check the schemas top level element
8115 */
8116 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008117 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008118 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00008119 NULL, NULL, node,
8120 "The document '%s' to be included is not a schema document",
8121 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008122 xmlFreeDoc(doc);
8123 return (-1);
8124 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008125
William M. Brack2f2a6632004-08-20 23:09:47 +00008126 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008127 /*
8128 * 2.1 SII has a targetNamespace [attribute], and its ·actual
8129 * value· is identical to the ·actual value· of the targetNamespace
8130 * [attribute] of SIIÂ’ (which must have such an [attribute]).
8131 */
8132 if (targetNamespace != NULL) {
8133 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008134 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008135 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008136 NULL, NULL, node,
8137 "The target namespace of the included schema "
8138 "'%s' has to be absent, since the including schema "
8139 "has no target namespace",
8140 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008141 xmlFreeDoc(doc);
8142 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008143 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
8144 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008145 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008146 NULL, NULL, node,
8147 "The target namespace '%s' of the included schema '%s' "
8148 "differs from '%s' of the including schema",
8149 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008150 xmlFreeDoc(doc);
8151 return (-1);
8152 }
8153 } else if (schema->targetNamespace != NULL) {
8154 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
8155 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
8156 } else
8157 wasConvertingNs = 1;
8158 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008159 /*
8160 * register the include
8161 */
8162 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
8163 if (include == NULL) {
8164 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
8165 xmlFreeDoc(doc);
8166 return (-1);
8167 }
8168
8169 memset(include, 0, sizeof(xmlSchemaInclude));
8170 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8171 include->doc = doc;
8172 include->next = schema->includes;
8173 schema->includes = include;
8174
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008175 /*
8176 * parse the declarations in the included file like if they
8177 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008178 */
8179 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00008180 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008181 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008182 /*
8183 * The default values ("blockDefault", "elementFormDefault", etc.)
8184 * are set to the values of the included schema and restored afterwards.
8185 */
8186 saveFlags = schema->flags;
8187 xmlSchemaClearSchemaDefaults(schema);
8188 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008189 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00008190 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008191 /*
8192 * Remove the converting flag.
8193 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008194 if ((wasConvertingNs == 0) &&
8195 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00008196 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008197 return (1);
8198}
8199
8200/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008201 * xmlSchemaParseChoice:
8202 * @ctxt: a schema validation context
8203 * @schema: the schema being built
8204 * @node: a subtree containing XML Schema informations
8205 *
8206 * parse a XML schema Choice definition
8207 * *WARNING* this interface is highly subject to change
8208 *
William M. Bracke7091952004-05-11 15:09:58 +00008209 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008210 * 1 in case of success.
8211 */
8212static xmlSchemaTypePtr
8213xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008214 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008215{
8216 xmlSchemaTypePtr type, subtype, last = NULL;
8217 xmlNodePtr child = NULL;
8218 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008219 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008220 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008221
8222 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8223 return (NULL);
8224
8225
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008226 snprintf((char *) name, 30, "#ch%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008227 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008228 if (type == NULL)
8229 return (NULL);
8230 type->node = node;
8231 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008232 /*
8233 * Check for illegal attributes.
8234 */
8235 attr = node->properties;
8236 while (attr != NULL) {
8237 if (attr->ns == NULL) {
8238 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8239 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8240 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8241 xmlSchemaPIllegalAttrErr(ctxt,
8242 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8243 NULL, type, attr);
8244 }
8245 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8246 xmlSchemaPIllegalAttrErr(ctxt,
8247 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8248 NULL, type, attr);
8249 }
8250 attr = attr->next;
8251 }
8252 /*
8253 * Extract and validate attributes.
8254 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008255 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008256 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8257 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8258 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008259 /*
8260 * And now for the children...
8261 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008262 oldcontainer = ctxt->container;
8263 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008264 child = node->children;
8265 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008266 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8267 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008268 }
8269 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008270 (IS_SCHEMA(child, "group")) ||
8271 (IS_SCHEMA(child, "any")) ||
8272 (IS_SCHEMA(child, "choice")) ||
8273 (IS_SCHEMA(child, "sequence"))) {
8274 subtype = NULL;
8275 if (IS_SCHEMA(child, "element")) {
8276 subtype = (xmlSchemaTypePtr)
8277 xmlSchemaParseElement(ctxt, schema, child, 0);
8278 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008279 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008280 } else if (IS_SCHEMA(child, "any")) {
8281 subtype = xmlSchemaParseAny(ctxt, schema, child);
8282 } else if (IS_SCHEMA(child, "sequence")) {
8283 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8284 } else if (IS_SCHEMA(child, "choice")) {
8285 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8286 }
8287 if (subtype != NULL) {
8288 if (last == NULL) {
8289 type->subtypes = subtype;
8290 last = subtype;
8291 } else {
8292 last->next = subtype;
8293 last = subtype;
8294 }
8295 last->next = NULL;
8296 }
8297 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008298 }
8299 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008300 /* TODO: error code. */
8301 xmlSchemaPContentErr(ctxt,
8302 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
8303 NULL, type, node, child, NULL,
8304 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008305 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008306 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008307 return (type);
8308}
8309
8310/**
8311 * xmlSchemaParseSequence:
8312 * @ctxt: a schema validation context
8313 * @schema: the schema being built
8314 * @node: a subtree containing XML Schema informations
8315 *
8316 * parse a XML schema Sequence definition
8317 * *WARNING* this interface is highly subject to change
8318 *
William M. Bracke7091952004-05-11 15:09:58 +00008319 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008320 * 1 in case of success.
8321 */
8322static xmlSchemaTypePtr
8323xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008324 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008325{
8326 xmlSchemaTypePtr type, subtype, last = NULL;
8327 xmlNodePtr child = NULL;
8328 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008329 xmlAttrPtr attr;
8330 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008331
8332 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8333 return (NULL);
8334
William M. Brack2f2a6632004-08-20 23:09:47 +00008335 oldcontainer = ctxt->container;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008336 snprintf((char *) name, 30, "#seq%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008337 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008338 if (type == NULL)
8339 return (NULL);
8340 type->node = node;
8341 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008342 /*
8343 * Check for illegal attributes.
8344 */
8345 attr = node->properties;
8346 while (attr != NULL) {
8347 if (attr->ns == NULL) {
8348 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8349 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8350 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8351 xmlSchemaPIllegalAttrErr(ctxt,
8352 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8353 NULL, type, attr);
8354 }
8355 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8356 xmlSchemaPIllegalAttrErr(ctxt,
8357 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8358 NULL, type, attr);
8359 }
8360 attr = attr->next;
8361 }
8362 /*
8363 * Extract and validate attributes.
8364 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008365 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008366 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8367 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8368 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008369 /*
8370 * And now for the children...
8371 */
8372 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008373 child = node->children;
8374 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008375 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8376 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008377 }
8378 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008379 (IS_SCHEMA(child, "group")) ||
8380 (IS_SCHEMA(child, "any")) ||
8381 (IS_SCHEMA(child, "choice")) ||
8382 (IS_SCHEMA(child, "sequence"))) {
8383 subtype = NULL;
8384 if (IS_SCHEMA(child, "element")) {
8385 subtype = (xmlSchemaTypePtr)
8386 xmlSchemaParseElement(ctxt, schema, child, 0);
8387 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008388 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008389 } else if (IS_SCHEMA(child, "any")) {
8390 subtype = xmlSchemaParseAny(ctxt, schema, child);
8391 } else if (IS_SCHEMA(child, "choice")) {
8392 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8393 } else if (IS_SCHEMA(child, "sequence")) {
8394 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8395 }
8396 if (subtype != NULL) {
8397 if (last == NULL) {
8398 type->subtypes = subtype;
8399 last = subtype;
8400 } else {
8401 last->next = subtype;
8402 last = subtype;
8403 }
8404 last->next = NULL;
8405 }
8406 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008407 }
8408 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008409 xmlSchemaPContentErr(ctxt,
8410 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
8411 NULL, type, node, child, NULL,
8412 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008413 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008414 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008415
8416 return (type);
8417}
8418
8419/**
8420 * xmlSchemaParseRestriction:
8421 * @ctxt: a schema validation context
8422 * @schema: the schema being built
8423 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00008424 *
8425 * parse a XML schema Restriction definition
8426 * *WARNING* this interface is highly subject to change
8427 *
8428 * Returns the type definition or NULL in case of error
8429 */
8430static xmlSchemaTypePtr
8431xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008432 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008433{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008434 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00008435 xmlNodePtr child = NULL;
8436 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008437 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00008438 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008439
8440 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8441 return (NULL);
8442
8443 oldcontainer = ctxt->container;
8444
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008445 snprintf((char *) name, 30, "#restr%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008446 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008447 if (type == NULL)
8448 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008449 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008450 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00008451 /*
8452 * Check for illegal attributes.
8453 */
8454 attr = node->properties;
8455 while (attr != NULL) {
8456 if (attr->ns == NULL) {
8457 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8458 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
8459 xmlSchemaPIllegalAttrErr(ctxt,
8460 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8461 NULL, type, attr);
8462 }
8463 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8464 xmlSchemaPIllegalAttrErr(ctxt,
8465 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8466 NULL, type, attr);
8467 }
8468 attr = attr->next;
8469 }
8470 /*
8471 * Extract and validate attributes.
8472 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008473 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008474 /*
8475 * Attribute "base".
8476 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008477 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00008478 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00008479 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8480 /* TODO: Think about the error code. */
8481 xmlSchemaPMissingAttrErr(ctxt,
8482 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
8483 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008484 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008485 /*
8486 * And now for the children...
8487 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008488 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008489 child = node->children;
8490 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008491 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8492 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008493 }
8494 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008495 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8496 if (IS_SCHEMA(child, "all")) {
8497 subtype = (xmlSchemaTypePtr)
8498 xmlSchemaParseAll(ctxt, schema, child);
8499 child = child->next;
8500 type->subtypes = subtype;
8501 } else if (IS_SCHEMA(child, "choice")) {
8502 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8503 child = child->next;
8504 type->subtypes = subtype;
8505 } else if (IS_SCHEMA(child, "sequence")) {
8506 subtype = (xmlSchemaTypePtr)
8507 xmlSchemaParseSequence(ctxt, schema, child);
8508 child = child->next;
8509 type->subtypes = subtype;
8510 } else if (IS_SCHEMA(child, "group")) {
8511 subtype = (xmlSchemaTypePtr)
8512 xmlSchemaParseGroup(ctxt, schema, child, 0);
8513 child = child->next;
8514 type->subtypes = subtype;
8515 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008516 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
8517 if (IS_SCHEMA(child, "simpleType")) {
8518 if (type->base != NULL) {
8519 /*
8520 * src-restriction-base-or-simpleType
8521 * Either the base [attribute] or the simpleType [child] of the
8522 * <restriction> element must be present, but not both.
8523 */
8524 xmlSchemaPContentErr(ctxt,
8525 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
8526 NULL, NULL, type->node, child,
8527 "The attribute 'base' and the <simpleType> child are "
8528 "mutually exclusive", NULL);
8529 } else {
8530 subtype = (xmlSchemaTypePtr)
8531 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8532 type->baseType = subtype;
8533 }
8534 child = child->next;
8535 }
8536 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008537 if (IS_SCHEMA(child, "simpleType")) {
8538 subtype = (xmlSchemaTypePtr)
8539 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008540 type->subtypes = subtype;
8541 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00008542 }
8543 }
8544 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
8545 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
8546 xmlSchemaFacetPtr facet, lastfacet = NULL;
8547
Daniel Veillard01fa6152004-06-29 17:04:39 +00008548 /*
8549 * Add the facets to the parent simpleType/complexType.
8550 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008551 /*
8552 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
8553 * Simple Type Definition Schema Representation Constraint:
8554 * *Single Facet Value*
8555 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008556 while ((IS_SCHEMA(child, "minInclusive")) ||
8557 (IS_SCHEMA(child, "minExclusive")) ||
8558 (IS_SCHEMA(child, "maxInclusive")) ||
8559 (IS_SCHEMA(child, "maxExclusive")) ||
8560 (IS_SCHEMA(child, "totalDigits")) ||
8561 (IS_SCHEMA(child, "fractionDigits")) ||
8562 (IS_SCHEMA(child, "pattern")) ||
8563 (IS_SCHEMA(child, "enumeration")) ||
8564 (IS_SCHEMA(child, "whiteSpace")) ||
8565 (IS_SCHEMA(child, "length")) ||
8566 (IS_SCHEMA(child, "maxLength")) ||
8567 (IS_SCHEMA(child, "minLength"))) {
8568 facet = xmlSchemaParseFacet(ctxt, schema, child);
8569 if (facet != NULL) {
8570 if (lastfacet == NULL)
8571 ctxt->ctxtType->facets = facet;
8572 else
8573 lastfacet->next = facet;
8574 lastfacet = facet;
8575 lastfacet->next = NULL;
8576 }
8577 child = child->next;
8578 }
8579 /*
8580 * Create links for derivation and validation.
8581 */
8582 if (lastfacet != NULL) {
8583 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
8584
8585 facet = ctxt->ctxtType->facets;
8586 do {
8587 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
8588 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008589 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008590 xmlFree(facetLink);
8591 return (NULL);
8592 }
8593 facetLink->facet = facet;
8594 facetLink->next = NULL;
8595 if (lastFacetLink == NULL)
8596 ctxt->ctxtType->facetSet = facetLink;
8597 else
8598 lastFacetLink->next = facetLink;
8599 lastFacetLink = facetLink;
8600 facet = facet->next;
8601 } while (facet != NULL);
8602 }
8603 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008604 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
8605 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8606 if (IS_SCHEMA(child, "anyAttribute")) {
8607 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8608 child = child->next;
8609 }
8610 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008611 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008612 /* TODO: Think about the error code. */
8613 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8614 xmlSchemaPContentErr(ctxt,
8615 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8616 NULL, type, node, child, NULL,
8617 "annotation?, (group | all | choice | sequence)?, "
8618 "((attribute | attributeGroup)*, anyAttribute?))");
8619 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
8620 xmlSchemaPContentErr(ctxt,
8621 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8622 NULL, type, node, child, NULL,
8623 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8624 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8625 "length | minLength | maxLength | enumeration | whiteSpace | "
8626 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
8627 } else {
8628 /* Simple type */
8629 xmlSchemaPContentErr(ctxt,
8630 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8631 NULL, type, node, child, NULL,
8632 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8633 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8634 "length | minLength | maxLength | enumeration | whiteSpace | "
8635 "pattern)*))");
8636 }
8637 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008638 ctxt->container = oldcontainer;
8639 return (type);
8640}
8641
8642/**
8643 * xmlSchemaParseExtension:
8644 * @ctxt: a schema validation context
8645 * @schema: the schema being built
8646 * @node: a subtree containing XML Schema informations
8647 *
8648 * parse a XML schema Extension definition
8649 * *WARNING* this interface is highly subject to change
8650 *
8651 * Returns the type definition or NULL in case of error
8652 */
8653static xmlSchemaTypePtr
8654xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008655 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008656{
8657 xmlSchemaTypePtr type, subtype;
8658 xmlNodePtr child = NULL;
8659 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008660 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008661
8662 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8663 return (NULL);
8664
8665 oldcontainer = ctxt->container;
8666
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008667 snprintf((char *) name, 30, "#ext%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008668 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008669 if (type == NULL)
8670 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008671 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008672 type->node = node;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008673
8674 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8675
Daniel Veillard4255d502002-04-16 15:50:10 +00008676 ctxt->container = name;
8677
8678 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
8679 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008680 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008681 "<extension>: The attribute \"base\" is missing.\n",
8682 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008683 }
8684 child = node->children;
8685 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008686 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8687 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008688 }
8689 subtype = NULL;
8690
8691 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008692 subtype = xmlSchemaParseAll(ctxt, schema, child);
8693 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008694 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008695 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8696 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008697 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008698 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8699 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008700 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008701 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008702 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008703 }
8704 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008705 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008706 if ((ctxt->ctxtType != NULL) &&
8707 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8708 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8709 if (IS_SCHEMA(child, "anyAttribute")) {
8710 ctxt->ctxtType->attributeWildcard =
8711 xmlSchemaParseAnyAttribute(ctxt, schema, child);
8712 child = child->next;
8713 }
8714 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008715 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008716 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008717 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
8718 "<extension> has unexpected content.\n", type->name,
8719 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008720 }
8721 ctxt->container = oldcontainer;
8722 return (type);
8723}
8724
8725/**
8726 * xmlSchemaParseSimpleContent:
8727 * @ctxt: a schema validation context
8728 * @schema: the schema being built
8729 * @node: a subtree containing XML Schema informations
8730 *
8731 * parse a XML schema SimpleContent definition
8732 * *WARNING* this interface is highly subject to change
8733 *
8734 * Returns the type definition or NULL in case of error
8735 */
8736static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008737xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
8738 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008739{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008740 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008741 xmlNodePtr child = NULL;
8742 xmlChar name[30];
8743
8744 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8745 return (NULL);
8746
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008747 snprintf((char *) name, 30, "#SC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008748 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008749 if (type == NULL)
8750 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008751 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00008752 type->node = node;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008753
8754 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00008755
8756 child = node->children;
8757 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008758 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8759 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008760 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008761 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008762 ctxt->parentItem = type;
8763 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008764 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008765 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008766 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008767 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008768 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008769 subtype = (xmlSchemaTypePtr)
8770 xmlSchemaParseExtension(ctxt, schema, child);
8771 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008772 }
8773 type->subtypes = subtype;
8774 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008775 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008776 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
8777 "<simpleContent> has unexpected content.\n",
8778 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008779 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008780 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008781 return (type);
8782}
8783
8784/**
8785 * xmlSchemaParseComplexContent:
8786 * @ctxt: a schema validation context
8787 * @schema: the schema being built
8788 * @node: a subtree containing XML Schema informations
8789 *
8790 * parse a XML schema ComplexContent definition
8791 * *WARNING* this interface is highly subject to change
8792 *
8793 * Returns the type definition or NULL in case of error
8794 */
8795static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008796xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
8797 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008798{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008799 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008800 xmlNodePtr child = NULL;
8801 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008802 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008803
8804 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8805 return (NULL);
8806
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008807 snprintf((char *) name, 30, "#CC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008808 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008809 if (type == NULL)
8810 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008811 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008812 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008813 /*
8814 * Check for illegal attributes.
8815 */
8816 attr = node->properties;
8817 while (attr != NULL) {
8818 if (attr->ns == NULL) {
8819 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8820 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
8821 {
8822 xmlSchemaPIllegalAttrErr(ctxt,
8823 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8824 NULL, NULL, attr);
8825 }
8826 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8827 xmlSchemaPIllegalAttrErr(ctxt,
8828 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8829 NULL, NULL, attr);
8830 }
8831 attr = attr->next;
8832 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008833
8834 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8835
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008836 /*
8837 * Handle attribute 'mixed'.
8838 */
8839 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
8840 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
8841 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
8842 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008843 child = node->children;
8844 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008845 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8846 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008847 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008848 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008849 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008850 subtype = NULL;
8851 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008852 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008853 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008854 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008855 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008856 subtype = (xmlSchemaTypePtr)
8857 xmlSchemaParseExtension(ctxt, schema, child);
8858 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008859 }
8860 type->subtypes = subtype;
8861 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008862 xmlSchemaPContentErr(ctxt,
8863 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8864 NULL, NULL, node, child,
8865 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008866 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008867 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008868 return (type);
8869}
8870
8871/**
8872 * xmlSchemaParseComplexType:
8873 * @ctxt: a schema validation context
8874 * @schema: the schema being built
8875 * @node: a subtree containing XML Schema informations
8876 *
8877 * parse a XML schema Complex Type definition
8878 * *WARNING* this interface is highly subject to change
8879 *
8880 * Returns the type definition or NULL in case of error
8881 */
8882static xmlSchemaTypePtr
8883xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008884 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008885{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008886 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008887 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008888 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008889 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008890 xmlAttrPtr attr;
8891 const xmlChar *attrValue;
8892 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00008893 char buf[40];
8894
Daniel Veillard4255d502002-04-16 15:50:10 +00008895
8896 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8897 return (NULL);
8898
Daniel Veillard01fa6152004-06-29 17:04:39 +00008899 ctxtType = ctxt->ctxtType;
8900
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008901 if (topLevel) {
8902 attr = xmlSchemaGetPropNode(node, "name");
8903 if (attr == NULL) {
8904 xmlSchemaPMissingAttrErr(ctxt,
8905 XML_SCHEMAP_S4S_ATTR_MISSING,
8906 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
8907 "name", NULL);
8908 return (NULL);
8909 } else if (xmlSchemaPValAttrNode(ctxt,
8910 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
8911 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8912 return (NULL);
8913 }
8914 }
8915
8916 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008917 /*
8918 * Parse as local complex type definition.
8919 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008920 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008921 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
8922 if (type == NULL)
8923 return (NULL);
8924 name = (const xmlChar *) buf;
8925 type->node = node;
8926 type->type = XML_SCHEMA_TYPE_COMPLEX;
8927 /*
8928 * TODO: We need the target namespace.
8929 */
8930 } else {
8931 /*
8932 * Parse as global complex type definition.
8933 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008934 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008935 if (type == NULL)
8936 return (NULL);
8937 type->node = node;
8938 type->type = XML_SCHEMA_TYPE_COMPLEX;
8939 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8940 /*
8941 * Set defaults.
8942 */
8943 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
8944 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008945 }
8946 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008947 /*
8948 * Handle attributes.
8949 */
8950 attr = node->properties;
8951 while (attr != NULL) {
8952 if (attr->ns == NULL) {
8953 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
8954 /*
8955 * Attribute "id".
8956 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008957 xmlSchemaPValAttrID(ctxt, NULL, type, node,
8958 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008959 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
8960 /*
8961 * Attribute "mixed".
8962 */
8963 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8964 (xmlNodePtr) attr))
8965 type->flags |= XML_SCHEMAS_TYPE_MIXED;
8966 } else if (topLevel) {
8967 /*
8968 * Attributes of global complex type definitions.
8969 */
8970 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
8971 /* Pass. */
8972 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
8973 /*
8974 * Attribute "abstract".
8975 */
8976 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8977 (xmlNodePtr) attr))
8978 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
8979 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
8980 /*
8981 * Attribute "final".
8982 */
8983 attrValue = xmlSchemaGetNodeContent(ctxt,
8984 (xmlNodePtr) attr);
8985 if (xmlSchemaPValAttrBlockFinal(attrValue,
8986 &(type->flags),
8987 -1,
8988 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
8989 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
8990 -1, -1, -1) != 0)
8991 {
8992 xmlSchemaPSimpleTypeErr(ctxt,
8993 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8994 &des, type, (xmlNodePtr) attr,
8995 NULL,
8996 "(#all | List of (extension | restriction))",
8997 attrValue, NULL, NULL, NULL);
8998 }
8999 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
9000 /*
9001 * Attribute "block".
9002 */
9003 attrValue = xmlSchemaGetNodeContent(ctxt,
9004 (xmlNodePtr) attr);
9005 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9006 -1,
9007 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
9008 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
9009 -1, -1, -1) != 0) {
9010 xmlSchemaPSimpleTypeErr(ctxt,
9011 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9012 &des, type, (xmlNodePtr) attr,
9013 NULL,
9014 "(#all | List of (extension | restriction)) ",
9015 attrValue, NULL, NULL, NULL);
9016 }
9017 } else {
9018 xmlSchemaPIllegalAttrErr(ctxt,
9019 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9020 &des, type, attr);
9021 }
9022 } else {
9023 xmlSchemaPIllegalAttrErr(ctxt,
9024 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9025 &des, type, attr);
9026 }
9027 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9028 xmlSchemaPIllegalAttrErr(ctxt,
9029 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9030 &des, type, attr);
9031 }
9032 attr = attr->next;
9033 }
9034 /*
9035 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009036 * This will be only changed if a complex type
9037 * inherits an attribute wildcard from a base type.
9038 */
9039 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009040 /*
9041 * And now for the children...
9042 */
9043 oldcontainer = ctxt->container;
9044 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009045 child = node->children;
9046 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009047 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9048 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009049 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009050 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009051 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009052 /*
9053 * 3.4.3 : 2.2
9054 * Specifying mixed='true' when the <simpleContent>
9055 * alternative is chosen has no effect
9056 */
William M. Bracke7091952004-05-11 15:09:58 +00009057 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
9058 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009059 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
9060 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009061 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009062 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
9063 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009064 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009065 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009066 /*
9067 * Parse model groups.
9068 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009069 if (IS_SCHEMA(child, "all")) {
9070 subtype = xmlSchemaParseAll(ctxt, schema, child);
9071 child = child->next;
9072 } else if (IS_SCHEMA(child, "choice")) {
9073 subtype = xmlSchemaParseChoice(ctxt, schema, child);
9074 child = child->next;
9075 } else if (IS_SCHEMA(child, "sequence")) {
9076 subtype = xmlSchemaParseSequence(ctxt, schema, child);
9077 child = child->next;
9078 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009079 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009080 child = child->next;
9081 }
9082 if (subtype != NULL)
9083 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009084 /*
9085 * Parse attribute decls/refs.
9086 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009087 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009088 /*
9089 * Parse attribute wildcard.
9090 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009091 if (IS_SCHEMA(child, "anyAttribute")) {
9092 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
9093 child = child->next;
9094 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009095 }
9096 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009097 xmlSchemaPContentErr(ctxt,
9098 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9099 &des, type, node, child,
9100 NULL, "(annotation?, (simpleContent | complexContent | "
9101 "((group | all | choice | sequence)?, ((attribute | "
9102 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009103 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009104 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00009105 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009106 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009107 return (type);
9108}
9109
Daniel Veillard4255d502002-04-16 15:50:10 +00009110/**
9111 * xmlSchemaParseSchema:
9112 * @ctxt: a schema validation context
9113 * @node: a subtree containing XML Schema informations
9114 *
9115 * parse a XML schema definition from a node set
9116 * *WARNING* this interface is highly subject to change
9117 *
9118 * Returns the internal XML Schema structure built from the resource or
9119 * NULL in case of error
9120 */
9121static xmlSchemaPtr
9122xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
9123{
9124 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009125 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009126 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009127 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009128
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009129 /*
9130 * This one is called by xmlSchemaParse only and is used if
9131 * the schema to be parsed was specified via the API; i.e. not
9132 * automatically by the validated instance document.
9133 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009134 if ((ctxt == NULL) || (node == NULL))
9135 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009136 nberrors = ctxt->nberrors;
9137 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009138 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009139 xmlSchemaImportPtr import;
9140
Daniel Veillard4255d502002-04-16 15:50:10 +00009141 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009142 if (schema == NULL)
9143 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009144 /*
9145 * Disable build of list of items.
9146 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009147 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9148 if (attr != NULL) {
9149 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9150 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
9151 /*
9152 * TODO: Should we proceed with an invalid target namespace?
9153 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009154 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
9155 } else {
9156 schema->targetNamespace = NULL;
9157 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009158 /*
9159 * Add the current ns name and location to the import table;
9160 * this is needed to have a consistent mechanism, regardless
9161 * if all schemata are constructed dynamically fired by the
9162 * instance or if the schema to be used was specified via
9163 * the API.
9164 */
9165 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
9166 schema->targetNamespace);
9167 if (import == NULL) {
9168 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
9169 NULL, NULL, (xmlNodePtr) ctxt->doc,
9170 "Internal error: xmlSchemaParseSchema, "
9171 "failed to add an import entry", NULL);
9172 xmlSchemaFree(schema);
9173 schema = NULL;
9174 return (NULL);
9175 }
9176 import->schemaLocation = ctxt->URL;
9177 /*
9178 * NOTE: We won't set the doc here, otherwise it will be freed
9179 * if the import struct is freed.
9180 * import->doc = ctxt->doc;
9181 */
9182
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009183 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009184 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
9185 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
9186
William M. Brack2f2a6632004-08-20 23:09:47 +00009187 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009188 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
9189 } else {
9190 xmlDocPtr doc;
9191
9192 doc = node->doc;
9193
9194 if ((doc != NULL) && (doc->URL != NULL)) {
9195 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9196 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009197 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009198 } else {
9199 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9200 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009201 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009202 }
9203 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009204 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009205 if (ctxt->nberrors != 0) {
9206 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009207 xmlSchemaFree(schema);
9208 schema = NULL;
9209 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009210 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009211 if (schema != NULL)
9212 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009213 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00009214#ifdef DEBUG
9215 if (schema == NULL)
9216 xmlGenericError(xmlGenericErrorContext,
9217 "xmlSchemaParse() failed\n");
9218#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009219 return (schema);
9220}
9221
9222/************************************************************************
9223 * *
9224 * Validating using Schemas *
9225 * *
9226 ************************************************************************/
9227
9228/************************************************************************
9229 * *
9230 * Reading/Writing Schemas *
9231 * *
9232 ************************************************************************/
9233
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009234#if 0 /* Will be enabled if it is clear what options are needed. */
9235/**
9236 * xmlSchemaParserCtxtSetOptions:
9237 * @ctxt: a schema parser context
9238 * @options: a combination of xmlSchemaParserOption
9239 *
9240 * Sets the options to be used during the parse.
9241 *
9242 * Returns 0 in case of success, -1 in case of an
9243 * API error.
9244 */
9245static int
9246xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
9247 int options)
9248
9249{
9250 int i;
9251
9252 if (ctxt == NULL)
9253 return (-1);
9254 /*
9255 * WARNING: Change the start value if adding to the
9256 * xmlSchemaParseOption.
9257 */
9258 for (i = 1; i < (int) sizeof(int) * 8; i++) {
9259 if (options & 1<<i) {
9260 return (-1);
9261 }
9262 }
9263 ctxt->options = options;
9264 return (0);
9265}
9266
9267/**
9268 * xmlSchemaValidCtxtGetOptions:
9269 * @ctxt: a schema parser context
9270 *
9271 * Returns the option combination of the parser context.
9272 */
9273static int
9274xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
9275
9276{
9277 if (ctxt == NULL)
9278 return (-1);
9279 else
9280 return (ctxt->options);
9281}
9282
9283 void *curItems; /* used for dynamic addition of schemata */
9284 int nbCurItems; /* used for dynamic addition of schemata */
9285 int sizeCurItems; /* used for dynamic addition of schemata */
9286
9287#endif
9288
Daniel Veillard4255d502002-04-16 15:50:10 +00009289/**
9290 * xmlSchemaNewParserCtxt:
9291 * @URL: the location of the schema
9292 *
9293 * Create an XML Schemas parse context for that file/resource expected
9294 * to contain an XML Schemas file.
9295 *
9296 * Returns the parser context or NULL in case of error
9297 */
9298xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009299xmlSchemaNewParserCtxt(const char *URL)
9300{
Daniel Veillard4255d502002-04-16 15:50:10 +00009301 xmlSchemaParserCtxtPtr ret;
9302
9303 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009304 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009305
9306 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9307 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009308 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009309 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009310 return (NULL);
9311 }
9312 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009313 ret->dict = xmlDictCreate();
9314 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00009315 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009316 return (ret);
9317}
9318
9319/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009320 * xmlSchemaNewParserCtxtUseDict:
9321 * @URL: the location of the schema
9322 * @dict: the dictionary to be used
9323 *
9324 * Create an XML Schemas parse context for that file/resource expected
9325 * to contain an XML Schemas file.
9326 *
9327 * Returns the parser context or NULL in case of error
9328 */
9329static xmlSchemaParserCtxtPtr
9330xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9331{
9332 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009333 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009334 if (URL == NULL)
9335 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009336 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009337
9338 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9339 if (ret == NULL) {
9340 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9341 NULL);
9342 return (NULL);
9343 }
9344 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9345 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009346 xmlDictReference(dict);
9347 if (URL != NULL)
9348 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009349 ret->includes = 0;
9350 return (ret);
9351}
9352
9353
9354/**
Daniel Veillard6045c902002-10-09 21:13:59 +00009355 * xmlSchemaNewMemParserCtxt:
9356 * @buffer: a pointer to a char array containing the schemas
9357 * @size: the size of the array
9358 *
9359 * Create an XML Schemas parse context for that memory buffer expected
9360 * to contain an XML Schemas file.
9361 *
9362 * Returns the parser context or NULL in case of error
9363 */
9364xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009365xmlSchemaNewMemParserCtxt(const char *buffer, int size)
9366{
Daniel Veillard6045c902002-10-09 21:13:59 +00009367 xmlSchemaParserCtxtPtr ret;
9368
9369 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009370 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009371
9372 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9373 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009374 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009375 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009376 return (NULL);
9377 }
9378 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9379 ret->buffer = buffer;
9380 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009381 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00009382 return (ret);
9383}
9384
9385/**
Daniel Veillard9d751502003-10-29 13:21:47 +00009386 * xmlSchemaNewDocParserCtxt:
9387 * @doc: a preparsed document tree
9388 *
9389 * Create an XML Schemas parse context for that document.
9390 * NB. The document may be modified during the parsing process.
9391 *
9392 * Returns the parser context or NULL in case of error
9393 */
9394xmlSchemaParserCtxtPtr
9395xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
9396{
9397 xmlSchemaParserCtxtPtr ret;
9398
9399 if (doc == NULL)
9400 return (NULL);
9401
9402 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9403 if (ret == NULL) {
9404 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9405 NULL);
9406 return (NULL);
9407 }
9408 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9409 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009410 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00009411 /* The application has responsibility for the document */
9412 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00009413
9414 return (ret);
9415}
9416
9417/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009418 * xmlSchemaFreeParserCtxt:
9419 * @ctxt: the schema parser context
9420 *
9421 * Free the resources associated to the schema parser context
9422 */
9423void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009424xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
9425{
Daniel Veillard4255d502002-04-16 15:50:10 +00009426 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009427 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00009428 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009429 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009430 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009431 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009432 xmlFree(ctxt->assemble);
9433 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009434 if (ctxt->vctxt != NULL) {
9435 xmlSchemaFreeValidCtxt(ctxt->vctxt);
9436 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009437 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00009438 xmlFree(ctxt);
9439}
9440
9441/************************************************************************
9442 * *
9443 * Building the content models *
9444 * *
9445 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009446
Daniel Veillard4255d502002-04-16 15:50:10 +00009447/**
9448 * xmlSchemaBuildAContentModel:
9449 * @type: the schema type definition
9450 * @ctxt: the schema parser context
9451 * @name: the element name whose content is being built
9452 *
9453 * Generate the automata sequence needed for that type
9454 */
9455static void
9456xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009457 xmlSchemaParserCtxtPtr ctxt,
9458 const xmlChar * name)
9459{
Daniel Veillard4255d502002-04-16 15:50:10 +00009460 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009461 xmlGenericError(xmlGenericErrorContext,
9462 "Found unexpected type = NULL in %s content model\n",
9463 name);
9464 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009465 }
9466 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009467 case XML_SCHEMA_TYPE_ANY: {
9468 xmlAutomataStatePtr start, end;
9469 xmlSchemaWildcardPtr wild;
9470 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00009471
Daniel Veillardc0826a72004-08-10 14:17:33 +00009472 wild = type->attributeWildcard;
9473
9474 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009475 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009476 "Internal error: xmlSchemaBuildAContentModel, "
9477 "no wildcard on xsd:any.\n", NULL, NULL);
9478 return;
9479 }
9480
9481 start = ctxt->state;
9482 end = xmlAutomataNewState(ctxt->am);
9483
9484 if (type->maxOccurs == 1) {
9485 if (wild->any == 1) {
9486 /*
9487 * We need to add both transitions:
9488 *
9489 * 1. the {"*", "*"} for elements in a namespace.
9490 */
9491 ctxt->state =
9492 xmlAutomataNewTransition2(ctxt->am,
9493 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9494 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9495 /*
9496 * 2. the {"*"} for elements in no namespace.
9497 */
9498 ctxt->state =
9499 xmlAutomataNewTransition2(ctxt->am,
9500 start, NULL, BAD_CAST "*", NULL, type);
9501 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9502
9503 } else if (wild->nsSet != NULL) {
9504 ns = wild->nsSet;
9505 do {
9506 ctxt->state = start;
9507 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9508 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
9509 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9510 ns = ns->next;
9511 } while (ns != NULL);
9512
9513 } else if (wild->negNsSet != NULL) {
9514 xmlAutomataStatePtr deadEnd;
9515
9516 deadEnd = xmlAutomataNewState(ctxt->am);
9517 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9518 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9519 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9520 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9521 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9522 }
9523 } else {
9524 int counter;
9525 xmlAutomataStatePtr hop;
9526 int maxOccurs =
9527 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
9528 int minOccurs =
9529 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9530
9531 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9532 hop = xmlAutomataNewState(ctxt->am);
9533 if (wild->any == 1) {
9534 ctxt->state =
9535 xmlAutomataNewTransition2(ctxt->am,
9536 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9537 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9538 ctxt->state =
9539 xmlAutomataNewTransition2(ctxt->am,
9540 start, NULL, BAD_CAST "*", NULL, type);
9541 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9542 } else if (wild->nsSet != NULL) {
9543 ns = wild->nsSet;
9544 do {
9545 ctxt->state =
9546 xmlAutomataNewTransition2(ctxt->am,
9547 start, NULL, BAD_CAST "*", ns->value, type);
9548 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9549 ns = ns->next;
9550 } while (ns != NULL);
9551
9552 } else if (wild->negNsSet != NULL) {
9553 xmlAutomataStatePtr deadEnd;
9554
9555 deadEnd = xmlAutomataNewState(ctxt->am);
9556 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9557 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9558 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9559 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9560 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9561 }
9562 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
9563 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
9564 }
9565 if (type->minOccurs == 0) {
9566 xmlAutomataNewEpsilon(ctxt->am, start, end);
9567 }
9568 ctxt->state = end;
9569 break;
9570 }
9571 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009572 xmlAutomataStatePtr oldstate;
9573 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00009574
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009575 /*
9576 * IMPORTANT: This puts element declarations
9577 * (and never element decl. references) into the
9578 * automaton. This is crucial and should not be changed,
9579 * since validating functions rely now on it.
9580 */
9581 particle = (xmlSchemaElementPtr) type;
9582 if (particle->ref != NULL) {
9583 if (particle->refDecl == NULL) {
9584 /*
9585 * Skip content model creation if the reference
9586 * did not resolve to a declaration.
9587 */
9588 break;
9589 } else {
9590 /*
9591 * Referenced global element declaration.
9592 */
9593 elemDecl = particle->refDecl;
9594 }
9595 } else {
9596 /*
9597 * Anonymous element declaration.
9598 */
9599 elemDecl = particle;
9600 }
9601
9602 oldstate = ctxt->state;
9603
9604 if (particle->maxOccurs >= UNBOUNDED) {
9605 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009606 xmlAutomataStatePtr tmp;
9607 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009608
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009609 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009610 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009611 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009612 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009613 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00009614 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009615 xmlAutomataNewTransition2(ctxt->am,
9616 ctxt->state, NULL,
9617 elemDecl->name,
9618 elemDecl->targetNamespace,
9619 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009620 tmp = ctxt->state;
9621 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009622 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009623 ctxt->state =
9624 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009625 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00009626
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009627 } else {
9628 ctxt->state =
9629 xmlAutomataNewTransition2(ctxt->am,
9630 ctxt->state, NULL,
9631 elemDecl->name,
9632 elemDecl->targetNamespace,
9633 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009634 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9635 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009636 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009637 /* basically an elem* */
9638 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9639 ctxt->state);
9640 }
9641 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009642 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009643 xmlAutomataStatePtr tmp;
9644 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009645
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009646 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9647 oldstate, NULL);
9648 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009649 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009650 particle->minOccurs - 1,
9651 particle->maxOccurs - 1);
9652 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9653 ctxt->state,
9654 NULL,
9655 elemDecl->name,
9656 elemDecl->targetNamespace,
9657 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009658 tmp = ctxt->state;
9659 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009660 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009661 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009662 NULL, counter);
9663 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009664 /* basically an elem? */
9665 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009666 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009667 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00009668
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009669 } else {
9670 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9671 ctxt->state,
9672 NULL,
9673 elemDecl->name,
9674 elemDecl->targetNamespace,
9675 (xmlSchemaTypePtr) elemDecl);
9676 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009677 /* basically an elem? */
9678 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009679 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009680 }
9681 }
9682 break;
9683 }
9684 case XML_SCHEMA_TYPE_SEQUENCE:{
9685 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009686
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009687 /*
9688 * If max and min occurances are default (1) then
9689 * simply iterate over the subtypes
9690 */
9691 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
9692 subtypes = type->subtypes;
9693 while (subtypes != NULL) {
9694 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9695 subtypes = subtypes->next;
9696 }
9697 } else {
9698 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009699
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009700 if (type->maxOccurs >= UNBOUNDED) {
9701 if (type->minOccurs > 1) {
9702 xmlAutomataStatePtr tmp;
9703 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009704
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009705 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9706 oldstate,
9707 NULL);
9708 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009709
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009710 counter = xmlAutomataNewCounter(ctxt->am,
9711 type->
9712 minOccurs - 1,
9713 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009714
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009715 subtypes = type->subtypes;
9716 while (subtypes != NULL) {
9717 xmlSchemaBuildAContentModel(subtypes, ctxt,
9718 name);
9719 subtypes = subtypes->next;
9720 }
9721 tmp = ctxt->state;
9722 xmlAutomataNewCountedTrans(ctxt->am, tmp,
9723 oldstate, counter);
9724 ctxt->state =
9725 xmlAutomataNewCounterTrans(ctxt->am, tmp,
9726 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009727
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009728 } else {
9729 subtypes = type->subtypes;
9730 while (subtypes != NULL) {
9731 xmlSchemaBuildAContentModel(subtypes, ctxt,
9732 name);
9733 subtypes = subtypes->next;
9734 }
9735 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9736 oldstate);
9737 if (type->minOccurs == 0) {
9738 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9739 ctxt->state);
9740 }
9741 }
9742 } else if ((type->maxOccurs > 1)
9743 || (type->minOccurs > 1)) {
9744 xmlAutomataStatePtr tmp;
9745 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009746
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009747 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9748 oldstate,
9749 NULL);
9750 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00009751
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009752 counter = xmlAutomataNewCounter(ctxt->am,
9753 type->minOccurs -
9754 1,
9755 type->maxOccurs -
9756 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009757
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009758 subtypes = type->subtypes;
9759 while (subtypes != NULL) {
9760 xmlSchemaBuildAContentModel(subtypes, ctxt,
9761 name);
9762 subtypes = subtypes->next;
9763 }
9764 tmp = ctxt->state;
9765 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
9766 counter);
9767 ctxt->state =
9768 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
9769 counter);
9770 if (type->minOccurs == 0) {
9771 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9772 ctxt->state);
9773 }
Daniel Veillardb509f152002-04-17 16:28:10 +00009774
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009775 } else {
9776 subtypes = type->subtypes;
9777 while (subtypes != NULL) {
9778 xmlSchemaBuildAContentModel(subtypes, ctxt,
9779 name);
9780 subtypes = subtypes->next;
9781 }
9782 if (type->minOccurs == 0) {
9783 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9784 ctxt->state);
9785 }
9786 }
9787 }
9788 break;
9789 }
9790 case XML_SCHEMA_TYPE_CHOICE:{
9791 xmlSchemaTypePtr subtypes;
9792 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00009793
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009794 start = ctxt->state;
9795 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00009796
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009797 /*
9798 * iterate over the subtypes and remerge the end with an
9799 * epsilon transition
9800 */
9801 if (type->maxOccurs == 1) {
9802 subtypes = type->subtypes;
9803 while (subtypes != NULL) {
9804 ctxt->state = start;
9805 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9806 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9807 subtypes = subtypes->next;
9808 }
9809 } else {
9810 int counter;
9811 xmlAutomataStatePtr hop;
9812 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9813 UNBOUNDED : type->maxOccurs - 1;
9814 int minOccurs =
9815 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00009816
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009817 /*
9818 * use a counter to keep track of the number of transtions
9819 * which went through the choice.
9820 */
9821 counter =
9822 xmlAutomataNewCounter(ctxt->am, minOccurs,
9823 maxOccurs);
9824 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00009825
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009826 subtypes = type->subtypes;
9827 while (subtypes != NULL) {
9828 ctxt->state = start;
9829 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9830 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9831 subtypes = subtypes->next;
9832 }
9833 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9834 counter);
9835 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9836 counter);
9837 }
9838 if (type->minOccurs == 0) {
9839 xmlAutomataNewEpsilon(ctxt->am, start, end);
9840 }
9841 ctxt->state = end;
9842 break;
9843 }
9844 case XML_SCHEMA_TYPE_ALL:{
9845 xmlAutomataStatePtr start;
9846 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009847
Daniel Veillard3646d642004-06-02 19:19:14 +00009848 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009849 int lax;
9850
9851 subtypes = type->subtypes;
9852 if (subtypes == NULL)
9853 break;
9854 start = ctxt->state;
9855 while (subtypes != NULL) {
9856 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00009857 /*
9858 * the following 'if' was needed to fix bug 139897
9859 * not quite sure why it only needs to be done for
9860 * elements with a 'ref', but it seems to work ok.
9861 */
9862 if (subtypes->ref != NULL)
9863 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009864 elem = (xmlSchemaElementPtr) subtypes;
9865 /*
9866 * NOTE: The {max occurs} of all the particles in the
9867 * {particles} of the group must be 0 or 1.
9868 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009869 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009870 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
9871 ctxt->state,
9872 elem->name,
9873 elem->targetNamespace,
9874 1, 1, subtypes);
9875 } else if ((elem->minOccurs == 0) &&
9876 (elem->maxOccurs == 1)) {
9877
9878 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
9879 ctxt->state,
9880 elem->name,
9881 elem->targetNamespace,
9882 0,
9883 1,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009884 subtypes);
9885 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009886 /*
9887 * NOTE: if maxOccurs == 0 then no transition will be
9888 * created.
9889 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009890 subtypes = subtypes->next;
9891 }
9892 lax = type->minOccurs == 0;
9893 ctxt->state =
9894 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
9895 lax);
9896 break;
9897 }
9898 case XML_SCHEMA_TYPE_RESTRICTION:
9899 if (type->subtypes != NULL)
9900 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9901 break;
9902 case XML_SCHEMA_TYPE_EXTENSION:
9903 if (type->baseType != NULL) {
9904 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009905
9906 /*
9907 * TODO: Circular definitions will be checked at the
9908 * constraint level. So remove this when the complex type
9909 * constraints are implemented.
9910 */
Daniel Veillardf7627552004-04-22 07:15:40 +00009911 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009912 /* TODO: Change the error code. */
9913 xmlSchemaPCustomErr(ctxt,
9914 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
9915 NULL, type, type->node,
9916 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00009917 return;
9918 }
9919 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009920 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00009921 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009922 subtypes = type->subtypes;
9923 while (subtypes != NULL) {
9924 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9925 subtypes = subtypes->next;
9926 }
9927 } else if (type->subtypes != NULL)
9928 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9929 break;
9930 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00009931 /*
9932 * Handle model group definition references.
9933 * NOTE: type->subtypes is the referenced model grop definition;
9934 * and type->subtypes->subtypes is the model group (i.e. <all> or
9935 * <choice> or <sequence>).
9936 */
9937 if ((type->ref != NULL) && (type->subtypes != NULL) &&
9938 (type->subtypes->subtypes != NULL)) {
9939 xmlSchemaTypePtr modelGr;
9940 xmlAutomataStatePtr start, end;
9941
9942 modelGr = type->subtypes->subtypes;
9943 start = ctxt->state;
9944 end = xmlAutomataNewState(ctxt->am);
9945 if (type->maxOccurs == 1) {
9946 ctxt->state = start;
9947 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9948 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9949 } else {
9950 int counter;
9951 xmlAutomataStatePtr hop;
9952 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9953 UNBOUNDED : type->maxOccurs - 1;
9954 int minOccurs =
9955 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9956
9957 counter =
9958 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9959 hop = xmlAutomataNewState(ctxt->am);
9960 ctxt->state = start;
9961 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9962 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9963 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9964 counter);
9965 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9966 counter);
9967 }
9968 if (type->minOccurs == 0) {
9969 xmlAutomataNewEpsilon(ctxt->am, start, end);
9970 }
9971 ctxt->state = end;
9972 break;
9973 }
9974 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009975 case XML_SCHEMA_TYPE_COMPLEX:
9976 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
9977 if (type->subtypes != NULL)
9978 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9979 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00009980 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
9981 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009982 default:
9983 xmlGenericError(xmlGenericErrorContext,
9984 "Found unexpected type %d in %s content model\n",
9985 type->type, name);
9986 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009987 }
9988}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009989
Daniel Veillard4255d502002-04-16 15:50:10 +00009990/**
9991 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009992 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +00009993 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009994 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00009995 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009996 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +00009997 */
9998static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009999xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010000 xmlSchemaParserCtxtPtr ctxt,
10001 const xmlChar * name)
10002{
Daniel Veillard4255d502002-04-16 15:50:10 +000010003 xmlAutomataStatePtr start;
10004
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010005 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
10006 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
10007 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
10008 (type->contModel != NULL))
10009 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010010
10011#ifdef DEBUG_CONTENT
10012 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010013 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010014#endif
10015
Daniel Veillard4255d502002-04-16 15:50:10 +000010016 ctxt->am = xmlNewAutomata();
10017 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010018 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010019 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010020 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010021 }
10022 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010023 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000010024 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010025 type->contModel = xmlAutomataCompile(ctxt->am);
10026 if (type->contModel == NULL) {
10027 xmlSchemaPCustomErr(ctxt,
10028 XML_SCHEMAP_INTERNAL,
10029 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010030 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010031 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010032 xmlSchemaPCustomErr(ctxt,
10033 XML_SCHEMAP_NOT_DETERMINISTIC,
10034 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010035 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010036 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000010037 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000010038#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010039 xmlGenericError(xmlGenericErrorContext,
10040 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010041 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000010042#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000010043 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000010044 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000010045 xmlFreeAutomata(ctxt->am);
10046 ctxt->am = NULL;
10047}
10048
10049/**
10050 * xmlSchemaRefFixupCallback:
10051 * @elem: the schema element context
10052 * @ctxt: the schema parser context
10053 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000010054 * Resolves the references of an element declaration
10055 * or particle, which has an element declaration as it's
10056 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000010057 */
10058static void
10059xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010060 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010061 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010062 const xmlChar * context ATTRIBUTE_UNUSED,
10063 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000010064{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010065 if ((ctxt == NULL) || (elem == NULL) ||
10066 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010067 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010068 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000010069 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010070 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +000010071
Daniel Veillardc0826a72004-08-10 14:17:33 +000010072 /*
10073 * TODO: Evaluate, what errors could occur if the declaration is not
10074 * found. It might be possible that the "typefixup" might crash if
10075 * no ref declaration was found.
10076 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010077 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010078 if (elemDecl == NULL) {
10079 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010080 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010081 NULL, (xmlSchemaTypePtr) elem, elem->node,
10082 "ref", elem->ref, elem->refNs,
10083 XML_SCHEMA_TYPE_ELEMENT, NULL);
10084 } else
10085 elem->refDecl = elemDecl;
10086 } else {
10087 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
10088 xmlSchemaTypePtr type;
10089
10090 /* (type definition) ... otherwise the type definition ·resolved·
10091 * to by the ·actual value· of the type [attribute] ...
10092 */
10093 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
10094 elem->namedTypeNs);
10095 if (type == NULL) {
10096 xmlSchemaPResCompAttrErr(ctxt,
10097 XML_SCHEMAP_SRC_RESOLVE,
10098 NULL, (xmlSchemaTypePtr) elem, elem->node,
10099 "type", elem->namedType, elem->namedTypeNs,
10100 XML_SCHEMA_TYPE_BASIC, "type definition");
10101 } else
10102 elem->subtypes = type;
10103 }
10104 if (elem->substGroup != NULL) {
10105 xmlSchemaElementPtr substHead;
10106
10107 /*
10108 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
10109 * substitutionGroup?
10110 */
10111 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010112 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010113 if (substHead == NULL) {
10114 xmlSchemaPResCompAttrErr(ctxt,
10115 XML_SCHEMAP_SRC_RESOLVE,
10116 NULL, (xmlSchemaTypePtr) elem, NULL,
10117 "substitutionGroup", elem->substGroup, elem->substGroupNs,
10118 XML_SCHEMA_TYPE_ELEMENT, NULL);
10119 } else {
10120 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
10121 /*
10122 * (type definition)...otherwise the {type definition} of the
10123 * element declaration ·resolved· to by the ·actual value· of
10124 * the substitutionGroup [attribute], if present
10125 */
10126 if (elem->subtypes == NULL)
10127 elem->subtypes = substHead->subtypes;
10128 }
10129 }
10130 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
10131 (elem->substGroup == NULL))
10132 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10133 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010134}
10135
William M. Bracke7091952004-05-11 15:09:58 +000010136/**
10137 * xmlSchemaParseListRefFixup:
10138 * @type: the schema type definition
10139 * @ctxt: the schema parser context
10140 *
10141 * Fixup of the itemType reference of the list type.
10142 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010143static void
William M. Bracke7091952004-05-11 15:09:58 +000010144xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010145{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010146
Daniel Veillard01fa6152004-06-29 17:04:39 +000010147 if (((type->base == NULL) &&
10148 (type->subtypes == NULL)) ||
10149 ((type->base != NULL) &&
10150 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010151 /*
10152 * src-list-itemType-or-simpleType
10153 * Either the itemType [attribute] or the <simpleType> [child] of
10154 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010155 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010156 /*
10157 * TODO: Move this to the parse function.
10158 */
10159 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010160 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010161 NULL, type, type->node,
10162 "The attribute 'itemType' and the <simpleType> child "
10163 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010164 } else if (type->base!= NULL) {
10165 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
10166 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010167 xmlSchemaPResCompAttrErr(ctxt,
10168 XML_SCHEMAP_SRC_RESOLVE,
10169 NULL, type, type->node,
10170 "itemType", type->base, type->baseNs,
10171 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010172 }
10173 }
10174 if ((type->subtypes != NULL) &&
10175 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
10176 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +000010177}
10178
10179/**
10180 * xmlSchemaParseUnionRefCheck:
10181 * @typeDecl: the schema type definition
10182 * @ctxt: the schema parser context
10183 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000010184 * Checks and builds the memberTypes of the union type.
10185 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000010186 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010187static int
William M. Bracke7091952004-05-11 15:09:58 +000010188xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +000010189 xmlSchemaParserCtxtPtr ctxt)
10190{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010191
Daniel Veillard01fa6152004-06-29 17:04:39 +000010192 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
10193 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000010194
Daniel Veillard01fa6152004-06-29 17:04:39 +000010195 /* 1 If the <union> alternative is chosen, then [Definition:]
10196 * define the explicit members as the type definitions ·resolved·
10197 * to by the items in the ·actual value· of the memberTypes [attribute],
10198 * if any, followed by the type definitions corresponding to the
10199 * <simpleType>s among the [children] of <union>, if any.
10200 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010201
Daniel Veillard01fa6152004-06-29 17:04:39 +000010202 if (type->type != XML_SCHEMA_TYPE_UNION)
10203 return (-1);
10204 if (ctxt->ctxtType == NULL) {
10205 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010206 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010207 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
10208 "available", NULL, NULL);
10209 return (-1);
10210 }
10211 /*
10212 * src-union-memberTypes-or-simpleTypes
10213 * Either the memberTypes [attribute] of the <union> element must
10214 * be non-empty or there must be at least one simpleType [child].
10215 */
10216 if ((type->base == NULL) &&
10217 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010218 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010219 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010220 NULL, NULL, type->node,
10221 "Either the attribute 'memberTypes' must be non-empty "
10222 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010223 }
10224
10225 ctxtType = ctxt->ctxtType;
10226 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010227 xmlAttrPtr attr;
10228 const xmlChar *cur, *end;
10229 xmlChar *tmp;
10230 const xmlChar *localName, *uri;
10231
10232 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010233 cur = type->base;
10234 do {
10235 while (IS_BLANK_CH(*cur))
10236 cur++;
10237 end = cur;
10238 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
10239 end++;
10240 if (end == cur)
10241 break;
10242 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010243 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
10244 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
10245 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010246 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010247 xmlSchemaPResCompAttrErr(ctxt,
10248 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
10249 NULL, NULL, type->node, "memberTypes", localName, uri,
10250 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010251 } else {
10252 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10253 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10254 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10255 if (link == NULL) {
10256 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10257 return (-1);
10258 }
10259 link->type = memberType;
10260 link->next = NULL;
10261 if (lastLink == NULL)
10262 ctxtType->memberTypes = link;
10263 else
10264 lastLink->next = link;
10265 lastLink = link;
10266 }
10267 xmlFree(tmp);
10268 cur = end;
10269 } while (*cur != 0);
10270 }
10271 /*
10272 * Add local simple types,
10273 */
10274 memberType = type->subtypes;
10275 while (memberType != NULL) {
10276 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10277 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10278 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10279 if (link == NULL) {
10280 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10281 return (-1);
10282 }
10283 link->type = memberType;
10284 link->next = NULL;
10285 if (lastLink == NULL)
10286 ctxtType->memberTypes = link;
10287 else
10288 lastLink->next = link;
10289 lastLink = link;
10290 memberType = memberType->next;
10291 }
10292 /*
10293 * The actual value is then formed by replacing any union type
10294 * definition in the ·explicit members· with the members of their
10295 * {member type definitions}, in order.
10296 */
10297 link = ctxtType->memberTypes;
10298 while (link != NULL) {
10299 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10300 subLink = link->type->memberTypes;
10301 if (subLink != NULL) {
10302 link->type = subLink->type;
10303 if (subLink->next != NULL) {
10304 lastLink = link->next;
10305 subLink = subLink->next;
10306 prevLink = link;
10307 while (subLink != NULL) {
10308 newLink = (xmlSchemaTypeLinkPtr)
10309 xmlMalloc(sizeof(xmlSchemaTypeLink));
10310 if (newLink == NULL) {
10311 xmlSchemaPErrMemory(ctxt, "allocating a type link",
10312 NULL);
10313 return (-1);
10314 }
10315 newLink->type = memberType;
10316 prevLink->next = newLink;
10317 prevLink = newLink;
10318 newLink->next = lastLink;
10319
10320 subLink = subLink->next;
10321 }
10322 }
10323 }
10324 }
10325 link = link->next;
10326 }
10327
10328 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000010329}
10330
Daniel Veillard4255d502002-04-16 15:50:10 +000010331/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010332 * xmlSchemaIsDerivedFromBuiltInType:
10333 * @ctxt: the schema parser context
10334 * @type: the type definition
10335 * @valType: the value type
10336 *
10337 *
10338 * Returns 1 if the type has the given value type, or
10339 * is derived from such a type.
10340 */
William M. Brack803812b2004-06-03 02:11:24 +000010341static int
Daniel Veillard3646d642004-06-02 19:19:14 +000010342xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
10343 xmlSchemaTypePtr type, int valType)
10344{
10345 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010346 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000010347 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010348 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000010349 return(1);
10350 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
10351 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
10352 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
10353 ((xmlSchemaAttributePtr) type)->subtypes, valType));
10354 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
10355 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
10356 if (type->baseType != NULL)
10357 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
10358 valType));
10359 } else if ((type->subtypes != NULL) &&
10360 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
10361 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10362 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
10363 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
10364 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
10365 valType));
10366 }
10367
10368 return (0);
10369}
10370
10371/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010372 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000010373 * @type: the simpleType definition
10374 *
10375 * Returns the primitive type of the given type or
10376 * NULL in case of error.
10377 */
10378static xmlSchemaTypePtr
10379xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
10380{
10381 while (type != NULL) {
10382 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
10383 return (type);
10384 type = type->baseType;
10385 }
10386
10387 return (NULL);
10388}
10389
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010390/**
10391 * xmlSchemaGetBuiltInTypeAncestor:
10392 * @type: the simpleType definition
10393 *
10394 * Returns the primitive type of the given type or
10395 * NULL in case of error.
10396 */
10397static xmlSchemaTypePtr
10398xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
10399{
10400 while (type != NULL) {
10401 if (type->type == XML_SCHEMA_TYPE_BASIC)
10402 return (type);
10403 type = type->baseType;
10404 }
10405
10406 return (NULL);
10407}
10408
Daniel Veillard01fa6152004-06-29 17:04:39 +000010409
10410/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010411 * xmlSchemaBuildAttributeUsesOwned:
10412 * @ctxt: the schema parser context
10413 * @type: the complex type definition
10414 * @cur: the attribute declaration list
10415 * @lastUse: the top of the attribute use list
10416 *
10417 * Builds the attribute uses list on the given complex type.
10418 * This one is supposed to be called by
10419 * xmlSchemaBuildAttributeValidation only.
10420 */
10421static int
10422xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
10423 xmlSchemaAttributePtr cur,
10424 xmlSchemaAttributeLinkPtr *uses,
10425 xmlSchemaAttributeLinkPtr *lastUse)
10426{
10427 xmlSchemaAttributeLinkPtr tmp;
10428 while (cur != NULL) {
10429 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10430 /*
10431 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
10432 * to by the ·actual value·s of the ref [attribute] of the
10433 * <attributeGroup> [children], if any."
10434 */
10435 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
10436 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
10437 lastUse) == -1) {
10438 return (-1);
10439 }
10440 } else {
10441 /* W3C: "1 The set of attribute uses corresponding to the
10442 * <attribute> [children], if any."
10443 */
10444 tmp = (xmlSchemaAttributeLinkPtr)
10445 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10446 if (tmp == NULL) {
10447 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
10448 return (-1);
10449 }
10450 tmp->attr = cur;
10451 tmp->next = NULL;
10452 if (*uses == NULL)
10453 *uses = tmp;
10454 else
10455 (*lastUse)->next = tmp;
10456 *lastUse = tmp;
10457 }
10458 cur = cur->next;
10459 }
10460 return (0);
10461}
10462
Daniel Veillard50355f02004-06-08 17:52:16 +000010463/**
10464 * xmlSchemaCloneWildcardNsConstraints:
10465 * @ctxt: the schema parser context
10466 * @dest: the destination wildcard
10467 * @source: the source wildcard
10468 *
10469 * Clones the namespace constraints of source
10470 * and assignes them to dest.
10471 * Returns -1 on internal error, 0 otherwise.
10472 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010473static int
10474xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
10475 xmlSchemaWildcardPtr *dest,
10476 xmlSchemaWildcardPtr source)
10477{
10478 xmlSchemaWildcardNsPtr cur, tmp, last;
10479
10480 if ((source == NULL) || (*dest == NULL))
10481 return(-1);
10482 (*dest)->any = source->any;
10483 cur = source->nsSet;
10484 last = NULL;
10485 while (cur != NULL) {
10486 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10487 if (tmp == NULL)
10488 return(-1);
10489 tmp->value = cur->value;
10490 if (last == NULL)
10491 (*dest)->nsSet = tmp;
10492 else
10493 last->next = tmp;
10494 last = tmp;
10495 cur = cur->next;
10496 }
10497 if ((*dest)->negNsSet != NULL)
10498 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
10499 if (source->negNsSet != NULL) {
10500 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10501 if ((*dest)->negNsSet == NULL)
10502 return(-1);
10503 (*dest)->negNsSet->value = source->negNsSet->value;
10504 } else
10505 (*dest)->negNsSet = NULL;
10506 return(0);
10507}
10508
Daniel Veillard50355f02004-06-08 17:52:16 +000010509/**
10510 * xmlSchemaUnionWildcards:
10511 * @ctxt: the schema parser context
10512 * @completeWild: the first wildcard
10513 * @curWild: the second wildcard
10514 *
10515 * Unions the namespace constraints of the given wildcards.
10516 * @completeWild will hold the resulting union.
10517 * Returns a positive error code on failure, -1 in case of an
10518 * internal error, 0 otherwise.
10519 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010520static int
10521xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
10522 xmlSchemaWildcardPtr completeWild,
10523 xmlSchemaWildcardPtr curWild)
10524{
10525 xmlSchemaWildcardNsPtr cur, curB, tmp;
10526
10527 /*
10528 * 1 If O1 and O2 are the same value, then that value must be the
10529 * value.
10530 */
10531 if ((completeWild->any == curWild->any) &&
10532 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10533 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10534
10535 if ((completeWild->negNsSet == NULL) ||
10536 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10537
10538 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010539 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010540
10541 /*
10542 * Check equality of sets.
10543 */
10544 cur = completeWild->nsSet;
10545 while (cur != NULL) {
10546 found = 0;
10547 curB = curWild->nsSet;
10548 while (curB != NULL) {
10549 if (cur->value == curB->value) {
10550 found = 1;
10551 break;
10552 }
10553 curB = curB->next;
10554 }
10555 if (!found)
10556 break;
10557 cur = cur->next;
10558 }
10559 if (found)
10560 return(0);
10561 } else
10562 return(0);
10563 }
10564 }
10565 /*
10566 * 2 If either O1 or O2 is any, then any must be the value
10567 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010568 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010569 if (completeWild->any == 0) {
10570 completeWild->any = 1;
10571 if (completeWild->nsSet != NULL) {
10572 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10573 completeWild->nsSet = NULL;
10574 }
10575 if (completeWild->negNsSet != NULL) {
10576 xmlFree(completeWild->negNsSet);
10577 completeWild->negNsSet = NULL;
10578 }
10579 }
Daniel Veillard50355f02004-06-08 17:52:16 +000010580 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010581 }
10582 /*
10583 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
10584 * then the union of those sets must be the value.
10585 */
10586 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10587 int found;
10588 xmlSchemaWildcardNsPtr start;
10589
10590 cur = curWild->nsSet;
10591 start = completeWild->nsSet;
10592 while (cur != NULL) {
10593 found = 0;
10594 curB = start;
10595 while (curB != NULL) {
10596 if (cur->value == curB->value) {
10597 found = 1;
10598 break;
10599 }
10600 curB = curB->next;
10601 }
10602 if (!found) {
10603 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10604 if (tmp == NULL)
10605 return (-1);
10606 tmp->value = cur->value;
10607 tmp->next = completeWild->nsSet;
10608 completeWild->nsSet = tmp;
10609 }
10610 cur = cur->next;
10611 }
10612
10613 return(0);
10614 }
10615 /*
10616 * 4 If the two are negations of different values (namespace names
10617 * or ·absent·), then a pair of not and ·absent· must be the value.
10618 */
10619 if ((completeWild->negNsSet != NULL) &&
10620 (curWild->negNsSet != NULL) &&
10621 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
10622 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000010623
10624 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010625 }
10626 /*
10627 * 5.
10628 */
10629 if (((completeWild->negNsSet != NULL) &&
10630 (completeWild->negNsSet->value != NULL) &&
10631 (curWild->nsSet != NULL)) ||
10632 ((curWild->negNsSet != NULL) &&
10633 (curWild->negNsSet->value != NULL) &&
10634 (completeWild->nsSet != NULL))) {
10635
10636 int nsFound, absentFound = 0;
10637
10638 if (completeWild->nsSet != NULL) {
10639 cur = completeWild->nsSet;
10640 curB = curWild->negNsSet;
10641 } else {
10642 cur = curWild->nsSet;
10643 curB = completeWild->negNsSet;
10644 }
10645 nsFound = 0;
10646 while (cur != NULL) {
10647 if (cur->value == NULL)
10648 absentFound = 1;
10649 else if (cur->value == curB->value)
10650 nsFound = 1;
10651 if (nsFound && absentFound)
10652 break;
10653 cur = cur->next;
10654 }
10655
10656 if (nsFound && absentFound) {
10657 /*
10658 * 5.1 If the set S includes both the negated namespace
10659 * name and ·absent·, then any must be the value.
10660 */
10661 completeWild->any = 1;
10662 if (completeWild->nsSet != NULL) {
10663 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10664 completeWild->nsSet = NULL;
10665 }
10666 if (completeWild->negNsSet != NULL) {
10667 xmlFree(completeWild->negNsSet);
10668 completeWild->negNsSet = NULL;
10669 }
10670 } else if (nsFound && (!absentFound)) {
10671 /*
10672 * 5.2 If the set S includes the negated namespace name
10673 * but not ·absent·, then a pair of not and ·absent· must
10674 * be the value.
10675 */
10676 if (completeWild->nsSet != NULL) {
10677 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10678 completeWild->nsSet = NULL;
10679 }
10680 if (completeWild->negNsSet == NULL) {
10681 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10682 if (completeWild->negNsSet == NULL)
10683 return (-1);
10684 }
10685 completeWild->negNsSet->value = NULL;
10686 } else if ((!nsFound) && absentFound) {
10687 /*
10688 * 5.3 If the set S includes ·absent· but not the negated
10689 * namespace name, then the union is not expressible.
10690 */
10691 xmlSchemaPErr(ctxt, completeWild->node,
10692 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010693 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010694 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010695 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010696 } else if ((!nsFound) && (!absentFound)) {
10697 /*
10698 * 5.4 If the set S does not include either the negated namespace
10699 * name or ·absent·, then whichever of O1 or O2 is a pair of not
10700 * and a namespace name must be the value.
10701 */
10702 if (completeWild->negNsSet == NULL) {
10703 if (completeWild->nsSet != NULL) {
10704 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10705 completeWild->nsSet = NULL;
10706 }
10707 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10708 if (completeWild->negNsSet == NULL)
10709 return (-1);
10710 completeWild->negNsSet->value = curWild->negNsSet->value;
10711 }
10712 }
10713 return (0);
10714 }
10715 /*
10716 * 6.
10717 */
10718 if (((completeWild->negNsSet != NULL) &&
10719 (completeWild->negNsSet->value == NULL) &&
10720 (curWild->nsSet != NULL)) ||
10721 ((curWild->negNsSet != NULL) &&
10722 (curWild->negNsSet->value == NULL) &&
10723 (completeWild->nsSet != NULL))) {
10724
10725 if (completeWild->nsSet != NULL) {
10726 cur = completeWild->nsSet;
10727 } else {
10728 cur = curWild->nsSet;
10729 }
10730 while (cur != NULL) {
10731 if (cur->value == NULL) {
10732 /*
10733 * 6.1 If the set S includes ·absent·, then any must be the
10734 * value.
10735 */
10736 completeWild->any = 1;
10737 if (completeWild->nsSet != NULL) {
10738 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10739 completeWild->nsSet = NULL;
10740 }
10741 if (completeWild->negNsSet != NULL) {
10742 xmlFree(completeWild->negNsSet);
10743 completeWild->negNsSet = NULL;
10744 }
10745 return (0);
10746 }
10747 cur = cur->next;
10748 }
10749 if (completeWild->negNsSet == NULL) {
10750 /*
10751 * 6.2 If the set S does not include ·absent·, then a pair of not
10752 * and ·absent· must be the value.
10753 */
10754 if (completeWild->nsSet != NULL) {
10755 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10756 completeWild->nsSet = NULL;
10757 }
10758 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10759 if (completeWild->negNsSet == NULL)
10760 return (-1);
10761 completeWild->negNsSet->value = NULL;
10762 }
10763 return (0);
10764 }
10765 return (0);
10766
10767}
10768
Daniel Veillard50355f02004-06-08 17:52:16 +000010769/**
10770 * xmlSchemaIntersectWildcards:
10771 * @ctxt: the schema parser context
10772 * @completeWild: the first wildcard
10773 * @curWild: the second wildcard
10774 *
10775 * Intersects the namespace constraints of the given wildcards.
10776 * @completeWild will hold the resulting intersection.
10777 * Returns a positive error code on failure, -1 in case of an
10778 * internal error, 0 otherwise.
10779 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010780static int
10781xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
10782 xmlSchemaWildcardPtr completeWild,
10783 xmlSchemaWildcardPtr curWild)
10784{
William M. Brack803812b2004-06-03 02:11:24 +000010785 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010786
10787 /*
10788 * 1 If O1 and O2 are the same value, then that value must be the
10789 * value.
10790 */
10791 if ((completeWild->any == curWild->any) &&
10792 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10793 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10794
10795 if ((completeWild->negNsSet == NULL) ||
10796 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10797
10798 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010799 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010800
10801 /*
10802 * Check equality of sets.
10803 */
10804 cur = completeWild->nsSet;
10805 while (cur != NULL) {
10806 found = 0;
10807 curB = curWild->nsSet;
10808 while (curB != NULL) {
10809 if (cur->value == curB->value) {
10810 found = 1;
10811 break;
10812 }
10813 curB = curB->next;
10814 }
10815 if (!found)
10816 break;
10817 cur = cur->next;
10818 }
10819 if (found)
10820 return(0);
10821 } else
10822 return(0);
10823 }
10824 }
10825 /*
10826 * 2 If either O1 or O2 is any, then the other must be the value.
10827 */
10828 if ((completeWild->any != curWild->any) && (completeWild->any)) {
10829 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10830 return(-1);
10831 return(0);
10832 }
10833 /*
10834 * 3 If either O1 or O2 is a pair of not and a value (a namespace
10835 * name or ·absent·) and the other is a set of (namespace names or
10836 * ·absent·), then that set, minus the negated value if it was in
10837 * the set, minus ·absent· if it was in the set, must be the value.
10838 */
10839 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
10840 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
10841 const xmlChar *neg;
10842
10843 if (completeWild->nsSet == NULL) {
10844 neg = completeWild->negNsSet->value;
10845 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10846 return(-1);
10847 } else
10848 neg = curWild->negNsSet->value;
10849 /*
10850 * Remove absent and negated.
10851 */
10852 prev = NULL;
10853 cur = completeWild->nsSet;
10854 while (cur != NULL) {
10855 if (cur->value == NULL) {
10856 if (prev == NULL)
10857 completeWild->nsSet = cur->next;
10858 else
10859 prev->next = cur->next;
10860 xmlFree(cur);
10861 break;
10862 }
10863 prev = cur;
10864 cur = cur->next;
10865 }
10866 if (neg != NULL) {
10867 prev = NULL;
10868 cur = completeWild->nsSet;
10869 while (cur != NULL) {
10870 if (cur->value == neg) {
10871 if (prev == NULL)
10872 completeWild->nsSet = cur->next;
10873 else
10874 prev->next = cur->next;
10875 xmlFree(cur);
10876 break;
10877 }
10878 prev = cur;
10879 cur = cur->next;
10880 }
10881 }
10882
10883 return(0);
10884 }
10885 /*
10886 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
10887 * then the intersection of those sets must be the value.
10888 */
10889 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10890 int found;
10891
10892 cur = completeWild->nsSet;
10893 prev = NULL;
10894 while (cur != NULL) {
10895 found = 0;
10896 curB = curWild->nsSet;
10897 while (curB != NULL) {
10898 if (cur->value == curB->value) {
10899 found = 1;
10900 break;
10901 }
10902 curB = curB->next;
10903 }
10904 if (!found) {
10905 if (prev == NULL)
10906 completeWild->nsSet = cur->next;
10907 else
10908 prev->next = cur->next;
10909 tmp = cur->next;
10910 xmlFree(cur);
10911 cur = tmp;
10912 continue;
10913 }
10914 prev = cur;
10915 cur = cur->next;
10916 }
10917
10918 return(0);
10919 }
10920 /* 5 If the two are negations of different namespace names,
10921 * then the intersection is not expressible
10922 */
10923 if ((completeWild->negNsSet != NULL) &&
10924 (curWild->negNsSet != NULL) &&
10925 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
10926 (completeWild->negNsSet->value != NULL) &&
10927 (curWild->negNsSet->value != NULL)) {
10928
10929 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010930 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010931 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010932 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010933 }
10934 /*
10935 * 6 If the one is a negation of a namespace name and the other
10936 * is a negation of ·absent·, then the one which is the negation
10937 * of a namespace name must be the value.
10938 */
10939 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
10940 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
10941 (completeWild->negNsSet->value == NULL)) {
10942 completeWild->negNsSet->value = curWild->negNsSet->value;
10943 }
10944 return(0);
10945}
10946
Daniel Veillard50355f02004-06-08 17:52:16 +000010947/**
10948 * xmlSchemaIsWildcardNsConstraintSubset:
10949 * @ctxt: the schema parser context
10950 * @wildA: the first wildcard
10951 * @wildB: the second wildcard
10952 *
10953 * Returns 1 if the namespace constraint of @wildA is an intensional
10954 * subset of @wildB, 0 otherwise.
10955 */
10956static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000010957xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
10958 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000010959{
Daniel Veillard3646d642004-06-02 19:19:14 +000010960
Daniel Veillard50355f02004-06-08 17:52:16 +000010961 /*
10962 * Schema Component Constraint: Wildcard Subset
10963 */
10964 /*
10965 * 1 super must be any.
10966 */
10967 if (wildB->any)
10968 return (1);
10969 /*
10970 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
10971 * 2.2 super must be a pair of not and the same value.
10972 */
10973 if ((wildA->negNsSet != NULL) &&
10974 (wildB->negNsSet != NULL) &&
10975 (wildA->negNsSet->value == wildA->negNsSet->value))
10976 return (1);
10977 /*
10978 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
10979 */
10980 if (wildA->nsSet != NULL) {
10981 /*
10982 * 3.2.1 super must be the same set or a superset thereof.
10983 */
10984 if (wildB->nsSet != NULL) {
10985 xmlSchemaWildcardNsPtr cur, curB;
10986 int found = 0;
10987
10988 cur = wildA->nsSet;
10989 while (cur != NULL) {
10990 found = 0;
10991 curB = wildB->nsSet;
10992 while (curB != NULL) {
10993 if (cur->value == curB->value) {
10994 found = 1;
10995 break;
10996 }
10997 curB = curB->next;
10998 }
10999 if (!found)
11000 return (0);
11001 cur = cur->next;
11002 }
11003 if (found)
11004 return (1);
11005 } else if (wildB->negNsSet != NULL) {
11006 xmlSchemaWildcardNsPtr cur;
11007 /*
11008 * 3.2.2 super must be a pair of not and a namespace name or
11009 * ·absent· and that value must not be in sub's set.
11010 */
11011 cur = wildA->nsSet;
11012 while (cur != NULL) {
11013 if (cur->value == wildB->negNsSet->value)
11014 return (0);
11015 cur = cur->next;
11016 }
11017 return (1);
11018 }
11019 }
11020 return (0);
11021}
11022
11023/**
11024 * xmlSchemaBuildCompleteAttributeWildcard:
11025 * @ctxt: the schema parser context
11026 * @attrs: the attribute list
11027 * @completeWild: the resulting complete wildcard
11028 *
11029 * Returns -1 in case of an internal error, 0 otherwise.
11030 */
11031static int
11032xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
11033 xmlSchemaAttributePtr attrs,
11034 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000011035{
11036 while (attrs != NULL) {
11037 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
11038 xmlSchemaAttributeGroupPtr group;
11039
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011040 group = (xmlSchemaAttributeGroupPtr) attrs;
11041 /*
11042 * Handle attribute group references.
11043 */
11044 if (group->ref != NULL) {
11045 if (group->refItem == NULL) {
11046 /*
11047 * TODO: Should we raise a warning here?
11048 */
11049 /*
11050 * The referenced attribute group definition could not
11051 * be resolved beforehand, so skip.
11052 */
11053 attrs = attrs->next;
11054 continue;
11055 } else
11056 group = group->refItem;
11057 }
11058 /*
11059 * For every attribute group definition, an intersected wildcard
11060 * will be created (assumed that a wildcard exists on the
11061 * particular attr. gr. def. or on any contained attr. gr. def
11062 * at all).
11063 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
11064 * that the intersection will be performed only once.
11065 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011066 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
11067 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000011068 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11069 group->attributes, &group->attributeWildcard) == -1)
11070 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011071 }
11072 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
11073 }
11074 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000011075 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011076 /*
11077 * Copy the first encountered wildcard as context, except for the annotation.
11078 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011079 *completeWild = xmlSchemaAddWildcard(ctxt);
11080 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
11081 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
11082 completeWild, group->attributeWildcard) == -1)
11083 return (-1);
11084 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000011085 /*
11086 * Although the complete wildcard might not correspond to any
11087 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011088 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000011089 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011090 (*completeWild)->node = group->attributeWildcard->node;
11091
11092 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
11093 xmlSchemaFreeWildcard(*completeWild);
11094 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011095 }
11096 }
11097 }
11098 attrs = attrs->next;
11099 }
11100
Daniel Veillard50355f02004-06-08 17:52:16 +000011101 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011102}
11103
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011104static int
11105xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
11106 int *fixed,
11107 const xmlChar **value,
11108 xmlSchemaValPtr *val)
11109{
11110 *fixed = 0;
11111 *value = NULL;
11112 if (val != 0)
11113 *val = NULL;
11114
11115 if (item->defValue == NULL)
11116 item = item->refDecl;
11117
11118 if (item == NULL)
11119 return (0);
11120
11121 if (item->defValue != NULL) {
11122 *value = item->defValue;
11123 if (val != 0)
11124 *val = item->defVal;
11125 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
11126 *fixed = 1;
11127 return (1);
11128 }
11129 return (0);
11130}
Daniel Veillard3646d642004-06-02 19:19:14 +000011131/**
11132 * xmlSchemaMatchesWildcardNs:
11133 * @wild: the wildcard
11134 * @ns: the namespace
11135 *
11136 *
11137 * Returns 1 if the given namespace matches the wildcard,
11138 * 0 otherwise.
11139 */
11140static int
11141xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
11142{
11143 if (wild == NULL)
11144 return(0);
11145
11146 if (wild->any)
11147 return(1);
11148 else if (wild->nsSet != NULL) {
11149 xmlSchemaWildcardNsPtr cur;
11150
11151 cur = wild->nsSet;
11152 while (cur != NULL) {
11153 if (xmlStrEqual(cur->value, ns))
11154 return(1);
11155 cur = cur->next;
11156 }
11157 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
11158 (!xmlStrEqual(wild->negNsSet->value, ns)))
11159 return(1);
11160
11161 return(0);
11162}
11163
11164/**
11165 * xmlSchemaBuildAttributeValidation:
11166 * @ctxt: the schema parser context
11167 * @type: the complex type definition
11168 *
11169 *
11170 * Builds the wildcard and the attribute uses on the given complex type.
11171 * Returns -1 if an internal error occurs, 0 otherwise.
11172 */
11173static int
11174xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
11175{
11176 xmlSchemaTypePtr baseType = NULL;
11177 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000011178 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000011179 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011180 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000011181 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011182 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011183 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011184
Daniel Veillard01fa6152004-06-29 17:04:39 +000011185 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011186 /*
11187 * Complex Type Definition with complex content Schema Component.
11188 *
11189 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011190 * TODO: Add checks for absent referenced attribute declarations and
11191 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000011192 */
11193 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011194 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011195 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000011196 "attribute uses already builded.\n",
11197 NULL, NULL);
11198 return (-1);
11199 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011200 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011201 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011202 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011203 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011204 type->name, NULL);
11205 return (-1);
11206 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011207 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011208 if (baseType == anyType)
11209 baseIsAnyType = 1;
11210 /*
11211 * Inherit the attribute uses of the base type.
11212 */
11213 /*
11214 * NOTE: It is allowed to "extend" the anyType complex type.
11215 */
11216 if (!baseIsAnyType) {
11217 if (baseType != NULL) {
11218 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
11219 tmp = (xmlSchemaAttributeLinkPtr)
11220 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11221 if (tmp == NULL) {
11222 xmlSchemaPErrMemory(ctxt,
11223 "building attribute uses of complexType", NULL);
11224 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011225 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011226 tmp->attr = cur->attr;
11227 tmp->next = NULL;
11228 if (type->attributeUses == NULL) {
11229 type->attributeUses = tmp;
11230 } else
11231 lastBaseUse->next = tmp;
11232 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011233 }
11234 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011235 }
11236 if ((type->subtypes != NULL) &&
11237 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11238 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011239 /*
11240 * type --> (<simpleContent>|<complexContent>)
11241 * --> (<restriction>|<extension>) --> attributes
11242 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011243 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011244 } else {
11245 /* Short hand form of the complexType. */
11246 attrs = type->attributes;
11247 }
11248 /*
11249 * Handle attribute wildcards.
11250 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011251 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11252 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011253 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011254 * NOTE: During the parse time, the wildcard is created on the complexType
11255 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011256 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011257 if (err == -1) {
11258 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
11259 "Internal error: xmlSchemaBuildAttributeValidation: "
11260 "failed to build an intersected attribute wildcard.\n",
11261 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011262 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011263 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011264
11265 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
11266 ((baseIsAnyType) ||
11267 ((baseType != NULL) &&
11268 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11269 (baseType->attributeWildcard != NULL)))) {
11270 if (type->attributeWildcard != NULL) {
11271 /*
11272 * Union the complete wildcard with the base wildcard.
11273 */
11274 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
11275 baseType->attributeWildcard) == -1)
11276 return (-1);
11277 } else {
11278 /*
11279 * Just inherit the wildcard.
11280 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011281 /*
11282 * NOTE: This is the only case where an attribute
11283 * wildcard is shared.
11284 */
11285 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
11286 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011287 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000011288 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011289 }
11290
11291 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11292 if (type->attributeWildcard != NULL) {
11293 /*
11294 * Derivation Valid (Restriction, Complex)
11295 * 4.1 The {base type definition} must also have one.
11296 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011297 if (baseType->attributeWildcard == NULL) {
11298 xmlSchemaPCustomErr(ctxt,
11299 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
11300 NULL, type, NULL,
11301 "The type has an attribute wildcard, "
11302 "but the base type %s does not have one",
11303 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11304 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011305 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011306 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011307 type->attributeWildcard, baseType->attributeWildcard) == 0) {
11308 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011309 xmlSchemaPCustomErr(ctxt,
11310 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
11311 NULL, type, NULL,
11312 "The attribute wildcard is not a valid "
11313 "subset of the wildcard in the base type %s",
11314 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11315 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011316 return (1);
11317 }
11318 /* 4.3 Unless the {base type definition} is the ·ur-type
11319 * definition·, the complex type definition's {attribute
11320 * wildcard}'s {process contents} must be identical to or
11321 * stronger than the {base type definition}'s {attribute
11322 * wildcard}'s {process contents}, where strict is stronger
11323 * than lax is stronger than skip.
11324 */
11325 if ((type->baseType != anyType) &&
11326 (type->attributeWildcard->processContents <
11327 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011328 xmlSchemaPCustomErr(ctxt,
11329 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
11330 NULL, type, NULL,
11331 "The 'process contents' of the attribute wildcard is weaker than "
11332 "the one in the base type %s",
11333 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11334 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011335 return (1);
11336 }
11337 }
11338 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11339 /*
11340 * Derivation Valid (Extension)
11341 * At this point the type and the base have both, either
11342 * no wildcard or a wildcard.
11343 */
11344 if ((baseType->attributeWildcard != NULL) &&
11345 (baseType->attributeWildcard != type->attributeWildcard)) {
11346 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011347 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011348 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011349 xmlSchemaPCustomErr(ctxt,
11350 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
11351 NULL, type, NULL,
11352 "The attribute wildcard is not a valid "
11353 "superset of the one in the base type %s",
11354 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11355 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011356 return (1);
11357 }
11358 }
11359 }
11360
Daniel Veillard3646d642004-06-02 19:19:14 +000011361 /*
11362 * Gather attribute uses defined by this type.
11363 */
11364 if (attrs != NULL) {
11365 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
11366 &uses, &lastUse) == -1) {
11367 return (-1);
11368 }
11369 }
11370 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
11371 * "Two distinct attribute declarations in the {attribute uses} must
11372 * not have identical {name}s and {target namespace}s."
11373 *
11374 * For "extension" this is done further down.
11375 */
11376 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
11377 cur = uses;
11378 while (cur != NULL) {
11379 tmp = cur->next;
11380 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011381 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11382 xmlSchemaGetAttrName(tmp->attr))) &&
11383 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11384 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
11385
11386 xmlSchemaPAttrUseErr(ctxt,
11387 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11388 NULL, type, NULL, cur->attr,
11389 "Duplicate attribute use %s specified",
11390 xmlSchemaFormatNsUriLocal(&str,
11391 xmlSchemaGetAttrTargetNsURI(tmp->attr),
11392 xmlSchemaGetAttrName(tmp->attr))
11393 );
11394 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011395 break;
11396 }
11397 tmp = tmp->next;
11398 }
11399 cur = cur->next;
11400 }
11401 }
11402 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11403 /*
11404 * Derive by restriction.
11405 */
11406 if (baseIsAnyType) {
11407 type->attributeUses = uses;
11408 } else {
11409 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011410 const xmlChar *bEffValue;
11411 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000011412
11413 cur = uses;
11414 while (cur != NULL) {
11415 found = 0;
11416 base = type->attributeUses;
11417 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011418 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11419 xmlSchemaGetAttrName(base->attr)) &&
11420 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
11421 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011422
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011423 found = 1;
11424
Daniel Veillard3646d642004-06-02 19:19:14 +000011425 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
11426 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11427 /*
11428 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000011429 */
11430 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011431 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011432 NULL, type, NULL, cur->attr,
11433 "The 'optional' use is inconsistent with a matching "
11434 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011435 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
11436 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11437 /*
11438 * derivation-ok-restriction 3
11439 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011440 xmlSchemaPCustomErr(ctxt,
11441 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
11442 NULL, type, NULL,
11443 "A matching attribute use for the 'required' "
11444 "attribute use %s of the base type is missing",
11445 xmlSchemaFormatNsUriLocal(&str,
11446 xmlSchemaGetAttrTargetNsURI(base->attr),
11447 xmlSchemaGetAttrName(base->attr)));
11448 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011449 } else {
11450 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011451 * 2.1.3 [Definition:] Let the effective value
11452 * constraint of an attribute use be its {value
11453 * constraint}, if present, otherwise its {attribute
11454 * declaration}'s {value constraint} .
11455 */
11456 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11457 &bEffValue, 0);
11458 /*
11459 * 2.1.3 ... one of the following must be true
11460 *
11461 * 2.1.3.1 B's ·effective value constraint· is
11462 * ·absent· or default.
11463 */
11464 if ((bEffValue != NULL) &&
11465 (effFixed == 1)) {
11466 const xmlChar *rEffValue = NULL;
11467
11468 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11469 &rEffValue, 0);
11470 /*
11471 * 2.1.3.2 R's ·effective value constraint· is
11472 * fixed with the same string as B's.
11473 */
11474 if ((effFixed == 0) ||
11475 (! xmlStrEqual(rEffValue, bEffValue))) {
11476 xmlSchemaPAttrUseErr(ctxt,
11477 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
11478 NULL, type, NULL, cur->attr,
11479 "The effective value constraint of the "
11480 "attribute use is inconsistent with "
11481 "its correspondent of the base type",
11482 NULL);
11483 }
11484 }
11485 /*
11486 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
11487 */
11488 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011489 * Override the attribute use.
11490 */
11491 base->attr = cur->attr;
11492 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011493
Daniel Veillard3646d642004-06-02 19:19:14 +000011494 break;
11495 }
11496 base = base->next;
11497 }
11498
11499 if (!found) {
11500 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11501 /*
11502 * derivation-ok-restriction 2.2
11503 */
11504 if ((type->attributeWildcard != NULL) &&
11505 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
11506 cur->attr->targetNamespace))
11507 found = 1;
11508
11509 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011510 xmlSchemaPAttrUseErr(ctxt,
11511 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
11512 NULL, type, NULL, cur->attr,
11513 "Neither a matching attribute use, "
11514 "nor a matching wildcard in the base type does exist",
11515 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011516 } else {
11517 /*
11518 * Add the attribute use.
11519 *
11520 * Note that this may lead to funny derivation error reports, if
11521 * multiple equal attribute uses exist; but this is not
11522 * allowed anyway, and it will be reported beforehand.
11523 */
11524 tmp = cur;
11525 if (prev != NULL)
11526 prev->next = cur->next;
11527 else
11528 uses = cur->next;
11529 cur = cur->next;
11530 if (type->attributeUses == NULL) {
11531 type->attributeUses = tmp;
11532 } else
11533 lastBaseUse->next = tmp;
11534 lastBaseUse = tmp;
11535
11536 continue;
11537 }
11538 }
11539 }
11540 prev = cur;
11541 cur = cur->next;
11542 }
11543 if (uses != NULL)
11544 xmlSchemaFreeAttributeUseList(uses);
11545 }
11546 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11547 /*
11548 * The spec allows only appending, and not other kinds of extensions.
11549 *
11550 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
11551 */
11552 if (uses != NULL) {
11553 if (type->attributeUses == NULL) {
11554 type->attributeUses = uses;
11555 } else
11556 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011557 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011558 } else {
11559 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000011560 * Derive implicitely from the ur-type.
11561 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011562 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011563 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011564 /*
11565 * 3.4.6 -> Complex Type Definition Properties Correct
11566 */
11567 if (type->attributeUses != NULL) {
11568 cur = type->attributeUses;
11569 prev = NULL;
11570 while (cur != NULL) {
11571 /*
11572 * 4. Two distinct attribute declarations in the {attribute uses} must
11573 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000011574 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011575 * Note that this was already done for "restriction" and types derived from
11576 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000011577 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011578 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11579 tmp = cur->next;
11580 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011581 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11582 xmlSchemaGetAttrName(tmp->attr))) &&
11583 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11584 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011585
Daniel Veillardc0826a72004-08-10 14:17:33 +000011586 xmlSchemaPAttrUseErr(ctxt,
11587 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11588 NULL, type, NULL, tmp->attr,
11589 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011590 break;
11591 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011592 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011593 }
11594 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011595 /*
11596 * 5. Two distinct attribute declarations in the {attribute uses} must
11597 * not have {type definition}s which are or are derived from ID.
11598 */
11599 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000011600 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011601 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011602 xmlSchemaPAttrUseErr(ctxt,
11603 XML_SCHEMAP_CT_PROPS_CORRECT_5,
11604 NULL, type, NULL, cur->attr,
11605 "There must not exist more than one attribute use, "
11606 "declared of type 'ID' or derived from it",
11607 NULL);
11608 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000011609 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011610 id = cur;
11611 }
11612 /*
11613 * Remove "prohibited" attribute uses. The reason this is done at this late
11614 * stage is to be able to catch dublicate attribute uses. So we had to keep
11615 * prohibited uses in the list as well.
11616 */
11617 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11618 tmp = cur;
11619 if (prev == NULL)
11620 type->attributeUses = cur->next;
11621 else
11622 prev->next = cur->next;
11623 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011624 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000011625 } else {
11626 prev = cur;
11627 cur = cur->next;
11628 }
11629 }
11630 }
11631 /*
11632 * TODO: This check should be removed if we are 100% sure of
11633 * the base type attribute uses already being built.
11634 */
11635 if ((baseType != NULL) && (!baseIsAnyType) &&
11636 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11637 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011638 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011639 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011640 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011641 baseType->name, NULL);
11642 }
11643 return (0);
11644}
11645
11646/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000011647 * xmlSchemaTypeFinalContains:
11648 * @schema: the schema
11649 * @type: the type definition
11650 * @final: the final
11651 *
11652 * Evaluates if a type definition contains the given "final".
11653 * This does take "finalDefault" into account as well.
11654 *
11655 * Returns 1 if the type does containt the given "final",
11656 * 0 otherwise.
11657 */
11658static int
11659xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
11660{
11661 int tfinal = final, tflags = type->flags;
11662
11663 if (type == NULL)
11664 return (0);
11665 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
11666 switch (final) {
11667 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
11668 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
11669 break;
11670 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
11671 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
11672 break;
11673 case XML_SCHEMAS_TYPE_FINAL_LIST:
11674 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
11675 break;
11676 case XML_SCHEMAS_TYPE_FINAL_UNION:
11677 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
11678 break;
11679 }
11680 tflags = schema->flags;
11681 }
11682 if (tflags & tfinal)
11683 return (1);
11684 else
11685 return (0);
11686
11687}
11688
11689/**
11690 * xmlSchemaGetUnionSimpleTypeMemberTypes:
11691 * @type: the Union Simple Type
11692 *
11693 * Returns a list of member types of @type if existing,
11694 * returns NULL otherwise.
11695 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011696static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000011697xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
11698{
11699 while (type != NULL) {
11700 if (type->memberTypes != NULL)
11701 return (type->memberTypes);
11702 else
11703 type = type->baseType;
11704 }
11705 return (NULL);
11706}
11707
11708/**
11709 * xmlSchemaGetListSimpleTypeItemType:
11710 * @type: the simple type definition
11711 *
11712 * Returns the item type definition of the list simple type.
11713 */
11714static xmlSchemaTypePtr
11715xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
11716{
11717 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
11718 return (NULL);
11719 /*
11720 * Note: In libxml2, the built-in types do not reflect
11721 * the datatype hierarchy (yet?) - we have to treat them
11722 * in a special way.
11723 */
11724 if (type->type == XML_SCHEMA_TYPE_BASIC)
11725 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
11726 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
11727 /* 1 If the <list> alternative is chosen, then the type
11728 * definition ·resolved· to by the ·actual value· of the
11729 * itemType [attribute] of <list>, if present, otherwise
11730 * the type definition corresponding to the <simpleType>
11731 * among the [children] of <list>.
11732 */
11733 return (type->subtypes->subtypes);
11734 else {
11735 /* 2 If the <restriction> option is chosen, then the
11736 * {item type definition} of the {base type definition}.
11737 */
11738 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
11739 }
11740}
11741
11742/**
11743 * xmlSchemaCheckCOSSTDerivedOK:
11744 * @type: the derived simple type definition
11745 * @baseType: the base type definition
11746 *
11747 * Checks wheter @type can be validly
11748 * derived from @baseType.
11749 *
11750 * Returns 0 on success, an positive error code otherwise.
11751 */
11752static int
11753xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
11754 xmlSchemaTypePtr type,
11755 xmlSchemaTypePtr baseType,
11756 int subset)
11757{
11758 /*
11759 * Schema Component Constraint: Type Derivation OK (Simple)
11760 *
11761 *
11762 * 1 They are the same type definition.
11763 * TODO: The identy check might have to be more complex than this.
11764 */
11765 if (type == baseType)
11766 return (0);
11767 /*
11768 * 2.1 restriction is not in the subset, or in the {final}
11769 * of its own {base type definition};
11770 */
11771 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
11772 (xmlSchemaTypeFinalContains(schema,
11773 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
11774 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
11775 }
11776 /* 2.2 */
11777 if (type->baseType == baseType) {
11778 /*
11779 * 2.2.1 D's ·base type definition· is B.
11780 */
11781 return (0);
11782 }
11783 /*
11784 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
11785 * and is validly derived from B given the subset, as defined by this
11786 * constraint.
11787 */
11788 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
11789 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
11790 return (0);
11791 }
11792 /*
11793 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
11794 * definition·.
11795 */
11796 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
11797 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
11798 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
11799 return (0);
11800 }
11801 /*
11802 * 2.2.4 B's {variety} is union and D is validly derived from a type
11803 * definition in B's {member type definitions} given the subset, as
11804 * defined by this constraint.
11805 *
11806 * NOTE: This seems not to involve built-in types, since there is no
11807 * built-in Union Simple Type.
11808 */
11809 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11810 xmlSchemaTypeLinkPtr cur;
11811
11812 cur = baseType->memberTypes;
11813 while (cur != NULL) {
11814 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
11815 cur->type, subset) == 0)
11816 return (0);
11817 cur = cur->next;
11818 }
11819 }
11820
11821 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
11822}
11823
11824
11825/**
11826 * xmlSchemaCheckSTPropsCorrect:
11827 * @ctxt: the schema parser context
11828 * @type: the simple type definition
11829 *
11830 * Checks st-props-correct.
11831 *
11832 * Returns 0 if the properties are correct,
11833 * if not, a positive error code and -1 on internal
11834 * errors.
11835 */
11836static int
11837xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
11838 xmlSchemaTypePtr type)
11839{
11840 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
11841 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011842 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011843
Daniel Veillardc0826a72004-08-10 14:17:33 +000011844 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011845 /*
11846 * Schema Component Constraint: Simple Type Definition Properties Correct
11847 *
11848 * NOTE: This is somehow redundant, since we actually built a simple type
11849 * to have all the needed information; this acts as an self test.
11850 */
11851 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11852 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11853 /*
11854 * TODO: 1 The values of the properties of a simple type definition must be as
11855 * described in the property tableau in Datatype definition, modulo the
11856 * impact of Missing Sub-components (§5.3).
11857 */
11858 /* Base type: If the datatype has been ·derived· by ·restriction·
11859 * then the Simple Type Definition component from which it is ·derived·,
11860 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
11861 */
11862 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011863 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011864 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011865 NULL, type, NULL,
11866 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011867 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11868 }
11869 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
11870 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
11871 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011872 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011873 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011874 NULL, type, NULL,
11875 "The base type %s is not a simple type",
11876 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11877 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011878 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11879 }
11880 if ((baseType != anySimpleType) &&
11881 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011882 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011883 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011884 NULL, type, NULL,
11885 "A type, derived by list or union, must have"
11886 "the simple ur-type definition as base type, not %s",
11887 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11888 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011889 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11890 }
11891 /*
11892 * Variety: One of {atomic, list, union}.
11893 */
11894 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11895 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
11896 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011897 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011898 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011899 NULL, type, NULL,
11900 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011901 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11902 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011903 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011904
11905 /*
11906 * 2 All simple type definitions must be derived ultimately from the ·simple
11907 * ur-type definition (so· circular definitions are disallowed). That is, it
11908 * must be possible to reach a built-in primitive datatype or the ·simple
11909 * ur-type definition· by repeatedly following the {base type definition}.
11910 */
11911 baseType = type->baseType;
11912 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
11913 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11914 xmlSchemaTypeFixup(baseType, ctxt, NULL);
11915 if (baseType == anySimpleType)
11916 break;
11917 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011918 xmlSchemaPCustomErr(ctxt,
11919 XML_SCHEMAP_ST_PROPS_CORRECT_2,
11920 NULL, type, NULL,
11921 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011922 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
11923 }
11924 baseType = baseType->baseType;
11925 }
11926 /*
11927 * 3 The {final} of the {base type definition} must not contain restriction.
11928 */
11929 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
11930 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011931 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011932 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011933 NULL, type, NULL,
11934 "The 'final' of its base type %s must not contain "
11935 "'restriction'",
11936 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11937 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011938 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
11939 }
11940 return (0);
11941}
11942
11943/**
11944 * xmlSchemaCheckDerivationValidSimpleRestriction:
11945 * @ctxt: the schema parser context
11946 * @type: the simple type definition
11947 *
11948 * Checks if the given @type (simpleType) is derived
11949 * validly by restriction.
11950 *
11951 * Returns -1 on internal errors, 0 if the type is validly derived,
11952 * a positive error code otherwise.
11953 */
11954static int
11955xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011956 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011957{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011958 xmlChar *str = NULL;
11959
11960 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011961
11962 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
11963 xmlSchemaPErr(ctxt, type->node,
11964 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011965 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
11966 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011967 type->name, NULL);
11968 return (-1);
11969 }
11970
11971 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
11972 xmlSchemaTypePtr primitive;
11973 /*
11974 * 1.1 The {base type definition} must be an atomic simple
11975 * type definition or a built-in primitive datatype.
11976 */
11977 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011978 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011979 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011980 NULL, type, NULL,
11981 "The base type %s is not an atomic simple type",
11982 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11983 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011984 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
11985 }
11986 /* 1.2 The {final} of the {base type definition} must not contain
11987 * restriction.
11988 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011989 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011990 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11991 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011992 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011993 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011994 NULL, type, NULL,
11995 "The final of its base type %s must not contain 'restriction'",
11996 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11997 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011998 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
11999 }
12000
12001 /*
12002 * 1.3.1 DF must be an allowed constraining facet for the {primitive
12003 * type definition}, as specified in the appropriate subsection of 3.2
12004 * Primitive datatypes.
12005 */
12006 if (type->facets != NULL) {
12007 xmlSchemaFacetPtr facet;
12008 int ok = 1;
12009
12010 primitive = xmlSchemaGetPrimitiveType(type);
12011 if (primitive == NULL) {
12012 xmlSchemaPErr(ctxt, type->node,
12013 XML_ERR_INTERNAL_ERROR,
12014 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012015 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012016 type->name, NULL);
12017 return (-1);
12018 }
12019 facet = type->facets;
12020 do {
12021 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012022 ok = 0;
12023 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012024 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012025 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012026 }
12027 facet = facet->next;
12028 } while (facet != NULL);
12029 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000012030 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012031 }
12032 /*
12033 * TODO: 1.3.2 (facet derivation)
12034 */
12035 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12036 xmlSchemaTypePtr itemType = NULL;
12037
12038 itemType = xmlSchemaGetListSimpleTypeItemType(type);
12039 if (itemType == NULL) {
12040 xmlSchemaPErr(ctxt, type->node,
12041 XML_ERR_INTERNAL_ERROR,
12042 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012043 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012044 type->name, NULL);
12045 return (-1);
12046 }
12047 /*
12048 * 2.1 The {item type definition} must have a {variety} of atomic or
12049 * union (in which case all the {member type definitions}
12050 * must be atomic).
12051 */
12052 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12053 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012054 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012055 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012056 NULL, type, NULL,
12057 "The item type %s must have a variety of atomic or union",
12058 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
12059 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012060 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
12061 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12062 xmlSchemaTypeLinkPtr member;
12063
12064 member = itemType->memberTypes;
12065 while (member != NULL) {
12066 if ((member->type->flags &
12067 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012068 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012069 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012070 NULL, type, NULL,
12071 "The item type is a union type, but the "
12072 "member type %s of this item type is not atomic",
12073 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12074 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012075 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
12076 }
12077 member = member->next;
12078 }
12079 }
12080
12081 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12082 xmlSchemaFacetPtr facet;
12083 /*
12084 * This is the case if we have: <simpleType><list ..
12085 */
12086 /*
12087 * 2.3.1
12088 * 2.3.1.1 The {final} of the {item type definition} must not
12089 * contain list.
12090 */
12091 if (xmlSchemaTypeFinalContains(ctxt->schema,
12092 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012093 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012094 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012095 NULL, type, NULL,
12096 "The final of its item type %s must not contain 'list'",
12097 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
12098 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012099 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
12100 }
12101 /*
12102 * 2.3.1.2 The {facets} must only contain the whiteSpace
12103 * facet component.
12104 */
12105 if (type->facets != NULL) {
12106 facet = type->facets;
12107 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012108 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
12109 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012110 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012111 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012112 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
12113 }
12114 facet = facet->next;
12115 } while (facet != NULL);
12116 }
12117 /*
12118 * TODO: Datatypes states:
12119 * A ·list· datatype can be ·derived· from an ·atomic· datatype
12120 * whose ·lexical space· allows space (such as string or anyURI)or
12121 * a ·union· datatype any of whose {member type definitions}'s
12122 * ·lexical space· allows space.
12123 */
12124 } else {
12125 /*
12126 * This is the case if we have: <simpleType><restriction ...
12127 */
12128 /*
12129 * 2.3.2
12130 * 2.3.2.1 The {base type definition} must have a {variety} of list.
12131 */
12132 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012133 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012134 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012135 NULL, type, NULL,
12136 "The base type %s must be a list type",
12137 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12138 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012139 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
12140 }
12141 /*
12142 * 2.3.2.2 The {final} of the {base type definition} must not
12143 * contain restriction.
12144 */
12145 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12146 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012147 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012148 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012149 NULL, type, NULL,
12150 "The final of the base type %s must not contain 'restriction'",
12151 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12152 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012153 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
12154 }
12155 /*
12156 * 2.3.2.3 The {item type definition} must be validly derived
12157 * from the {base type definition}'s {item type definition} given
12158 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
12159 */
12160 {
12161 xmlSchemaTypePtr baseItemType;
12162
12163 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
12164 if (baseItemType == NULL) {
12165 xmlSchemaPErr(ctxt, type->node,
12166 XML_ERR_INTERNAL_ERROR,
12167 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012168 "List simple type '%s': Failed to "
12169 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012170 type->name, type->baseType->name);
12171 return (-1);
12172 }
12173 if ((itemType != baseItemType) &&
12174 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
12175 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012176 xmlChar *strBIT = NULL, *strBT = NULL;
12177 xmlSchemaPCustomErrExt(ctxt,
12178 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
12179 NULL, type, NULL,
12180 "The item type %s is not validly derived from the "
12181 "item type %s of the base type %s",
12182 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
12183 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
12184 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12185
12186 FREE_AND_NULL(str)
12187 FREE_AND_NULL(strBIT)
12188 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012189 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
12190 }
12191 }
12192
12193 if (type->facets != NULL) {
12194 xmlSchemaFacetPtr facet;
12195 int ok = 1;
12196 /*
12197 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
12198 * and enumeration facet components are allowed among the {facets}.
12199 */
12200 facet = type->facets;
12201 do {
12202 switch (facet->type) {
12203 case XML_SCHEMA_FACET_LENGTH:
12204 case XML_SCHEMA_FACET_MINLENGTH:
12205 case XML_SCHEMA_FACET_MAXLENGTH:
12206 case XML_SCHEMA_FACET_WHITESPACE:
12207 /*
12208 * TODO: 2.5.1.2 List datatypes
12209 * The value of ·whiteSpace· is fixed to the value collapse.
12210 */
12211 case XML_SCHEMA_FACET_PATTERN:
12212 case XML_SCHEMA_FACET_ENUMERATION:
12213 break;
12214 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012215 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012216 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012217 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012218 /*
12219 * We could return, but it's nicer to report all
12220 * invalid facets.
12221 */
12222 ok = 0;
12223 }
12224 }
12225 facet = facet->next;
12226 } while (facet != NULL);
12227 if (ok == 0)
12228 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
12229 /*
12230 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
12231 * is a facet of the same kind in the {facets} of the {base type
12232 * definition} (call this BF),then the DF's {value} must be a valid
12233 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
12234 */
12235 }
12236
12237
12238 }
12239 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12240 /*
12241 * 3.1 The {member type definitions} must all have {variety} of
12242 * atomic or list.
12243 */
12244 xmlSchemaTypeLinkPtr member;
12245
12246 member = type->memberTypes;
12247 while (member != NULL) {
12248 if (((member->type->flags &
12249 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12250 ((member->type->flags &
12251 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012252 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012253 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012254 NULL, type, NULL,
12255 "The member type %s is neither an atomic, nor a list type",
12256 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12257 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012258 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
12259 }
12260 member = member->next;
12261 }
12262 /*
12263 * 3.3.1 If the {base type definition} is the ·simple ur-type
12264 * definition·
12265 */
12266 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12267 /*
12268 * 3.3.1.1 All of the {member type definitions} must have a
12269 * {final} which does not contain union.
12270 */
12271 member = type->memberTypes;
12272 while (member != NULL) {
12273 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
12274 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012275 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012276 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012277 NULL, type, NULL,
12278 "The final of member type %s contains 'union'",
12279 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12280 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012281 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
12282 }
12283 member = member->next;
12284 }
12285 /*
12286 * 3.3.1.2 The {facets} must be empty.
12287 */
12288 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012289 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012290 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012291 NULL, type, NULL,
12292 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012293 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
12294 }
12295 } else {
12296 /*
12297 * 3.3.2.1 The {base type definition} must have a {variety} of union.
12298 */
12299 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012300 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012301 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012302 NULL, type, NULL,
12303 "The base type %s is not a union type",
12304 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12305 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012306 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
12307 }
12308 /*
12309 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
12310 */
12311 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12312 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012313 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012314 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012315 NULL, type, NULL,
12316 "The final of its base type %s must not contain 'restriction'",
12317 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12318 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012319 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
12320 }
12321 /*
12322 * 3.3.2.3 The {member type definitions}, in order, must be validly
12323 * derived from the corresponding type definitions in the {base
12324 * type definition}'s {member type definitions} given the empty set,
12325 * as defined in Type Derivation OK (Simple) (§3.14.6).
12326 */
12327 {
12328 xmlSchemaTypeLinkPtr baseMember;
12329
12330 /*
12331 * OPTIMIZE: if the type is restricting, it has no local defined
12332 * member types and inherits the member types of the base type;
12333 * thus a check for equality can be skipped.
12334 */
12335 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012336 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000012337 * union simple type can have other member types as the member
12338 * types of it's base type. This check seems not necessary with
12339 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012340 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012341 */
12342 if (type->memberTypes != NULL) {
12343 member = type->memberTypes;
12344 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
12345 if ((member == NULL) && (baseMember != NULL)) {
12346 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012347 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012348 "Internal error: "
12349 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012350 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012351 "of member types in the base type\n",
12352 type->name, NULL);
12353 }
12354 while (member != NULL) {
12355 if (baseMember == NULL) {
12356 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012357 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012358 "Internal error: "
12359 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012360 "(3.3.2.3), union simple type '%s', unequal number "
12361 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012362 type->name, NULL);
12363 }
12364 if ((member->type != baseMember->type) &&
12365 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
12366 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012367 xmlChar *strBMT = NULL, *strBT = NULL;
12368
12369 xmlSchemaPCustomErrExt(ctxt,
12370 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
12371 NULL, type, NULL,
12372 "The member type %s is not validly derived from its "
12373 "corresponding member type %s of the base type %s",
12374 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
12375 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
12376 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12377 FREE_AND_NULL(str)
12378 FREE_AND_NULL(strBMT)
12379 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012380 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
12381 }
12382 member = member->next;
12383 baseMember = baseMember->next;
12384 }
12385 }
12386 }
12387 /*
12388 * 3.3.2.4 Only pattern and enumeration facet components are
12389 * allowed among the {facets}.
12390 */
12391 if (type->facets != NULL) {
12392 xmlSchemaFacetPtr facet;
12393 int ok = 1;
12394
12395 facet = type->facets;
12396 do {
12397 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
12398 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012399 xmlSchemaPIllegalFacetListUnionErr(ctxt,
12400 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
12401 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012402 ok = 0;
12403 }
12404 facet = facet->next;
12405 } while (facet != NULL);
12406 if (ok == 0)
12407 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
12408
12409 }
12410 /*
12411 * TODO: 3.3.2.5 (facet derivation)
12412 */
12413 }
12414 }
12415
12416 return (0);
12417}
12418
12419/**
12420 * xmlSchemaCheckSRCSimpleType:
12421 * @ctxt: the schema parser context
12422 * @type: the simple type definition
12423 *
12424 * Checks crc-simple-type constraints.
12425 *
12426 * Returns 0 if the constraints are satisfied,
12427 * if not a positive error code and -1 on internal
12428 * errors.
12429 */
12430static int
12431xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
12432 xmlSchemaTypePtr type)
12433{
12434 /*
12435 * NOTE: src-simple-type 2-4 are redundant, since the checks
12436 * were are done for the corresponding <restriction>, <list> and <union>
12437 * elements, but W3C wants a <simpleType> error as well, so it gets one.
12438 * Maby this can be skipped in the future, if we get sure it's not needed.
12439 */
12440 if (type->subtypes == NULL) {
12441 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012442 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012443 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012444 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012445 type->name, NULL);
12446 return (-1);
12447 }
12448 /*
12449 * src-simple-type.1 The corresponding simple type definition, if any,
12450 * must satisfy the conditions set out in Constraints on Simple Type
12451 * Definition Schema Components (§3.14.6).
12452 */
12453 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
12454 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
12455 /*
12456 * TODO: Removed this, since it got annoying to get an
12457 * extra error report, if anything failed until now.
12458 * Enable this if needed.
12459 */
12460 /*
12461 xmlSchemaPErr(ctxt, type->node,
12462 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012463 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012464 "on simple type definitions.\n",
12465 type->name, NULL);
12466 */
12467 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
12468 }
12469
12470 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
12471 /*
12472 * src-simple-type.2 If the <restriction> alternative is chosen,
12473 * either it must have a base [attribute] or a <simpleType> among its
12474 * [children], but not both.
12475 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012476 /*
12477 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
12478 * NOTE: This was removed, since this will be already handled
12479 * in the parse function for <restriction>.
12480 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012481 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
12482 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
12483 * an itemType [attribute] or a <simpleType> among its [children],
12484 * but not both.
12485 * NOTE: baseType is set to the local simple type definiton,
12486 * if existent, at parse time. This is a hack and not nice.
12487 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012488 /*
12489 * TODO: Remove this, and add the check to the parse function of <list>.
12490 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012491 if (((type->subtypes->base == NULL) &&
12492 (type->baseType == NULL)) ||
12493 ((type->subtypes->base != NULL) &&
12494 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012495 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012496 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012497 NULL, type, NULL,
12498 "Either the attribute 'itemType' or the <simpleType> child "
12499 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012500 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
12501 }
12502
12503
12504 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
12505 xmlSchemaTypeLinkPtr member;
12506 xmlSchemaTypePtr ancestor, anySimpleType;
12507
12508 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12509
12510 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
12511 * the <union> alternative is chosen, there must not be any entries
12512 * in the memberTypes [attribute] at any depth which resolve to the
12513 * component corresponding to the <simpleType>.
12514 */
12515 member = type->memberTypes;
12516 while (member != NULL) {
12517 ancestor = member->type;
12518 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
12519 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12520 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
12521 if (ancestor == anySimpleType)
12522 break;
12523 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012524 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012525 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012526 NULL, type, NULL,
12527 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012528 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
12529 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12530 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012531 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000012532 * type as item type, which in turn has a list ST as member
12533 * type, we will assume this here as well, since this check
12534 * was not yet performed.
12535 */
12536
12537 }
12538 ancestor = ancestor->baseType;
12539 }
12540 member = member->next;
12541 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012542 }
12543
12544 return (0);
12545}
12546
William M. Brack2f2a6632004-08-20 23:09:47 +000012547#if 0 /* Not yet used code for CT schema validation */
12548static int
12549xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
12550 const xmlChar * value,
12551 xmlSchemaTypePtr type,
12552 int fireErrors)
12553{
12554 int ret;
12555 /*
12556 * 3.14.4 Simple Type Definition Validation Rules
12557 * Validation Rule: String Valid
12558 */
12559 /*
12560 * 1 It is schema-valid with respect to that definition as defined
12561 * by Datatype Valid in [XML Schemas: Datatypes].
12562 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012563 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
12564 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000012565 return (ret);
12566 /*
12567 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
12568 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
12569 * the string must be a ·declared entity name·.
12570 */
12571 /*
12572 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
12573 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
12574 * then every whitespace-delimited substring of the string must be a ·declared
12575 * entity name·.
12576 */
12577 /*
12578 * 2.3 otherwise no further condition applies.
12579 */
12580
12581 return (0);
12582}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012583#endif
12584
William M. Brack2f2a6632004-08-20 23:09:47 +000012585
12586static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012587xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
12588{
12589 if (vctxt->pctxt == NULL) {
12590 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
12591 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
12592 if (vctxt->pctxt == NULL) {
12593 xmlSchemaVErr(vctxt, NULL,
12594 XML_SCHEMAV_INTERNAL,
12595 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12596 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000012597 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012598 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012599 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012600 /* TODO: Pass user data. */
12601 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
12602 }
12603 return (0);
12604}
12605
12606static int
12607xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
12608{
12609 if (ctxt->vctxt == NULL) {
12610 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
12611 if (ctxt->vctxt == NULL) {
12612 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012613 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012614 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12615 "failed to create a temp. validation context.\n",
12616 NULL, NULL);
12617 return (-1);
12618 }
12619 /* TODO: Pass user data. */
12620 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
12621 }
12622 return (0);
12623}
12624
12625/**
12626 * xmlSchemaCheckCOSValidDefault:
12627 * @ctxt: the schema parser context
12628 * @type: the simple type definition
12629 * @value: the default value
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000012630 * @val: the precomputed value to be returned
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012631 * @node: an optional node (the holder of the value)
12632 *
12633 * Checks the "cos-valid-default" constraints.
12634 *
12635 * Returns 0 if the constraints are satisfied,
12636 * if not, a positive error code and -1 on internal
12637 * errors.
12638 */
12639static int
12640xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
12641 xmlSchemaValidCtxtPtr vctxt,
12642 xmlSchemaTypePtr type,
12643 const xmlChar *value,
12644 xmlNodePtr node)
12645{
12646 int ret = 0;
12647
12648 /*
12649 * cos-valid-default:
12650 * Schema Component Constraint: Element Default Valid (Immediate)
12651 * For a string to be a valid default with respect to a type
12652 * definition the appropriate case among the following must be true:
12653 */
12654 /*
12655 * NOTE: This has to work without a given node (the holder of the
12656 * value), since it should work on the component, i.e. an underlying
12657 * DOM must not be mandatory.
12658 */
12659 if ((pctxt == NULL) || (vctxt == NULL)) {
12660 xmlSchemaPErr(pctxt, node,
12661 XML_SCHEMAP_INTERNAL,
12662 "Internal error: xmlSchemaCheckCOSValidDefault, "
12663 "bad arguments: the parser and/or validation context is "
12664 "missing.\n",
12665 NULL, NULL);
12666 return (-1);
12667 }
12668 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012669 /*
12670 * Complex type.
12671 *
12672 * 2.1 its {content type} must be a simple type definition or mixed.
12673 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012674 /*
12675 * TODO: Adjust this when the content type will be computed
12676 * correctly.
12677 */
12678 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
12679 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
12680 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
12681 xmlSchemaPSimpleTypeErr(pctxt,
12682 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
12683 NULL, NULL, node,
12684 type, NULL, NULL,
12685 "If the type of a constraint value is complex, its content "
12686 "type must be mixed or a simple type",
12687 NULL, NULL);
12688 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
12689 }
12690 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012691 /*
12692 * 2.2.2 If the {content type} is mixed, then the {content type}'s
12693 * particle must be ·emptiable· as defined by Particle Emptiable
12694 * (§3.9.6).
12695 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012696
William M. Brack2f2a6632004-08-20 23:09:47 +000012697 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012698 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000012699 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012700 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000012701 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012702 }
12703 /*
12704 * 1 If the type definition is a simple type definition, then the string
12705 * must be ·valid· with respect to that definition as defined by String
12706 * Valid (§3.14.4).
12707 *
12708 * AND
12709 *
12710 * 2.2.1 If the {content type} is a simple type definition, then the
12711 * string must be ·valid· with respect to that simple type definition
12712 * as defined by String Valid (§3.14.4).
12713 */
12714 vctxt->node = node;
12715 vctxt->cur = NULL;
12716 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
12717 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
12718 if (ret < 0) {
12719 xmlSchemaPErr(pctxt, node,
12720 /* NOTNICE: error code: This function will be used during
12721 * schema construction and xsi:type validation.
12722 */
12723 XML_SCHEMAP_INTERNAL,
12724 "Internal error: xmlSchemaCheckCOSValidDefault, "
12725 "while validating a value constaint value.\n",
12726 NULL, NULL);
12727
12728 }
12729 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000012730}
12731
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012732#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000012733/**
12734 * xmlSchemaGetSTContentOfCT:
12735 * @ctxt: the schema parser context
12736 * @type: the complex type definition
12737 *
12738 *
12739 * Returns the corresponding simple type for the content of
12740 * the complex type.
12741 */
12742static xmlSchemaTypePtr
12743xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
12744 xmlSchemaTypePtr type)
12745{
12746 xmlSchemaTypePtr orig = type, anyType;
12747
12748 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12749 while ((type != NULL) && (type != anyType) &&
12750 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
12751 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
12752 return(type);
12753 type = type->baseType;
12754 }
12755 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012756 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012757 NULL, orig, NULL,
12758 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
12759 "no simple type for the content of complex type '%s' could be "
12760 "computed", orig->name);
12761 return (NULL);
12762}
12763
12764
William M. Brack2f2a6632004-08-20 23:09:47 +000012765
William M. Brack2f2a6632004-08-20 23:09:47 +000012766
12767/**
12768 * xmlSchemaCheckCOSCTExtends:
12769 * @ctxt: the schema parser context
12770 * @type: the complex type definition
12771 *
12772 * Schema Component Constraint: Derivation Valid (Extension)
12773 *
12774 * Returns 0 if the constraints are satisfied, a positive
12775 * error code if not and -1 if an internal error occured.
12776 */
12777static int
12778xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
12779 xmlSchemaTypePtr type)
12780{
12781 xmlSchemaTypePtr base;
12782 /*
12783 * 1 If the {base type definition} is a complex type definition,
12784 * then all of the following must be true:
12785 */
12786 base = type->baseType;
12787 if (base == NULL) {
12788 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012789 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012790 NULL, type, NULL,
12791 "Internal error: xmlSchemaCheckCOSCTExtends, "
12792 "the complex type '%s' has no base type", type->name);
12793 return (-1);
12794 }
12795 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
12796 /*
12797 * 1.1 The {final} of the {base type definition} must not
12798 * contain extension.
12799 */
12800 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
12801 xmlSchemaPCustomErr(ctxt,
12802 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
12803 NULL, type, NULL,
12804 "The 'final' of the base type definition "
12805 "contains extension", NULL);
12806 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
12807 }
12808 /*
12809 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
12810 * of the complex type definition itself, that is, for every attribute
12811 * use in the {attribute uses} of the {base type definition}, there
12812 * must be an attribute use in the {attribute uses} of the complex
12813 * type definition itself whose {attribute declaration} has the same
12814 * {name}, {target namespace} and {type definition} as its attribute
12815 * declaration
12816 *
12817 * NOTE: This will be already satisfied by the way the attribute uses
12818 * are extended in xmlSchemaBuildAttributeValidation; thus this check
12819 * is not needed.
12820 */
12821
12822 /*
12823 * 1.3 If it has an {attribute wildcard}, the complex type definition
12824 * must also have one, and the base type definition's {attribute
12825 * wildcard}'s {namespace constraint} must be a subset of the complex
12826 * type definition's {attribute wildcard}'s {namespace constraint},
12827 * as defined by Wildcard Subset (§3.10.6).
12828 *
12829 * This is already checked in xmlSchemaBuildAttributeValidation; thus
12830 * this check is not needed.
12831 */
12832
12833 /*
12834 * 1.4 One of the following must be true:
12835 *
12836 * 1.4.1 The {content type} of the {base type definition} and the
12837 * {content type} of the complex type definition itself must be the same
12838 * simple type definition
12839 */
12840
12841
12842
12843 } else {
12844 /*
12845 * 2 If the {base type definition} is a simple type definition,
12846 * then all of the following must be true:
12847 */
12848 /*
12849 * 2.1 The {content type} must be the same simple type definition.
12850 */
12851 /*
12852 * 2.2 The {final} of the {base type definition} must not contain
12853 * extension
12854 */
12855 }
12856
12857}
12858
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012859static int
12860xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
12861 xmlSchemaTypePtr type)
12862{
12863 xmlSchemaTypePtr base, content;
12864 int OK = 0;
12865
12866 /*
12867 * TODO: Adjust the error codes here, as I used
12868 * XML_SCHEMAP_SRC_CT_1 only yet.
12869 */
12870 /*
12871 * Schema Representation Constraint:
12872 * Complex Type Definition Representation OK
12873 */
12874 base = type->baseType;
12875 if (base == NULL) {
12876 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
12877 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
12878 type->name);
12879 return (-1);
12880 }
12881
12882 if (type->subtypes != NULL) {
12883 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
12884 if IS_COMPLEX_TYPE(base) {
12885 /*
12886 * 1 If the <complexContent> alternative is chosen, the type definition
12887 * ·resolved· to by the ·actual value· of the base [attribute]
12888 * must be a complex type definition;
12889 */
12890 xmlSchemaPCustomErr(ctxt,
12891 XML_SCHEMAP_SRC_CT_1,
12892 NULL, type, NULL,
12893 "The base type is not a complex type", NULL);
12894 return (XML_SCHEMAP_SRC_CT_1);
12895 }
12896 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
12897
12898 if IS_SIMPLE_TYPE(base) {
12899 if (type->flags &
12900 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12901 /*
12902 * 2.1.3 only if the <extension> alternative is also
12903 * chosen, a simple type definition.
12904 */
12905 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
12906 xmlSchemaPCustomErr(ctxt,
12907 XML_SCHEMAP_SRC_CT_1,
12908 NULL, type, NULL,
12909 "A complex type (simple content) cannot restrict "
12910 "an other simple type",
12911 NULL);
12912 return (XML_SCHEMAP_SRC_CT_1);
12913 }
12914 OK = 1;
12915
12916 } else { /* if IS_SIMPLE_TYPE(base) */
12917 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
12918 /*
12919 * 2.1.2 only if the <restriction> alternative is also
12920 * chosen, a complex type definition whose {content type}
12921 * is mixed and a particle emptyable.
12922 */
12923 /*
12924 * FIXME TODO: Check for *empiable particle* is missing.
12925 */
12926 if ((type->flags &
12927 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
12928 xmlSchemaPCustomErr(ctxt,
12929 XML_SCHEMAP_SRC_CT_1,
12930 NULL, type, NULL,
12931 "A complex type (simple content) cannot "
12932 "extend an other complex type which has a "
12933 "content type of: 'mixed' and emptiable particle",
12934 NULL);
12935 return (XML_SCHEMAP_SRC_CT_1);
12936 }
12937 /*
12938 * NOTE: This will be fired as well, if the base type
12939 * is *'anyType'*.
12940 * NOTE: type->subtypes->subtypes will be the
12941 * <restriction> item.
12942 */
12943 if (type->subtypes->subtypes == NULL) {
12944 /* Yes, this is paranoid programming. */
12945 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12946 NULL, type, NULL,
12947 "Internal error: xmlSchemaCheckSRCCT, "
12948 "'%s', <simpleContent> has no <restriction>",
12949 type->name);
12950 return (-1);
12951 }
12952 /*
12953 * 2.2 If clause 2.1.2 above is satisfied, then there
12954 * must be a <simpleType> among the [children] of
12955 * <restriction>.
12956 */
12957 if (type->subtypes->subtypes->type !=
12958 XML_SCHEMA_TYPE_SIMPLE) {
12959 /* TODO: Change error code to ..._SRC_CT_2_2. */
12960 xmlSchemaPCustomErr(ctxt,
12961 XML_SCHEMAP_SRC_CT_1,
12962 NULL, type, NULL,
12963 "A <simpleType> is expected among the children "
12964 "of <restriction>", NULL);
12965 return (XML_SCHEMAP_SRC_CT_1);
12966 }
12967 OK = 1;
12968 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
12969 /*
12970 * 2.1.1 a complex type definition whose {content type} is a
12971 * simple type definition;
12972 */
12973 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
12974 xmlSchemaPCustomErr(ctxt,
12975 XML_SCHEMAP_SRC_CT_1,
12976 NULL, type, NULL,
12977 "A complex type (simple content) cannot "
12978 "be derived from the complex type '%s'",
12979 base->name);
12980 return (XML_SCHEMAP_SRC_CT_1);
12981 }
12982 content = base->contentTypeDef;
12983 if (content == NULL) {
12984 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12985 NULL, type, NULL,
12986 "Internal error: xmlSchemaCheckSRCCT, "
12987 "'%s', base type has no content type",
12988 type->name);
12989 return (-1);
12990 }
12991 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
12992 xmlSchemaPCustomErr(ctxt,
12993 XML_SCHEMAP_SRC_CT_1,
12994 NULL, type, NULL,
12995 "A complex type (simple content) cannot "
12996 "be derived from the complex type '%s'",
12997 base->name);
12998 return (XML_SCHEMAP_SRC_CT_1);
12999 }
13000 }
13001 }
13002 }
13003 }
13004 /*
13005 * TODO: 3 The corresponding complex type definition component must
13006 * satisfy the conditions set out in Constraints on Complex Type
13007 * Definition Schema Components (§3.4.6);
13008 *
13009 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
13010 * above for {attribute wildcard} is satisfied, the intensional
13011 * intersection must be expressible, as defined in Attribute Wildcard
13012 * Intersection (§3.10.6).
13013 */
13014
13015}
William M. Brack2f2a6632004-08-20 23:09:47 +000013016#endif
13017
Daniel Veillard01fa6152004-06-29 17:04:39 +000013018/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013019 * xmlSchemaGroupDefFixup:
13020 * @typeDecl: the schema model group definition
13021 * @ctxt: the schema parser context
13022 *
13023 * Fixes model group definitions.
13024 */
13025static void
13026xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
13027 xmlSchemaParserCtxtPtr ctxt,
13028 const xmlChar * name ATTRIBUTE_UNUSED)
13029{
13030 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
13031 if ((group->ref != NULL) && (group->subtypes == NULL)) {
13032 xmlSchemaTypePtr groupDef;
13033 /*
13034 * Resolve the reference.
13035 */
13036 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
13037 group->refNs);
13038 if (groupDef == NULL) {
13039 xmlSchemaPResCompAttrErr(ctxt,
13040 XML_SCHEMAP_SRC_RESOLVE,
13041 NULL, group, NULL,
13042 "ref", group->ref, group->refNs,
13043 XML_SCHEMA_TYPE_GROUP, NULL);
13044 return;
13045 }
13046 group->subtypes = groupDef;
13047 }
13048}
13049
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013050#if 0 /* Enable when the content type will be computed. */
13051static int
13052xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
13053 xmlSchemaTypePtr type)
13054{
13055 xmlSchemaTypePtr base, res = NULL;
13056
13057 base = type->baseType;
13058 if (base == NULL) {
13059 xmlSchemaPCustomErr(ctxt,
13060 XML_SCHEMAP_INTERNAL,
13061 NULL, type, NULL,
13062 "Internal error: xmlSchemaGetContentType, "
13063 "the complex type '%s' has no base type", type->name);
13064 return (-1);
13065 }
13066 if (IS_ANYTYPE(base) || (type->subtypes->type ==
13067 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
13068 xmlSchemaTypePtr start;
13069 /*
13070 * Effective 'mixed'.
13071 */
13072 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
13073 type->contentType = XML_SCHEMA_CONTENT_MIXED;
13074 /*
13075 * Effective content.
13076 */
13077 if (IS_ANYTYPE(base))
13078 start = type;
13079 else
13080 start = type->subtypes;
13081
13082 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
13083 xmlSchemaTypePtr baseContentItem;
13084
13085 /*
13086 * Complex type with simple content.
13087 */
13088 if IS_COMPLEX_TYPE(base) {
13089 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
13090 /*
13091 * Summary: a complex type (simple content) can *restrict*
13092 * a complex type with the following content type:
13093 * 1. 'mixed' and an emptiable particle
13094 * 2. simple type
13095 */
13096 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
13097 /*
13098 * 2 if the {content type} of the base type is mixed and a
13099 * particle which is ·emptiable·,
13100 * [...]
13101 * then starting from the simple type definition
13102 * corresponding to the <simpleType> among the [children]
13103 * of <restriction> (**which must be present**)
13104 *
13105 * FIXME TODO: Handle "emptiable particle".
13106 */
13107 res = type->subtypes->subtypes;
13108 if (res == NULL) {
13109 xmlSchemaPCustomErr(ctxt,
13110 XML_SCHEMAP_INTERNAL,
13111 NULL, type, NULL,
13112 "Internal error: xmlSchemaGetContentType, "
13113 "CT '%s' (restricting): <simpleContent> has no "
13114 "<restriction>",
13115 type->name);
13116 return (-1);
13117 }
13118
13119 res->subtypes;
13120 if (res == NULL) {
13121 xmlSchemaPCustomErr(ctxt,
13122 XML_SCHEMAP_INTERNAL,
13123 NULL, type, NULL,
13124 "Internal error: xmlSchemaGetContentType, "
13125 "CT '%s' (restricting): <restriction> has no "
13126 "mandatory <simpleType>",
13127 type->name);
13128 return (-1);
13129 }
13130 } else {
13131 baseContentItem = base->contentTypeDef;
13132 if (baseContentItem == NULL) {
13133 xmlSchemaPCustomErr(ctxt,
13134 XML_SCHEMAP_INTERNAL,
13135 NULL, type, NULL,
13136 "Internal error: xmlSchemaGetContentType, "
13137 "CT '%s' (restricting), the base type has no "
13138 "content type", type->name);
13139 return (-1);
13140 }
13141 if IS_SIMPLE_TYPE(baseContentItem) {
13142 /*
13143 * 1 If the base type is a complex type whose own
13144 * {content type} is a simple type and the <restriction>
13145 * alternative is chosen
13146 */
13147 /* type->subtypes->subtypes will be the restriction item.*/
13148 res = type->subtypes->subtypes;
13149 if (res == NULL) {
13150 xmlSchemaPCustomErr(ctxt,
13151 XML_SCHEMAP_INTERNAL,
13152 NULL, type, NULL,
13153 "Internal error: xmlSchemaGetContentType, "
13154 "CT '%s' (restricting): <simpleType> has no "
13155 "<restriction>", type->name);
13156 return (-1);
13157 }
13158 /*
13159 * 1.1 the simple type definition corresponding to the
13160 * <simpleType> among the [children] of <restriction>if
13161 * there is one;
13162 */
13163 res = res->subtypes;
13164 if (res == NULL) {
13165 /*
13166 * 1.2 otherwise the {content type}
13167 * of the base type .
13168 */
13169 res = baseContentItem;
13170 }
13171 }
13172 }
13173 /*
13174 * SPECIAL TODO: If *restricting* the spec wants us to
13175 * create an *additional* simple type which restricts the
13176 * located simple type; we won't do this yet, and look how
13177 * far we get with it.
13178 */
13179 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
13180 /*
13181 * Summary: a complex type (simple content) can *extend*
13182 * only a complex base with a simple type as content.
13183 */
13184 /*
13185 * 3 If the type definition ·resolved· to by the ·actual
13186 * value· of the base [attribute] is a complex type
13187 * definition (whose own {content type} *must be* a simple
13188 * type definition, see below) and the *<extension>*
13189 * alternative is chosen, then the {content type} of that
13190 * complex type definition;
13191 */
13192 res = base->contentTypeDef;
13193 if (res == NULL) {
13194 xmlSchemaPCustomErr(ctxt,
13195 XML_SCHEMAP_INTERNAL,
13196 NULL, type, NULL,
13197 "Internal error: xmlSchemaGetContentType, "
13198 "CT '%s' (extending), the base type has no content "
13199 "type", type->name);
13200 return (-1);
13201 }
13202 if (! IS_SIMPLE_TYPE(res)) {
13203 xmlSchemaPCustomErr(ctxt,
13204 XML_SCHEMAP_INTERNAL,
13205 NULL, type, NULL,
13206 "Internal error: xmlSchemaGetContentType, "
13207 "CT '%s' (extending), the content type of the "
13208 "base is not a simple type", type->name);
13209 return (-1);
13210 }
13211 }
13212 } else /* if IS_COMPLEX_TYPE(base) */
13213 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
13214 /*
13215 * 4 otherwise (the type definition ·resolved· to by the
13216 * ·actual value· of the base [attribute] is a simple type
13217 * definition and the <extension> alternative is chosen),
13218 * then that simple type definition.
13219 */
13220 res = base;
13221 }
13222 type->contentTypeDef = res;
13223 if (res == NULL) {
13224 xmlSchemaPCustomErr(ctxt,
13225 XML_SCHEMAP_INTERNAL,
13226 NULL, type, NULL,
13227 "Internal error: xmlSchemaGetContentType, "
13228 "'%s', the content type could not be determined",
13229 type->name);
13230 return (-1);
13231 }
13232
13233 }
13234
13235}
13236#endif
13237
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013238/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013239 * xmlSchemaTypeFixup:
13240 * @typeDecl: the schema type definition
13241 * @ctxt: the schema parser context
13242 *
13243 * Fixes the content model of the type.
13244 */
13245static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013246xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013247 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013248{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013249 xmlSchemaTypePtr ctxtType;
13250
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013251 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013252 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013253 /*
13254 * Do not allow the following types to be typefixed, prior to
13255 * the corresponding simple/complex types.
13256 */
13257 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013258 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013259 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13260 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13261 case XML_SCHEMA_TYPE_UNION:
13262 case XML_SCHEMA_TYPE_RESTRICTION:
13263 case XML_SCHEMA_TYPE_EXTENSION:
13264 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013265 default:
13266 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013267 }
13268 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013269 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013270 name = item->name;
13271 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
13272 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013273 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013274 if (item->subtypes != NULL) {
13275 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013276 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013277 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013278 NULL);
13279 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013280 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013281 XML_SCHEMA_CONTENT_SIMPLE;
13282 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013283 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013284 break;
13285 }
13286 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013287 xmlSchemaTypePtr base = NULL;
13288
13289 ctxt->ctxtType->flags |=
13290 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013291 if (item->baseType != NULL)
13292 base = item->baseType;
13293 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013294 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013295 xmlSchemaGetType(ctxt->schema, item->base,
13296 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013297 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013298 xmlSchemaPResCompAttrErr(ctxt,
13299 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000013300 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013301 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
13302 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013303 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013304 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000013305 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013306 xmlSchemaTypeFixup(base, ctxt, NULL);
13307 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013308 }
13309 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013310 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
13311 /*
13312 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000013313 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013314 /*
13315 * Content type.
13316 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013317 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013318 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013319 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13320 else if ((item->subtypes->subtypes == NULL) &&
13321 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013322 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013323 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013324 XML_SCHEMA_TYPE_SEQUENCE)))
13325 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013326 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13327 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013328 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013329 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013330 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013331 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013332 else {
13333 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013334 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013335 XML_SCHEMA_CONTENT_ELEMENTS;
13336 }
13337 } else {
13338 /*
13339 * SimpleType restriction.
13340 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013341 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013342 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013343 break;
13344 }
13345 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013346 xmlSchemaTypePtr base = NULL;
13347 xmlSchemaContentType explicitContentType;
13348
13349 /*
13350 * An extension does exist on a complexType only.
13351 */
13352 ctxt->ctxtType->flags |=
13353 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013354 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013355 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013356 xmlSchemaPCustomErr(ctxt,
13357 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013358 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013359 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000013360 return;
13361 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013362 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013363 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013364 xmlSchemaGetType(ctxt->schema, item->base,
13365 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013366 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013367 xmlSchemaPResCompAttrErr(ctxt,
13368 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013369 NULL, item, item->node,
13370 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013371 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013372 } else if (base->contentType ==
13373 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013374 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013375 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013376 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013377 }
13378 /*
13379 * The type definition ·resolved· to by the ·actual
13380 * value· of the base [attribute]
13381 */
13382 ctxt->ctxtType->baseType = base;
13383 /*
13384 * TODO: This one is still needed for computation of
13385 * the content model by xmlSchemaBuildAContentModel.
13386 * Try to get rid of it.
13387 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013388 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013389 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013390 if ((item->subtypes != NULL) &&
13391 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
13392 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013393
13394 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013395 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013396 /* 1.1.1 */
13397 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013398 else if ((item->subtypes->subtypes == NULL) &&
13399 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013400 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013401 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013402 XML_SCHEMA_TYPE_SEQUENCE)))
13403 /* 1.1.2 */
13404 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013405 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013406 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013407 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013408 /* 1.1.3 */
13409 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
13410 if (base != NULL) {
13411 /* It will be reported later, if the base is missing. */
13412 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
13413 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013414 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013415 } else if (base->contentType ==
13416 XML_SCHEMA_CONTENT_EMPTY) {
13417 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013418 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013419 XML_SCHEMA_CONTENT_ELEMENTS;
13420 } else {
13421 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013422 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013423 XML_SCHEMA_CONTENT_ELEMENTS;
13424 }
13425 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013426 break;
13427 }
13428 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013429 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013430 ctxt->ctxtType = item;
13431 /*
13432 * Start with an empty content-type type.
13433 */
13434 if (item->subtypes == NULL)
13435 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13436
13437 if ((item->subtypes == NULL) ||
13438 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013439 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013440 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013441 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
13442 /*
13443 * This case is understood as shorthand for complex
13444 * content restricting the ur-type definition, and
13445 * the details of the mappings should be modified as
13446 * necessary.
13447 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013448 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13449 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013450 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013451 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013452 * Assume that we inherit the content-type type
13453 * from 'anyType', which is 'mixed' and a particle
13454 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013455 */
13456 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013457 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013458 /*
13459 * Fixup the sub components.
13460 */
13461 if ((item->subtypes != NULL) &&
13462 (item->subtypes->contentType ==
13463 XML_SCHEMA_CONTENT_UNKNOWN)) {
13464 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013465 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013466 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13467 item->contentType = XML_SCHEMA_CONTENT_MIXED;
13468 } else if (item->subtypes != NULL) {
13469 /*
13470 * Use the content-type type of the model groups
13471 * defined, if 'mixed' is not set. If 'mixed' is set
13472 * it will expand the content-type by allowing character
13473 * content to appear.
13474 */
13475 item->contentType =
13476 item->subtypes->contentType;
13477 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013478
13479 /*
13480 * Some optimization for validation:
13481 * If there are no facets beside the "whitespace" facet,
13482 * then a value needs not to checked against against a
13483 * facet, thus no computed value is needed.
13484 * TODO URGENT: This is just a workaround, we need to
13485 * introduce the correct usage of contentType to store the
13486 * facets in!
13487 */
Daniel Veillardd3210bc2005-01-28 17:56:39 +000013488 if ((item->baseType != NULL) &&
13489 (item->baseType->flags &
13490 XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013491 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13492 else {
13493 xmlSchemaFacetLinkPtr cur;
13494
13495 for (cur = item->facetSet; cur != NULL;
13496 cur = cur->next) {
13497 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13498 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13499 break;
13500 }
13501 }
13502 }
13503
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013504 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013505 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013506 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013507 break;
13508 }
13509 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013510 if (item->subtypes == NULL) {
13511 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13512 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
13513 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000013514 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013515 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013516 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13517 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013518 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000013519 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013520 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013521 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013522 if (item->subtypes != NULL)
13523 item->contentType =
13524 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013525 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013526 /*
13527 * Removed due to implementation of the build of attribute uses.
13528 */
13529 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013530 if (item->attributes == NULL)
13531 item->attributes =
13532 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000013533 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013534 }
13535 break;
13536 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013537 case XML_SCHEMA_TYPE_SIMPLE:
13538 /*
13539 * Simple Type Definition Schema Component
13540 *
13541 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013542 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013543 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13544 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013545 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013546 ctxt->ctxtType = item;
13547 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013548 }
13549 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013550 if ((item->baseType != NULL) &&
13551 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013552 XML_SCHEMA_CONTENT_UNKNOWN)) {
13553 /* OPTIMIZE: Actually this one will never by hit, since
13554 * the base type is already type-fixed in <restriction>.
13555 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013556 ctxt->ctxtType = item;
13557 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013558 }
13559 /* Base type:
13560 * 2 If the <list> or <union> alternative is chosen,
13561 * then the ·simple ur-type definition·.
13562 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013563 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013564 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013565 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13566 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13567 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013568 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013569 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13570 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
13571 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013572 XML_SCHEMA_TYPE_RESTRICTION) {
13573 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
13574
13575 /*
13576 * Variety
13577 * If the <restriction> alternative is chosen, then the
13578 * {variety} of the {base type definition}.
13579 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013580 if (item->baseType != NULL) {
13581 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013582 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013583 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
13584 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013585 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013586 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13587 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013588 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013589 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013590 /*
13591 * Schema Component Constraint: Simple Type Restriction
13592 * (Facets)
13593 * NOTE: Satisfaction of 1 and 2 arise from the fixup
13594 * applied beforehand.
13595 *
13596 * 3 The {facets} of R are the union of S and the {facets}
13597 * of B, eliminating duplicates. To eliminate duplicates,
13598 * when a facet of the same kind occurs in both S and the
13599 * {facets} of B, the one in the {facets} of B is not
13600 * included, with the exception of enumeration and pattern
13601 * facets, for which multiple occurrences with distinct values
13602 * are allowed.
13603 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013604 if (item->baseType->facetSet != NULL) {
13605 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013606 if (last != NULL)
13607 while (last->next != NULL)
13608 last = last->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013609 cur = item->baseType->facetSet;
13610 for (; cur != NULL; cur = cur->next) {
13611 /*
13612 * Base patterns won't be add here:
13613 * they are ORed in a type and
13614 * ANDed in derived types. This will
13615 * happed at validation level by
13616 * walking the base axis of the type.
13617 */
13618 if (cur->facet->type ==
13619 XML_SCHEMA_FACET_PATTERN)
13620 continue;
13621 facet = NULL;
13622 if ((item->facetSet != NULL) &&
13623 /* REMOVED: a check for
13624 * XML_SCHEMA_FACET_PATTERN was already
13625 * performed above.
13626
13627 * (cur->facet->type !=
13628 * XML_SCHEMA_FACET_PATTERN) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000013629 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013630 (cur->facet->type !=
13631 XML_SCHEMA_FACET_ENUMERATION)) {
13632 facet = item->facetSet;
13633 do {
13634 if (cur->facet->type ==
13635 facet->facet->type)
13636 break;
13637 facet = facet->next;
13638 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013639 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013640 if (facet == NULL) {
13641 facet = (xmlSchemaFacetLinkPtr)
13642 xmlMalloc(sizeof(xmlSchemaFacetLink));
13643 if (facet == NULL) {
13644 xmlSchemaPErrMemory(ctxt,
13645 "fixing simpleType", NULL);
13646 return;
13647 }
13648 /*
13649 * The facets are not copied but referenced
13650 * via the facet link.
13651 */
13652 facet->facet = cur->facet;
13653 facet->next = NULL;
13654 if (last == NULL)
13655 item->facetSet = facet;
13656 else
13657 last->next = facet;
13658 last = facet;
13659 }
13660 }
13661 }
13662 /*
13663 * Some optimization for validation:
13664 * If there are no facets beside the "whitespace" facet,
13665 * then a value needs not to checked against against a
13666 * facet, thus no computed value is needed.
13667 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000013668 if (item->baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013669 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13670 else {
13671 for (cur = item->facetSet; cur != NULL;
13672 cur = cur->next) {
13673 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13674 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13675 break;
13676 }
13677 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013678 }
13679 }
13680 }
13681 /*
13682 * Check constraints.
13683 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013684 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013685 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013686 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013687 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013688 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013689 case XML_SCHEMA_TYPE_ALL:
13690 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013691 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013692 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013693 case XML_SCHEMA_TYPE_GROUP:
13694 /*
13695 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
13696 */
13697 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013698 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013699 xmlSchemaParseListRefFixup(item, ctxt);
13700 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013701 break;
13702 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013703 xmlSchemaParseUnionRefCheck(item, ctxt);
13704 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013705 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013706 case XML_SCHEMA_TYPE_BASIC:
13707 case XML_SCHEMA_TYPE_ANY:
13708 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013709 case XML_SCHEMA_TYPE_UR:
13710 case XML_SCHEMA_TYPE_ELEMENT:
13711 case XML_SCHEMA_TYPE_ATTRIBUTE:
13712 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000013713 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013714 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013715 case XML_SCHEMA_FACET_MININCLUSIVE:
13716 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13717 case XML_SCHEMA_FACET_MAXINCLUSIVE:
13718 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13719 case XML_SCHEMA_FACET_TOTALDIGITS:
13720 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13721 case XML_SCHEMA_FACET_PATTERN:
13722 case XML_SCHEMA_FACET_ENUMERATION:
13723 case XML_SCHEMA_FACET_WHITESPACE:
13724 case XML_SCHEMA_FACET_LENGTH:
13725 case XML_SCHEMA_FACET_MAXLENGTH:
13726 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013727 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13728 if (item->subtypes != NULL)
13729 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013730 break;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000013731 case XML_SCHEMA_TYPE_IDC_UNIQUE:
13732 case XML_SCHEMA_TYPE_IDC_KEY:
13733 case XML_SCHEMA_TYPE_IDC_KEYREF:
13734 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013735 }
13736 }
Daniel Veillard8651f532002-04-17 09:06:27 +000013737#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013738 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013739 xmlGenericError(xmlGenericErrorContext,
13740 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013741 item->node->doc->URL,
13742 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013743 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013744 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013745 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013746 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013747 case XML_SCHEMA_CONTENT_SIMPLE:
13748 xmlGenericError(xmlGenericErrorContext, "simple\n");
13749 break;
13750 case XML_SCHEMA_CONTENT_ELEMENTS:
13751 xmlGenericError(xmlGenericErrorContext, "elements\n");
13752 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013753 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013754 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
13755 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013756 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013757 xmlGenericError(xmlGenericErrorContext, "empty\n");
13758 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013759 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013760 xmlGenericError(xmlGenericErrorContext, "mixed\n");
13761 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013762 /* Removed, since not used. */
13763 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000013764 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013765 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
13766 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013767 */
Daniel Veillard8651f532002-04-17 09:06:27 +000013768 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013769 xmlGenericError(xmlGenericErrorContext, "basic\n");
13770 break;
13771 default:
13772 xmlGenericError(xmlGenericErrorContext,
13773 "not registered !!!\n");
13774 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013775 }
13776#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013777}
13778
13779/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013780 * xmlSchemaCheckFacet:
13781 * @facet: the facet
13782 * @typeDecl: the schema type definition
13783 * @ctxt: the schema parser context or NULL
13784 * @name: name of the type
13785 *
13786 * Checks the default values types, especially for facets
13787 *
13788 * Returns 0 if okay or -1 in cae of error
13789 */
13790int
13791xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013792 xmlSchemaTypePtr typeDecl,
13793 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013794{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013795 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013796 int ret = 0, reuseValCtxt = 0;
13797
Daniel Veillardce682bc2004-11-05 17:22:25 +000013798 if ((facet == NULL) || (typeDecl == NULL))
13799 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013800 /*
13801 * TODO: will the parser context be given if used from
13802 * the relaxNG module?
13803 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013804
13805 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013806 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013807 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013808 }
13809 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013810 case XML_SCHEMA_FACET_MININCLUSIVE:
13811 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13812 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013813 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13814 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013815 /*
13816 * Okay we need to validate the value
13817 * at that point.
13818 */
13819 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013820 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013821
13822 /* 4.3.5.5 Constraints on enumeration Schema Components
13823 * Schema Component Constraint: enumeration valid restriction
13824 * It is an ·error· if any member of {value} is not in the
13825 * ·value space· of {base type definition}.
13826 *
13827 * minInclusive, maxInclusive, minExclusive, maxExclusive:
13828 * The value ·must· be in the
13829 * ·value space· of the ·base type·.
13830 */
13831 /*
13832 * This function is intended to deliver a compiled value
13833 * on the facet. In XML Schemas the type holding a facet,
13834 * cannot be a built-in type. Thus to ensure that other API
13835 * calls (relaxng) do work, if the given type is a built-in
13836 * type, we will assume that the given built-in type *is
13837 * already* the base type.
13838 */
13839 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
13840 base = typeDecl->baseType;
13841 if (base == NULL) {
13842 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013843 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013844 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013845 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013846 typeDecl->name, NULL);
13847 return (-1);
13848 }
13849 } else
13850 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013851 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013852 * This avoids perseverative creation of the
13853 * validation context if a parser context is
13854 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013855 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013856 if (ctxt != NULL) {
13857 reuseValCtxt = 1;
13858 if (ctxt->vctxt == NULL) {
13859 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13860 return (-1);
13861 }
13862 vctxt = ctxt->vctxt;
13863 } else {
13864 vctxt = xmlSchemaNewValidCtxt(NULL);
13865 if (vctxt == NULL) {
13866 xmlSchemaPErr(ctxt, typeDecl->node,
13867 XML_SCHEMAP_INTERNAL,
13868 "Internal error: xmlSchemaCheckFacet, "
13869 "creating a new validation context.\n",
13870 NULL, NULL);
13871 return (-1);
13872 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013873 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013874
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013875 vctxt->node = facet->node;
13876 vctxt->cur = NULL;
13877 /*
13878 * NOTE: This call does not check the content nodes,
13879 * since they are not available:
13880 * facet->node is just the node holding the facet
13881 * definition, *not* the attribute holding the *value*
13882 * of the facet.
13883 */
13884 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
13885 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013886 facet->val = vctxt->value;
13887 vctxt->value = NULL;
13888 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013889 /* error code */
13890 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013891 xmlSchemaPErrExt(ctxt, facet->node,
13892 XML_SCHEMAP_INVALID_FACET,
13893 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013894 "Type definition '%s': The value '%s' of the "
13895 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013896 name, facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000013897 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000013898 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013899 }
13900 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013901 } else if (ret < 0) {
13902 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013903 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013904 NULL, NULL, NULL,
13905 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013906 "failed to validate the value '%s' name of the "
13907 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013908 facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000013909 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013910 base->name, NULL, NULL);
13911 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013912 }
13913 if (reuseValCtxt == 0)
13914 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013915 break;
13916 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013917 case XML_SCHEMA_FACET_PATTERN:
13918 facet->regexp = xmlRegexpCompile(facet->value);
13919 if (facet->regexp == NULL) {
13920 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013921 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013922 "Type definition '%s': The value '%s' of the "
13923 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013924 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013925 ret = -1;
13926 }
13927 break;
13928 case XML_SCHEMA_FACET_TOTALDIGITS:
13929 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13930 case XML_SCHEMA_FACET_LENGTH:
13931 case XML_SCHEMA_FACET_MAXLENGTH:
13932 case XML_SCHEMA_FACET_MINLENGTH:{
13933 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013934
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013935 tmp =
13936 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
13937 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013938 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013939 if (tmp != 0) {
13940 /* error code */
13941 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013942 xmlSchemaPErrExt(ctxt, facet->node,
13943 XML_SCHEMAP_INVALID_FACET_VALUE,
13944 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013945 "Type definition '%s': The value '%s' of the "
13946 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013947 name, facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000013948 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000013949 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013950 }
13951 ret = -1;
13952 }
13953 break;
13954 }
13955 case XML_SCHEMA_FACET_WHITESPACE:{
13956 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
13957 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
13958 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
13959 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
13960 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
13961 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
13962 } else {
13963 if (ctxt != NULL) {
13964 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013965 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013966 "Type definition '%s': The value '%s' of the "
13967 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013968 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013969 }
13970 ret = -1;
13971 }
13972 }
13973 default:
13974 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013975 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013976 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013977}
13978
13979/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013980 * xmlSchemaCheckDefaults:
13981 * @typeDecl: the schema type definition
13982 * @ctxt: the schema parser context
13983 *
13984 * Checks the default values types, especially for facets
13985 */
13986static void
13987xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013988 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013989{
Daniel Veillard4255d502002-04-16 15:50:10 +000013990 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013991 name = typeDecl->name;
13992 /*
13993 * NOTE: It is intended to use the facets list, instead
13994 * of facetSet.
13995 */
13996 if (typeDecl->facets != NULL) {
13997 xmlSchemaFacetPtr facet = typeDecl->facets;
13998
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000013999 /*
14000 * Temporarily assign the "schema" to the validation context
14001 * of the parser context. This is needed for NOTATION validation.
14002 */
14003 if (ctxt->vctxt == NULL) {
14004 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14005 return;
14006 }
14007 ctxt->vctxt->schema = ctxt->schema;
14008
Daniel Veillard01fa6152004-06-29 17:04:39 +000014009 while (facet != NULL) {
14010 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
14011 facet = facet->next;
14012 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014013
14014 ctxt->vctxt->schema = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014015 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014016}
14017
14018/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014019 * xmlSchemaGetCircModelGrDefRef:
14020 * @ctxtGr: the searched model group
14021 * @list: the list of model groups to be processed
14022 *
14023 * This one is intended to be used by
14024 * xmlSchemaCheckGroupDefCircular only.
14025 *
14026 * Returns the circular model group definition reference, otherwise NULL.
14027 */
14028static xmlSchemaTypePtr
14029xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
14030 xmlSchemaTypePtr gr)
14031{
14032 xmlSchemaTypePtr circ = NULL;
14033 int marked;
14034 /*
14035 * We will search for an model group reference which
14036 * references the context model group definition.
14037 */
14038 while (gr != NULL) {
14039 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
14040 (gr->type == XML_SCHEMA_TYPE_ALL) ||
14041 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
14042 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
14043 (gr->subtypes != NULL)) {
14044 marked = 0;
14045 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
14046 (gr->ref != NULL)) {
14047 if (gr->subtypes == ctxtGrDef)
14048 return (gr);
14049 else if (gr->subtypes->flags &
14050 XML_SCHEMAS_TYPE_MARKED) {
14051 gr = gr->next;
14052 continue;
14053 } else {
14054 /*
14055 * Mark to avoid infinite recursion on
14056 * circular references not yet examined.
14057 */
14058 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
14059 marked = 1;
14060 }
14061 if (gr->subtypes->subtypes != NULL)
14062 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
14063 gr->subtypes->subtypes);
14064 /*
14065 * Unmark the visited model group definition.
14066 */
14067 if (marked)
14068 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
14069 if (circ != NULL)
14070 return (circ);
14071 } else {
14072 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
14073 (xmlSchemaTypePtr) gr->subtypes);
14074 if (circ != NULL)
14075 return (circ);
14076 }
14077
14078 }
14079 gr = gr->next;
14080 }
14081 return (NULL);
14082}
14083
14084/**
14085 * xmlSchemaCheckGroupDefCircular:
14086 * attrGr: the model group definition
14087 * @ctxt: the parser context
14088 * @name: the name
14089 *
14090 * Checks for circular references to model group definitions.
14091 */
14092static void
14093xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
14094 xmlSchemaParserCtxtPtr ctxt,
14095 const xmlChar * name ATTRIBUTE_UNUSED)
14096{
14097 /*
14098 * Schema Component Constraint: Model Group Correct
14099 * 2 Circular groups are disallowed. That is, within the {particles}
14100 * of a group there must not be at any depth a particle whose {term}
14101 * is the group itself.
14102 */
14103 /*
14104 * NOTE: "gr->subtypes" holds the referenced group.
14105 */
14106 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
14107 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
14108 (modelGrDef->subtypes == NULL))
14109 return;
14110 else {
14111 xmlSchemaTypePtr circ;
14112
14113 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
14114 if (circ != NULL) {
14115 /*
14116 * TODO: Report the referenced attr group as QName.
14117 */
14118 xmlSchemaPCustomErr(ctxt,
14119 XML_SCHEMAP_MG_PROPS_CORRECT_2,
14120 NULL, NULL, circ->node,
14121 "Circular reference to the model group definition '%s' "
14122 "defined", modelGrDef->name);
14123 /*
14124 * NOTE: We will cut the reference to avoid further
14125 * confusion of the processor.
14126 * TODO: SPEC: Does the spec define how to process here?
14127 */
14128 circ->subtypes = NULL;
14129 }
14130 }
14131}
14132
14133
14134/**
14135 * xmlSchemaGetCircAttrGrRef:
14136 * @ctxtGr: the searched attribute group
14137 * @attr: the current attribute list to be processed
14138 *
14139 * This one is intended to be used by
14140 * xmlSchemaCheckSRCAttributeGroupCircular only.
14141 *
14142 * Returns the circular attribute grou reference, otherwise NULL.
14143 */
14144static xmlSchemaAttributeGroupPtr
14145xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
14146 xmlSchemaAttributePtr attr)
14147{
14148 xmlSchemaAttributeGroupPtr circ = NULL, gr;
14149 int marked;
14150 /*
14151 * We will search for an attribute group reference which
14152 * references the context attribute group.
14153 */
14154 while (attr != NULL) {
14155 marked = 0;
14156 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
14157 gr = (xmlSchemaAttributeGroupPtr) attr;
14158 if (gr->refItem != NULL) {
14159 if (gr->refItem == ctxtGr)
14160 return (gr);
14161 else if (gr->refItem->flags &
14162 XML_SCHEMAS_ATTRGROUP_MARKED) {
14163 attr = attr->next;
14164 continue;
14165 } else {
14166 /*
14167 * Mark as visited to avoid infinite recursion on
14168 * circular references not yet examined.
14169 */
14170 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
14171 marked = 1;
14172 }
14173 }
14174 if (gr->attributes != NULL)
14175 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
14176 /*
14177 * Unmark the visited group's attributes.
14178 */
14179 if (marked)
14180 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
14181 if (circ != NULL)
14182 return (circ);
14183 }
14184 attr = attr->next;
14185 }
14186 return (NULL);
14187}
14188
14189/**
14190 * xmlSchemaCheckSRCAttributeGroupCircular:
14191 * attrGr: the attribute group definition
14192 * @ctxt: the parser context
14193 * @name: the name
14194 *
14195 * Checks for circular references of attribute groups.
14196 */
14197static void
14198xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
14199 xmlSchemaParserCtxtPtr ctxt,
14200 const xmlChar * name ATTRIBUTE_UNUSED)
14201{
14202 /*
14203 * Schema Representation Constraint:
14204 * Attribute Group Definition Representation OK
14205 * 3 Circular group reference is disallowed outside <redefine>.
14206 * That is, unless this element information item's parent is
14207 * <redefine>, then among the [children], if any, there must
14208 * not be an <attributeGroup> with ref [attribute] which resolves
14209 * to the component corresponding to this <attributeGroup>. Indirect
14210 * circularity is also ruled out. That is, when QName resolution
14211 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
14212 * any <attributeGroup>s with a ref [attribute] among the [children],
14213 * it must not be the case that a ·QName· is encountered at any depth
14214 * which resolves to the component corresponding to this <attributeGroup>.
14215 */
14216 /*
14217 * Only global components can be referenced.
14218 */
14219 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
14220 (attrGr->attributes == NULL))
14221 return;
14222 else {
14223 xmlSchemaAttributeGroupPtr circ;
14224
14225 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
14226 if (circ != NULL) {
14227 /*
14228 * TODO: Report the referenced attr group as QName.
14229 */
14230 xmlSchemaPCustomErr(ctxt,
14231 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
14232 NULL, NULL, circ->node,
14233 "Circular reference to the attribute group '%s' "
14234 "defined", attrGr->name);
14235 /*
14236 * NOTE: We will cut the reference to avoid further
14237 * confusion of the processor.
14238 * BADSPEC: The spec should define how to process in this case.
14239 */
14240 circ->attributes = NULL;
14241 circ->refItem = NULL;
14242 }
14243 }
14244}
14245
14246/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000014247 * xmlSchemaAttrGrpFixup:
14248 * @attrgrpDecl: the schema attribute definition
14249 * @ctxt: the schema parser context
14250 * @name: the attribute name
14251 *
14252 * Fixes finish doing the computations on the attributes definitions
14253 */
14254static void
Daniel Veillard3646d642004-06-02 19:19:14 +000014255xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014256 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000014257{
14258 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000014259 name = attrgrp->name;
14260 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014261 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000014262 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014263 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000014264
Daniel Veillardc0826a72004-08-10 14:17:33 +000014265 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
14266 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014267 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014268 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014269 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014270 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
14271 "ref", attrgrp->ref, attrgrp->refNs,
14272 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014273 return;
14274 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014275 attrgrp->refItem = ref;
14276 /*
14277 * Check for self reference!
14278 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014279 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000014280 attrgrp->attributes = ref->attributes;
14281 attrgrp->attributeWildcard = ref->attributeWildcard;
14282 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000014283}
14284
14285/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014286 * xmlSchemaAttrCheckValConstr:
14287 * @item: an schema attribute declaration/use
14288 * @ctxt: a schema parser context
14289 * @name: the name of the attribute
14290 *
14291 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000014292 *
14293 * Fixes finish doing the computations on the attributes definitions
14294 */
14295static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014296xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
14297 xmlSchemaParserCtxtPtr ctxt,
14298 const xmlChar * name ATTRIBUTE_UNUSED)
14299{
14300
14301 /*
14302 * a-props-correct
14303 * Schema Component Constraint: Attribute Declaration Properties Correct
14304 *
14305 * 2 if there is a {value constraint}, the canonical lexical
14306 * representation of its value must be ·valid· with respect
14307 * to the {type definition} as defined in String Valid (§3.14.4).
14308 */
14309
14310 if (item->defValue != NULL) {
14311 int ret;
14312 xmlNodePtr node;
14313 xmlSchemaTypePtr type;
14314
14315 if (item->subtypes == NULL) {
14316 xmlSchemaPErr(ctxt, item->node,
14317 XML_SCHEMAP_INTERNAL,
14318 "Internal error: xmlSchemaCheckAttrValConstr, "
14319 "type is missing... skipping validation of "
14320 "value constraint", NULL, NULL);
14321 return;
14322 }
14323
14324 /*
14325 * TODO: Try to avoid creating a new context.
14326 * TODO: This all is not very performant.
14327 */
14328 type = item->subtypes;
14329 /*
14330 * Ensure there's validation context.
14331 */
14332 if (ctxt->vctxt == NULL) {
14333 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
14334 xmlSchemaPErr(ctxt, item->node,
14335 XML_SCHEMAP_INTERNAL,
14336 "Internal error: xmlSchemaCheckAttrValConstr, "
14337 "creating a new validation context.\n",
14338 NULL, NULL);
14339 return;
14340 }
14341 }
14342
14343 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
14344 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
14345 else
14346 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
14347 ctxt->vctxt->node = node;
14348 ctxt->vctxt->cur = NULL;
14349 /*
14350 * NOTE: This call does not check the content nodes,
14351 * since they are not available:
14352 * facet->node is just the node holding the facet
14353 * definition, *not* the attribute holding the *value*
14354 * of the facet.
14355 */
14356 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
14357 item->defValue, 0, 1, 1, 0);
14358 if (ret == 0) {
14359 /*
14360 * Store the computed value.
14361 */
14362 item->defVal = ctxt->vctxt->value;
14363 ctxt->vctxt->value = NULL;
14364 } else if (ret > 0) {
14365 if (ctxt != NULL) {
14366 xmlSchemaPSimpleTypeErr(ctxt,
14367 XML_SCHEMAP_A_PROPS_CORRECT_2,
14368 NULL, NULL, node,
14369 type, NULL, item->defValue,
14370 NULL, NULL, NULL);
14371 }
14372 } else if (ret < 0) {
14373 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14374 NULL, NULL, node,
14375 "Internal error: xmlSchemaAttrCheckValConstr, "
14376 "failed to validate the value constraint of the "
14377 "attribute decl/use against the type '%s'",
14378 type->name);
14379 }
14380 }
14381}
14382
14383#if 0 /* Not used yet. */
14384static int
14385xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
14386 xmlSchemaElementPtr edecl)
14387{
14388 /*
14389 * TODO: 1 The values of the properties of an element declaration must be as
14390 * described in the property tableau in The Element Declaration Schema
14391 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
14392 */
14393 /*
14394 * 2 If there is a {value constraint}, the canonical lexical
14395 * representation of its value must be ·valid· with respect to the {type
14396 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14397 *
14398 * NOTE: This is done in xmlSchemaCheckElemValConstr.
14399 */
14400 /*
14401 * 3 If there is a non-·absent· {substitution group affiliation},
14402 * then {scope} must be global.
14403 *
14404 * NOTE: This is done in xmlSchemaParseElement.
14405 * TODO: Move it to this layer here.
14406 */
14407 /*
14408 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
14409 * of the element declaration must be validly derived from the {type
14410 * definition} of the {substitution group affiliation}, given the value
14411 * of the {substitution group exclusions} of the {substitution group
14412 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
14413 * (if the {type definition} is complex) or as defined in
14414 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
14415 * simple).
14416 */
14417 /*
14418 * TODO: 5 If the {type definition} or {type definition}'s {content type}
14419 * is or is derived from ID then there must not be a {value constraint}.
14420 * Note: The use of ID as a type definition for elements goes beyond
14421 * XML 1.0, and should be avoided if backwards compatibility is desired
14422 */
14423 /*
14424 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
14425 * be possible to return to an element declaration by repeatedly following
14426 * the {substitution group affiliation} property.
14427 */
14428}
14429#endif
14430
14431/**
14432 * xmlSchemaCheckElemValConstr:
14433 * @item: an schema element declaration/particle
14434 * @ctxt: a schema parser context
14435 * @name: the name of the attribute
14436 *
14437 * Validates the value constraints of an element declaration.
14438 *
14439 * Fixes finish doing the computations on the element declarations.
14440 */
14441static void
14442xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
14443 xmlSchemaParserCtxtPtr ctxt,
14444 const xmlChar * name ATTRIBUTE_UNUSED)
14445{
14446 if (decl->value != NULL) {
14447 int ret;
14448 xmlNodePtr node = NULL;
14449 xmlSchemaTypePtr type;
14450
14451 /*
14452 * 2 If there is a {value constraint}, the canonical lexical
14453 * representation of its value must be ·valid· with respect to the {type
14454 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14455 */
14456 if (decl->subtypes == NULL) {
14457 xmlSchemaPErr(ctxt, decl->node,
14458 XML_SCHEMAP_INTERNAL,
14459 "Internal error: xmlSchemaCheckElemValConstr, "
14460 "type is missing... skipping validation of "
14461 "the value constraint", NULL, NULL);
14462 return;
14463 }
14464 /*
14465 * Ensure there's a validation context.
14466 */
14467 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14468 return;
14469
14470 type = decl->subtypes;
14471
14472 if (decl->node != NULL) {
14473 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
14474 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
14475 else
14476 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
14477 }
14478 ctxt->vctxt->node = node;
14479 ctxt->vctxt->cur = NULL;
14480 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
14481 node);
14482 if (ret == 0) {
14483 /*
14484 * Consume the computed value.
14485 */
14486 decl->defVal = ctxt->vctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014487 ctxt->vctxt->value = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014488 } else if (ret < 0) {
14489 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14490 NULL, NULL, node,
14491 "Internal error: xmlSchemaElemCheckValConstr, "
14492 "failed to validate the value constraint of the "
14493 "element declaration '%s'",
14494 decl->name);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014495 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014496 }
14497}
14498
14499/**
14500 * xmlSchemaAttrFixup:
14501 * @item: an schema attribute declaration/use.
14502 * @ctxt: a schema parser context
14503 * @name: the name of the attribute
14504 *
14505 * Fixes finish doing the computations on attribute declarations/uses.
14506 */
14507static void
14508xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
14509 xmlSchemaParserCtxtPtr ctxt,
14510 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000014511{
Daniel Veillardc0826a72004-08-10 14:17:33 +000014512 /*
14513 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014514 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000014515 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014516 /*
14517 * The simple type definition corresponding to the <simpleType> element
14518 * information item in the [children], if present, otherwise the simple
14519 * type definition ·resolved· to by the ·actual value· of the type
14520 * [attribute], if present, otherwise the ·simple ur-type definition·.
14521 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014522 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014523 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014524 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
14525 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014526 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014527 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014528 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000014529
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014530 type = xmlSchemaGetType(ctxt->schema, item->typeName,
14531 item->typeNs);
14532 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014533 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014534 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014535 NULL, (xmlSchemaTypePtr) item, item->node,
14536 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014537 XML_SCHEMA_TYPE_SIMPLE, NULL);
14538 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014539 item->subtypes = type;
14540
14541 } else if (item->ref != NULL) {
14542 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000014543
Daniel Veillardc0826a72004-08-10 14:17:33 +000014544 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014545 * We have an attribute use here; assign the referenced
14546 * attribute declaration.
14547 */
14548 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014549 * TODO: Evaluate, what errors could occur if the declaration is not
14550 * found. It might be possible that the "typefixup" might crash if
14551 * no ref declaration was found.
14552 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014553 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
14554 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014555 xmlSchemaPResCompAttrErr(ctxt,
14556 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014557 NULL, (xmlSchemaTypePtr) item, item->node,
14558 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014559 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014560 return;
14561 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014562 item->refDecl = decl;
14563 xmlSchemaAttrFixup(decl, ctxt, NULL);
14564
14565 item->subtypes = decl->subtypes;
14566 /*
14567 * Attribute Use Correct
14568 * au-props-correct.2: If the {attribute declaration} has a fixed
14569 * {value constraint}, then if the attribute use itself has a
14570 * {value constraint}, it must also be fixed and its value must match
14571 * that of the {attribute declaration}'s {value constraint}.
14572 */
14573 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
14574 (item->defValue != NULL)) {
14575 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
14576 (!xmlStrEqual(item->defValue, decl->defValue))) {
14577 xmlSchemaPCustomErr(ctxt,
14578 XML_SCHEMAP_AU_PROPS_CORRECT_2,
14579 NULL, NULL, item->node,
14580 "The value constraint must be fixed "
14581 "and match the referenced attribute "
14582 "declarations's value constraint '%s'",
14583 decl->defValue);
14584 }
14585 /*
14586 * FUTURE: One should change the values of the attr. use
14587 * if ever validation should be attempted even if the
14588 * schema itself was not fully valid.
14589 */
14590 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014591 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014592 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14593 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014594}
14595
14596/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014597 * xmlSchemaResolveIDCKeyRef:
14598 * @idc: the identity-constraint definition
14599 * @ctxt: the schema parser context
14600 * @name: the attribute name
14601 *
14602 * Resolve keyRef references to key/unique IDCs.
14603 */
14604static void
14605xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
14606 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000014607 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014608{
14609 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
14610 return;
14611 if (idc->ref->name != NULL) {
14612 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
14613 ctxt->schema->idcDef,
14614 idc->ref->name,
14615 idc->ref->targetNamespace);
14616 if (idc->ref->item == NULL) {
14617 /*
14618 * TODO: It is actually not an error to fail to resolve.
14619 */
14620 xmlSchemaPResCompAttrErr(ctxt,
14621 XML_SCHEMAP_SRC_RESOLVE,
14622 NULL, (xmlSchemaTypePtr) idc, idc->node,
14623 "refer", idc->ref->name,
14624 idc->ref->targetNamespace,
14625 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
14626 return;
14627 }
14628 }
14629}
14630
14631/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014632 * xmlSchemaParse:
14633 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014634 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014635 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000014636 * XML Shema struture which can be used to validate instances.
14637 * *WARNING* this interface is highly subject to change
14638 *
14639 * Returns the internal XML Schema structure built from the resource or
14640 * NULL in case of error
14641 */
14642xmlSchemaPtr
14643xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
14644{
14645 xmlSchemaPtr ret = NULL;
14646 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014647 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014648 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014649
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014650 /*
14651 * This one is used if the schema to be parsed was specified via
14652 * the API; i.e. not automatically by the validated instance document.
14653 */
14654
Daniel Veillard4255d502002-04-16 15:50:10 +000014655 xmlSchemaInitTypes();
14656
Daniel Veillard6045c902002-10-09 21:13:59 +000014657 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000014658 return (NULL);
14659
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014660 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014661 ctxt->counter = 0;
14662 ctxt->container = NULL;
14663
14664 /*
14665 * First step is to parse the input document into an DOM/Infoset
14666 */
Daniel Veillard6045c902002-10-09 21:13:59 +000014667 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014668 doc = xmlReadFile((const char *) ctxt->URL, NULL,
14669 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014670 if (doc == NULL) {
14671 xmlSchemaPErr(ctxt, NULL,
14672 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014673 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014674 ctxt->URL, NULL);
14675 return (NULL);
14676 }
Daniel Veillard6045c902002-10-09 21:13:59 +000014677 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014678 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
14679 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014680 if (doc == NULL) {
14681 xmlSchemaPErr(ctxt, NULL,
14682 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014683 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014684 NULL, NULL);
14685 return (NULL);
14686 }
14687 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000014688 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000014689 } else if (ctxt->doc != NULL) {
14690 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014691 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000014692 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014693 xmlSchemaPErr(ctxt, NULL,
14694 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014695 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014696 NULL, NULL);
14697 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014698 }
14699
14700 /*
14701 * Then extract the root and Schema parse it
14702 */
14703 root = xmlDocGetRootElement(doc);
14704 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014705 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
14706 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014707 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000014708 if (!preserve) {
14709 xmlFreeDoc(doc);
14710 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014711 return (NULL);
14712 }
14713
14714 /*
14715 * Remove all the blank text nodes
14716 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014717 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000014718
14719 /*
14720 * Then do the parsing for good
14721 */
14722 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000014723 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000014724 if (!preserve) {
14725 xmlFreeDoc(doc);
14726 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014727 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000014728 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014729 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014730 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000014731 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014732 ctxt->ctxtType = NULL;
14733 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000014734 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000014735 * Then fixup all attributes declarations
14736 */
14737 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
14738
14739 /*
14740 * Then fixup all attributes group declarations
14741 */
14742 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
14743 ctxt);
14744
14745 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014746 * Resolve identity-constraint keyRefs.
14747 */
14748 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
14749
14750 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014751 * Check attribute groups for circular references.
14752 */
14753 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
14754 xmlSchemaCheckAttributeGroupCircular, ctxt);
14755
14756 /*
14757 * Then fixup all model group definitions.
14758 */
14759 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014760
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014761 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000014762 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000014763 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014764 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014765
14766 /*
14767 * Then fix references of element declaration; apply constraints.
14768 */
14769 xmlHashScanFull(ret->elemDecl,
14770 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014771
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014772 /*
14773 * Check model groups defnitions for circular references.
14774 */
14775 xmlHashScan(ret->groupDecl, (xmlHashScanner)
14776 xmlSchemaCheckGroupDefCircular, ctxt);
14777
Daniel Veillard4255d502002-04-16 15:50:10 +000014778 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014779 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000014780 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014781 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014782 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014783
14784 /*
14785 * Then check the defaults part of the type like facets values
14786 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014787 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000014788
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014789 /*
14790 * Validate the value constraint of attribute declarations/uses.
14791 */
14792 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
14793
14794 /*
14795 * Validate the value constraint of element declarations.
14796 */
14797 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
14798
Daniel Veillardc0826a72004-08-10 14:17:33 +000014799
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014800 if (ctxt->nberrors != 0) {
14801 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014802 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014803 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014804 return (ret);
14805}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014806
Daniel Veillard4255d502002-04-16 15:50:10 +000014807/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000014808 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000014809 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000014810 * @err: the error callback
14811 * @warn: the warning callback
14812 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000014813 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014814 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014815 */
14816void
14817xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014818 xmlSchemaValidityErrorFunc err,
14819 xmlSchemaValidityWarningFunc warn, void *ctx)
14820{
Daniel Veillard4255d502002-04-16 15:50:10 +000014821 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014822 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000014823 ctxt->error = err;
14824 ctxt->warning = warn;
14825 ctxt->userData = ctx;
14826}
14827
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014828/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000014829 * xmlSchemaGetParserErrors:
14830 * @ctxt: a XMl-Schema parser context
14831 * @err: the error callback result
14832 * @warn: the warning callback result
14833 * @ctx: contextual data for the callbacks result
14834 *
14835 * Get the callback information used to handle errors for a parser context
14836 *
14837 * Returns -1 in case of failure, 0 otherwise
14838 */
14839int
14840xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
14841 xmlSchemaValidityErrorFunc * err,
14842 xmlSchemaValidityWarningFunc * warn, void **ctx)
14843{
14844 if (ctxt == NULL)
14845 return(-1);
14846 if (err != NULL)
14847 *err = ctxt->error;
14848 if (warn != NULL)
14849 *warn = ctxt->warning;
14850 if (ctx != NULL)
14851 *ctx = ctxt->userData;
14852 return(0);
14853}
14854
14855/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014856 * xmlSchemaFacetTypeToString:
14857 * @type: the facet type
14858 *
14859 * Convert the xmlSchemaTypeType to a char string.
14860 *
14861 * Returns the char string representation of the facet type if the
14862 * type is a facet and an "Internal Error" string otherwise.
14863 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014864static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014865xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
14866{
14867 switch (type) {
14868 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014869 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014870 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014871 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014872 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014873 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014874 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014875 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014876 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014877 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014878 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014879 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014880 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014881 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014882 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014883 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014884 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014885 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014886 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014887 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014888 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014889 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014890 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014891 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014892 default:
14893 break;
14894 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014895 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014896}
14897
Daniel Veillardc0826a72004-08-10 14:17:33 +000014898static int
14899xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
14900{
14901 xmlSchemaTypePtr anc;
14902
14903 /*
14904 * The normalization type can be changed only for types which are derived
14905 * from xsd:string.
14906 */
14907 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000014908 if (type->builtInType == XML_SCHEMAS_STRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014909 return(XML_SCHEMAS_FACET_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000014910 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014911 return(XML_SCHEMAS_FACET_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014912 else {
14913 /*
14914 * For all ·atomic· datatypes other than string (and types ·derived·
14915 * by ·restriction· from it) the value of whiteSpace is fixed to
14916 * collapse
14917 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014918 return(XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014919 }
14920 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14921 /*
14922 * For list types the facet "whiteSpace" is fixed to "collapse".
14923 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014924 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014925 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014926 return (XML_SCHEMAS_FACET_UNKNOWN);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014927 } else if (type->facetSet != NULL) {
14928 xmlSchemaTypePtr anyST;
14929 xmlSchemaFacetLinkPtr lin;
14930
14931 /*
14932 * Atomic types.
14933 */
14934 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14935 anc = type->baseType;
14936 do {
14937 /*
14938 * For all ·atomic· datatypes other than string (and types ·derived·
14939 * by ·restriction· from it) the value of whiteSpace is fixed to
14940 * collapse
14941 */
14942 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
14943 (anc->builtInType == XML_SCHEMAS_STRING)) {
14944
14945 lin = type->facetSet;
14946 do {
14947 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014948 return(lin->facet->whitespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014949 break;
14950 }
14951 lin = lin->next;
14952 } while (lin != NULL);
14953 break;
14954 }
14955 anc = anc->baseType;
14956 } while (anc != anyST);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014957 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014958 }
14959 return (-1);
14960}
14961
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014962/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000014963 * xmlSchemaValidateFacetsInternal:
14964 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000014965 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000014966 * @facets: the list of facets to check
14967 * @value: the lexical repr of the value to validate
14968 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000014969 * @fireErrors: if 0, only internal errors will be fired;
14970 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000014971 *
14972 * Check a value against all facet conditions
14973 *
14974 * Returns 0 if the element is schemas valid, a positive error code
14975 * number otherwise and -1 in case of internal or API error.
14976 */
14977static int
14978xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014979 xmlSchemaTypePtr type,
14980 const xmlChar * value,
14981 unsigned long length,
14982 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000014983{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014984 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014985 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014986 xmlSchemaTypePtr biType; /* The build-in type. */
14987 xmlSchemaTypePtr tmpType;
14988 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000014989 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014990 xmlSchemaFacetPtr facet;
14991 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014992
Daniel Veillardc0826a72004-08-10 14:17:33 +000014993#ifdef DEBUG_UNION_VALIDATION
14994 printf("Facets of type: '%s'\n", (const char *) type->name);
14995 printf(" fireErrors: %d\n", fireErrors);
14996#endif
14997
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014998 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014999 /*
15000 * NOTE: Do not jump away, if the facetSet of the given type is
15001 * empty: until now, "pattern" facets of the *base types* need to
15002 * be checked as well.
15003 */
15004 biType = type->baseType;
15005 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
15006 biType = biType->baseType;
15007 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015008 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015009 "Internal error: xmlSchemaValidateFacetsInternal, "
15010 "the base type axis of the given type '%s' does not resolve to "
15011 "a built-in type.\n",
15012 type->name, NULL);
15013 return (-1);
15014 }
15015
15016 if (type->facetSet != NULL) {
15017 facetLink = type->facetSet;
15018 while (facetLink != NULL) {
15019 facet = facetLink->facet;
15020 /*
15021 * Skip the pattern "whiteSpace": it is used to
15022 * format the character content beforehand.
15023 */
15024 switch (facet->type) {
15025 case XML_SCHEMA_FACET_WHITESPACE:
15026 case XML_SCHEMA_FACET_PATTERN:
15027 case XML_SCHEMA_FACET_ENUMERATION:
15028 break;
15029 case XML_SCHEMA_FACET_LENGTH:
15030 case XML_SCHEMA_FACET_MINLENGTH:
15031 case XML_SCHEMA_FACET_MAXLENGTH:
15032 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15033 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
15034 value, length, 0);
15035 len = length;
15036 } else
15037 ret = xmlSchemaValidateLengthFacet(biType, facet,
15038 value, ctxt->value, &len);
15039 break;
15040 default:
15041 ret = xmlSchemaValidateFacet(biType, facet, value,
15042 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015043 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015044 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015045 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015046 "Internal error: xmlSchemaValidateFacetsInternal, "
15047 "validating facet of type '%s'.\n",
15048 type->name, NULL);
15049 break;
15050 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015051 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015052 type, facet, NULL, NULL, NULL, NULL);
15053 }
15054
15055 facetLink = facetLink->next;
15056 }
15057 if (ret >= 0) {
15058 /*
15059 * Process enumerations.
15060 */
15061 retFacet = 0;
15062 facetLink = type->facetSet;
15063 while (facetLink != NULL) {
15064 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
15065 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
15066 value, ctxt->value);
15067 if (retFacet <= 0)
15068 break;
15069 }
15070 facetLink = facetLink->next;
15071 }
15072 if (retFacet > 0) {
15073 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
15074 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015075 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015076 value, 0, type, NULL, NULL, NULL, NULL, NULL);
15077 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015078 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015079 "Internal error: xmlSchemaValidateFacetsInternal, "
15080 "validating facet of type '%s'.\n",
15081 BAD_CAST "enumeration", NULL);
15082 ret = -1;
15083 }
15084 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015085 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015086 if (ret >= 0) {
15087 /*
15088 * Process patters. Pattern facets are ORed at type level
15089 * and ANDed if derived. Walk the base type axis.
15090 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015091 tmpType = type;
15092 facet = NULL;
15093 do {
15094 retFacet = 0;
15095 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015096 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015097 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
15098 continue;
15099 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
15100 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015101 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015102 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015103 else if (retFacet < 0) {
15104 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
15105 "Internal error: xmlSchemaValidateFacetsInternal, "
15106 "validating 'pattern' facet '%s' of type '%s'.\n",
15107 facetLink->facet->value, tmpType->name);
15108 ret = -1;
15109 break;
15110 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000015111 /* Save the last non-validating facet. */
15112 facet = facetLink->facet;
15113 }
15114 if (retFacet != 0)
15115 break;
15116 tmpType = tmpType->baseType;
15117 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015118 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015119 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
15120 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015121 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015122 NULL, NULL, NULL, NULL);
15123 }
15124 }
15125 }
15126
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015127 return (ret);
15128}
15129
Daniel Veillard4255d502002-04-16 15:50:10 +000015130/************************************************************************
15131 * *
15132 * Simple type validation *
15133 * *
15134 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000015135
Daniel Veillard4255d502002-04-16 15:50:10 +000015136
15137/************************************************************************
15138 * *
15139 * DOM Validation code *
15140 * *
15141 ************************************************************************/
15142
Daniel Veillard4255d502002-04-16 15:50:10 +000015143static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015144 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000015145 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015146static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015147 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000015148 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015149 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000015150
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015151static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015152static int xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015153
15154#ifdef ELEM_INFO_ENABLED
15155/**
15156 * xmlSchemaGetFreshElemInfo:
15157 * @vctxt: the schema validation context
15158 *
15159 * Creates/reuses and initializes the element info item for
15160 * the currect tree depth.
15161 *
15162 * Returns the element info item or NULL on API or internal errors.
15163 */
15164static xmlSchemaElemInfoPtr
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015165xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt,
15166 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015167{
15168 xmlSchemaElemInfoPtr info = NULL;
15169
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015170 if (depth > vctxt->sizeElemInfos) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015171 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015172 "Internal error: xmlSchemaGetFreshElemInfo, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015173 "an inconsistent depth encountered.\n",
15174 NULL, NULL);
15175 return (NULL);
15176 }
15177 if (vctxt->elemInfos == NULL) {
15178 vctxt->elemInfos = (xmlSchemaElemInfoPtr *)
15179 xmlMalloc(10 * sizeof(xmlSchemaElemInfoPtr));
15180 if (vctxt->elemInfos == NULL) {
15181 xmlSchemaVErrMemory(vctxt,
15182 "allocating the element info array", NULL);
15183 return (NULL);
15184 }
15185 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaElemInfoPtr));
15186 vctxt->sizeElemInfos = 10;
15187 } else if (vctxt->sizeElemInfos == vctxt->depth) {
15188 int i = vctxt->sizeElemInfos;
15189
15190 vctxt->sizeElemInfos *= 2;
15191 vctxt->elemInfos = (xmlSchemaElemInfoPtr *)
15192 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
15193 sizeof(xmlSchemaElemInfoPtr));
15194 if (vctxt->elemInfos == NULL) {
15195 xmlSchemaVErrMemory(vctxt,
15196 "re-allocating the element info array", NULL);
15197 return (NULL);
15198 }
15199 /*
15200 * We need the new memory to be NULLed.
15201 * TODO: Use memset instead?
15202 */
15203 for (; i < vctxt->sizeElemInfos; i++)
15204 vctxt->elemInfos[i] = NULL;
15205 } else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015206 info = vctxt->elemInfos[depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015207
15208 if (info == NULL) {
15209 info = (xmlSchemaElemInfoPtr)
15210 xmlMalloc(sizeof(xmlSchemaElemInfo));
15211 if (info == NULL) {
15212 xmlSchemaVErrMemory(vctxt,
15213 "allocating an element info", NULL);
15214 return (NULL);
15215 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015216 vctxt->elemInfos[depth] = info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015217 }
15218 memset(info, 0, sizeof(xmlSchemaElemInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015219 info->depth = depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015220
15221 return (info);
15222}
15223#endif /* ELEM_INFO_ENABLED */
15224
Daniel Veillard3646d642004-06-02 19:19:14 +000015225
15226/**
15227 * xmlSchemaFreeAttrStates:
15228 * @state: a list of attribute states
15229 *
15230 * Free the given list of attribute states
15231 *
15232 */
15233static void
15234xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
15235{
15236 xmlSchemaAttrStatePtr tmp;
15237 while (state != NULL) {
15238 tmp = state;
15239 state = state->next;
15240 xmlFree(tmp);
15241 }
15242}
15243
Daniel Veillard4255d502002-04-16 15:50:10 +000015244/**
15245 * xmlSchemaRegisterAttributes:
15246 * @ctxt: a schema validation context
15247 * @attrs: a list of attributes
15248 *
15249 * Register the list of attributes as the set to be validated on that element
15250 *
15251 * Returns -1 in case of error, 0 otherwise
15252 */
15253static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015254xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
15255{
Daniel Veillard3646d642004-06-02 19:19:14 +000015256 xmlSchemaAttrStatePtr tmp;
15257
15258 ctxt->attr = NULL;
15259 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015260 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015261 if ((attrs->ns != NULL) &&
15262 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
15263 attrs = attrs->next;
15264 continue;
15265 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015266 tmp = (xmlSchemaAttrStatePtr)
15267 xmlMalloc(sizeof(xmlSchemaAttrState));
15268 if (tmp == NULL) {
15269 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
15270 return (-1);
15271 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015272 tmp->attr = attrs;
15273 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
15274 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015275 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015276 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015277 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000015278 else
15279 ctxt->attrTop->next = tmp;
15280 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015281 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015282 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015283 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000015284}
15285
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015286#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000015287/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015288 * xmlSchemaValidateCheckNodeList
15289 * @nodelist: the list of nodes
15290 *
15291 * Check the node list is only made of text nodes and entities pointing
15292 * to text nodes
15293 *
15294 * Returns 1 if true, 0 if false and -1 in case of error
15295 */
15296static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015297xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
15298{
Daniel Veillard4255d502002-04-16 15:50:10 +000015299 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015300 if (nodelist->type == XML_ENTITY_REF_NODE) {
15301 TODO /* implement recursion in the entity content */
15302 }
15303 if ((nodelist->type != XML_TEXT_NODE) &&
15304 (nodelist->type != XML_COMMENT_NODE) &&
15305 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000015306 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015307 return (0);
15308 }
15309 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015310 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015311 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015312}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015313#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015314
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015315static void
15316xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
15317{
15318 int i, nbItems;
15319 xmlSchemaTypePtr item, *items;
15320
15321
15322 /*
15323 * During the Assemble of the schema ctxt->curItems has
15324 * been filled with the relevant new items. Fix those up.
15325 */
15326 nbItems = ctxt->assemble->nbItems;
15327 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
15328
15329 for (i = 0; i < nbItems; i++) {
15330 item = items[i];
15331 switch (item->type) {
15332 case XML_SCHEMA_TYPE_ATTRIBUTE:
15333 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
15334 break;
15335 case XML_SCHEMA_TYPE_ELEMENT:
15336 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
15337 NULL, NULL, NULL);
15338 break;
15339 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15340 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
15341 ctxt, NULL);
15342 break;
15343 case XML_SCHEMA_TYPE_GROUP:
15344 xmlSchemaGroupDefFixup(item, ctxt, NULL);
15345 default:
15346 break;
15347 }
15348 }
15349 /*
15350 * Circularity checks.
15351 */
15352 for (i = 0; i < nbItems; i++) {
15353 item = items[i];
15354 switch (item->type) {
15355 case XML_SCHEMA_TYPE_GROUP:
15356 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
15357 break;
15358 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15359 xmlSchemaCheckAttributeGroupCircular(
15360 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
15361 break;
15362 default:
15363 break;
15364 }
15365 }
15366 /*
15367 * Fixup for all other item.
15368 * TODO: Hmm, not sure if starting from complex/simple types,
15369 * all subsequent items will be reached.
15370 */
15371 for (i = 0; i < nbItems; i++) {
15372 item = items[i];
15373 switch (item->type) {
15374 case XML_SCHEMA_TYPE_SIMPLE:
15375 case XML_SCHEMA_TYPE_COMPLEX:
15376 xmlSchemaTypeFixup(item, ctxt, NULL);
15377 break;
15378 default:
15379 break;
15380 }
15381 }
15382 /*
15383 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015384 * hold by simple type components only (and
15385 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015386 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015387 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015388 for (i = 0; i < nbItems; i++) {
15389 item = items[i];
15390 switch (item->type) {
15391 case XML_SCHEMA_TYPE_SIMPLE:
15392 case XML_SCHEMA_TYPE_COMPLEX:
15393 xmlSchemaCheckDefaults(item, ctxt, NULL);
15394 break;
15395 default:
15396 break;
15397 }
15398 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015399 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015400 /*
15401 * Build the content model for complex types.
15402 */
15403 for (i = 0; i < nbItems; i++) {
15404 item = items[i];
15405 switch (item->type) {
15406 case XML_SCHEMA_TYPE_COMPLEX:
15407 xmlSchemaBuildContentModel(item, ctxt, NULL);
15408 break;
15409 default:
15410 break;
15411 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015412 }
15413 /*
15414 * Validate value contraint values.
15415 */
15416 for (i = 0; i < nbItems; i++) {
15417 item = items[i];
15418 switch (item->type) {
15419 case XML_SCHEMA_TYPE_ATTRIBUTE:
15420 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
15421 break;
15422 case XML_SCHEMA_TYPE_ELEMENT:
15423 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
15424 break;
15425 default:
15426 break;
15427 }
15428 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015429}
15430
15431/**
15432 * xmlSchemaAssembleByLocation:
15433 * @pctxt: a schema parser context
15434 * @vctxt: a schema validation context
15435 * @schema: the existing schema
15436 * @node: the node that fired the assembling
15437 * @nsName: the namespace name of the new schema
15438 * @location: the location of the schema
15439 *
15440 * Expands an existing schema by an additional schema.
15441 *
15442 * Returns 0 if the new schema is correct, a positive error code
15443 * number otherwise and -1 in case of an internal or API error.
15444 */
15445static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015446xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
15447 xmlSchemaPtr schema,
15448 xmlNodePtr node,
15449 const xmlChar *nsName,
15450 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015451{
15452 const xmlChar *targetNs, *oldtns;
15453 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015454 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015455 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015456 xmlSchemaParserCtxtPtr pctxt;
15457
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015458 /*
15459 * This should be used:
15460 * 1. on <import>(s)
15461 * 2. if requested by the validated instance
15462 * 3. if requested via the API
15463 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015464 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015465 return (-1);
15466 /*
15467 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015468 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015469 if ((vctxt->pctxt == NULL) &&
15470 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
15471 xmlSchemaVErr(vctxt, node,
15472 XML_SCHEMAV_INTERNAL,
15473 "Internal error: xmlSchemaAssembleByLocation, "
15474 "failed to create a temp. parser context.\n",
15475 NULL, NULL);
15476 return (-1);
15477 }
15478 pctxt = vctxt->pctxt;
15479 /*
15480 * Set the counter to produce unique names for anonymous items.
15481 */
15482 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015483 /*
15484 * Acquire the schema document.
15485 */
15486 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
15487 nsName, location, &doc, &targetNs, 0);
15488 if (ret != 0) {
15489 if (doc != NULL)
15490 xmlFreeDoc(doc);
15491 } else if (doc != NULL) {
15492 docElem = xmlDocGetRootElement(doc);
15493 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015494 * Create new assemble info.
15495 */
15496 if (pctxt->assemble == NULL) {
15497 pctxt->assemble = xmlSchemaNewAssemble();
15498 if (pctxt->assemble == NULL) {
15499 xmlSchemaVErrMemory(vctxt,
15500 "Memory error: xmlSchemaAssembleByLocation, "
15501 "allocating assemble info", NULL);
15502 xmlFreeDoc(doc);
15503 return (-1);
15504 }
15505 }
15506 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015507 * Save and reset the context & schema.
15508 */
15509 oldflags = schema->flags;
15510 oldtns = schema->targetNamespace;
15511 olddoc = schema->doc;
15512
15513 xmlSchemaClearSchemaDefaults(schema);
15514 schema->targetNamespace = targetNs;
15515 /* schema->nbCurItems = 0; */
15516 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015517 pctxt->ctxtType = NULL;
15518 pctxt->parentItem = NULL;
15519
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015520 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
15521 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015522 xmlSchemaPostSchemaAssembleFixup(pctxt);
15523 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015524 * Set the counter of items.
15525 */
15526 schema->counter = pctxt->counter;
15527 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015528 * Free the list of assembled components.
15529 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015530 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015531 /*
15532 * Restore the context & schema.
15533 */
15534 schema->flags = oldflags;
15535 schema->targetNamespace = oldtns;
15536 schema->doc = olddoc;
15537 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015538 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015539 return (ret);
15540}
15541
15542/**
15543 * xmlSchemaAssembleByXSIAttr:
15544 * @vctxt: a schema validation context
15545 * @xsiAttr: an xsi attribute
15546 * @noNamespace: whether a schema with no target namespace is exptected
15547 *
15548 * Expands an existing schema by an additional schema using
15549 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
15550 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
15551 * must be set to 1.
15552 *
15553 * Returns 0 if the new schema is correct, a positive error code
15554 * number otherwise and -1 in case of an internal or API error.
15555 */
15556static int
15557xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
15558 xmlAttrPtr xsiAttr,
15559 int noNamespace)
15560{
15561 xmlChar *value;
15562 const xmlChar *cur, *end;
15563 const xmlChar *nsname = NULL, *location;
15564 int count = 0;
15565 int ret = 0;
15566
15567 if (xsiAttr == NULL) {
15568 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
15569 NULL, NULL,
15570 "Internal error: xmlSchemaAssembleByXSIAttr, "
15571 "bad arguments", NULL);
15572 return (-1);
15573 }
15574 /*
15575 * Parse the value; we will assume an even number of values
15576 * to be given (this is how Xerces and XSV work).
15577 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015578 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015579 cur = value;
15580 do {
15581 if (noNamespace != 1) {
15582 /*
15583 * Get the namespace name.
15584 */
15585 while (IS_BLANK_CH(*cur))
15586 cur++;
15587 end = cur;
15588 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15589 end++;
15590 if (end == cur)
15591 break;
15592 count++;
15593 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
15594 cur = end;
15595 }
15596 /*
15597 * Get the URI.
15598 */
15599 while (IS_BLANK_CH(*cur))
15600 cur++;
15601 end = cur;
15602 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15603 end++;
15604 if (end == cur)
15605 break;
15606 count++;
15607 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015608 cur = end;
15609 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015610 xsiAttr->parent, nsname, location);
15611 if (ret == -1) {
15612 xmlSchemaVCustomErr(vctxt,
15613 XML_SCHEMAV_INTERNAL,
15614 (xmlNodePtr) xsiAttr, NULL,
15615 "Internal error: xmlSchemaAssembleByXSIAttr, "
15616 "assembling schemata", NULL);
15617 if (value != NULL)
15618 xmlFree(value);
15619 return (-1);
15620 }
15621 } while (*cur != 0);
15622 if (value != NULL)
15623 xmlFree(value);
15624 return (ret);
15625}
15626
15627/**
15628 * xmlSchemaAssembleByXSIElem:
15629 * @vctxt: a schema validation context
15630 * @elem: an element node possibly holding xsi attributes
15631 * @noNamespace: whether a schema with no target namespace is exptected
15632 *
15633 * Assembles an existing schema by an additional schema using
15634 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
15635 * of the given @elem.
15636 *
15637 * Returns 0 if the new schema is correct, a positive error code
15638 * number otherwise and -1 in case of an internal or API error.
15639 */
15640static int
15641xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
15642 xmlNodePtr elem)
15643{
15644 int ret = 0, retNs = 0;
15645 xmlAttrPtr attr;
15646
15647 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
15648 if (attr != NULL) {
15649 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
15650 if (retNs == -1)
15651 return (-1);
15652 }
15653 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
15654 if (attr != NULL) {
15655 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
15656 if (ret == -1)
15657 return (-1);
15658 }
15659 if (retNs != 0)
15660 return (retNs);
15661 else
15662 return (ret);
15663}
15664
Daniel Veillard4255d502002-04-16 15:50:10 +000015665/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015666 * xmlSchemaValidateCallback:
15667 * @ctxt: a schema validation context
15668 * @name: the name of the element detected (might be NULL)
15669 * @type: the type
15670 *
15671 * A transition has been made in the automata associated to an element
15672 * content model
15673 */
15674static void
15675xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015676 const xmlChar * name ATTRIBUTE_UNUSED,
15677 xmlSchemaTypePtr type, xmlNodePtr node)
15678{
Daniel Veillard4255d502002-04-16 15:50:10 +000015679 xmlSchemaTypePtr oldtype = ctxt->type;
15680 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015681
Daniel Veillard4255d502002-04-16 15:50:10 +000015682#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000015683 xmlGenericError(xmlGenericErrorContext,
15684 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015685 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000015686#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015687 /*
15688 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
15689 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015690 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015691 ctxt->node = node;
15692 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015693
15694#ifdef ELEM_INFO_ENABLED
15695 xmlSchemaBeginElement(ctxt);
15696#endif
15697
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015698 /*
15699 * Assemble new schemata using xsi.
15700 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015701 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015702 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015703
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015704 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15705 if (ret == -1) {
15706 xmlSchemaVCustomErr(ctxt,
15707 XML_SCHEMAV_INTERNAL,
15708 ctxt->node, NULL,
15709 "Internal error: xmlSchemaValidateElement, "
15710 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015711 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015712 }
15713 /*
15714 * NOTE: We won't react on schema parser errors here.
15715 * TODO: But a warning would be nice.
15716 */
15717 }
15718 switch (type->type) {
15719 case XML_SCHEMA_TYPE_ELEMENT: {
15720 /*
15721 * NOTE: The build of the content model
15722 * (xmlSchemaBuildAContentModel) ensures that the element
15723 * declaration (and not a reference to it) will be given.
15724 */
15725 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
15726 /*
15727 * This is paranoid coding ;-)... it should not
15728 * happen here any more.
15729 */
15730 xmlSchemaVCustomErr(ctxt,
15731 XML_SCHEMAV_INTERNAL,
15732 node, NULL,
15733 "Internal error: xmlSchemaValidateCallback, "
15734 "element declaration 'reference' encountered, "
15735 "but an element declaration was expected",
15736 NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015737 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015738 }
15739 xmlSchemaValidateElementByDeclaration(ctxt,
15740 (xmlSchemaElementPtr) type);
15741 break;
15742 }
15743 case XML_SCHEMA_TYPE_ANY:
15744 xmlSchemaValidateElementByWildcard(ctxt, type);
15745 break;
15746 default:
15747 break;
15748 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015749leave:
15750
15751#ifdef ELEM_INFO_ENABLED
15752 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015753#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015754 ctxt->type = oldtype;
15755 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015756}
Daniel Veillard4255d502002-04-16 15:50:10 +000015757
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015758static int
15759xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
15760 const xmlChar *value,
15761 xmlSchemaValPtr *val,
15762 xmlNodePtr node)
15763{
15764 int ret;
15765
15766 ret = xmlValidateQName(value, 1);
15767 if (ret != 0)
15768 return (ret);
15769
15770 {
15771 xmlChar *uri = NULL;
15772 xmlChar *local = NULL;
15773 xmlChar *prefix;
15774
15775 local = xmlSplitQName2(value, &prefix);
15776 if (prefix != NULL) {
15777 xmlNsPtr ns;
15778
15779 /*
15780 * TODO: Make this streamable.
15781 */
15782 if ((node == NULL) || (node->doc == NULL)) {
15783 xmlFree(prefix);
15784 xmlFree(local);
15785 return (3);
15786 }
15787
15788 ns = xmlSearchNs(node->doc, node, prefix);
15789 if (ns == NULL) {
15790 xmlFree(prefix);
15791 xmlFree(local);
15792 return (1);
15793 }
15794 }
15795 if (prefix != NULL) {
15796 if (xmlHashLookup2(vctxt->schema->notaDecl, local, uri) == NULL)
15797 ret = 1;
15798 } else if (xmlHashLookup2(vctxt->schema->notaDecl, value,
15799 NULL) == NULL)
15800 ret = 1;
15801
15802 if ((ret == 0) && (val != NULL)) {
15803 if (prefix != NULL) {
15804 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST local,
15805 BAD_CAST xmlStrdup(uri));
15806 local = NULL;
15807 } else
15808 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST xmlStrdup(value),
15809 NULL);
15810 if (*val == NULL)
15811 ret = -1;
15812 }
15813 if (local != NULL)
15814 xmlFree(local);
15815 }
15816
15817 return (ret);
15818}
15819
Daniel Veillard01fa6152004-06-29 17:04:39 +000015820/**
15821 * xmlSchemaValidateSimpleTypeValue:
15822 * @ctxt: a schema validation context
15823 * @value: the value to be validated
15824 * @fireErrors: shall errors be reported?
15825 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015826 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015827 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000015828 *
15829 * Validates a value by the given type (user derived or built-in).
15830 *
15831 * Returns 0 if the value is valid, a positive error code
15832 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015833 */
15834static int
15835xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015836 xmlSchemaTypePtr type,
15837 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015838 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015839 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015840 int normalize,
15841 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015842{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015843 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015844 int ret = 0;
15845 xmlChar *normValue = NULL;
15846 int wtsp;
15847
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015848 node = ctxt->node;
15849 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015850 wtsp = ctxt->valueWS;
15851 /*
15852 * Normalize the value.
15853 */
15854 if (normalize &&
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015855 (ctxt->valueWS != XML_SCHEMAS_FACET_COLLAPSE)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015856 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
15857
15858 if ((norm != -1) && (norm > ctxt->valueWS)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015859 if (norm == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015860 normValue = xmlSchemaCollapseString(value);
15861 else
15862 normValue = xmlSchemaWhiteSpaceReplace(value);
15863 ctxt->valueWS = norm;
15864 if (normValue != NULL)
15865 value = (const xmlChar *) normValue;
15866 }
15867 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015868 /*
15869 * The nodes of a content must be checked only once,
15870 * this is not working since list types will fire this
15871 * multiple times.
15872 */
15873 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
15874 xmlNodePtr cur = ctxt->cur;
15875
15876 do {
15877 switch (cur->type) {
15878 case XML_TEXT_NODE:
15879 case XML_CDATA_SECTION_NODE:
15880 case XML_PI_NODE:
15881 case XML_COMMENT_NODE:
15882 case XML_XINCLUDE_START:
15883 case XML_XINCLUDE_END:
15884 break;
15885 case XML_ENTITY_REF_NODE:
15886 case XML_ENTITY_NODE:
15887 /* TODO: Scour the entities for illegal nodes. */
15888 TODO break;
15889 case XML_ELEMENT_NODE: {
15890 /* NOTE: Changed to an internal error, since the
15891 * existence of an element node will be already checked in
15892 * xmlSchemaValidateElementBySimpleType and in
15893 * xmlSchemaValidateElementByComplexType.
15894 */
15895 xmlSchemaVCustomErr(ctxt,
15896 XML_SCHEMAV_INTERNAL,
15897 /* XML_SCHEMAS_ERR_INVALIDELEM, */
15898 node, type,
15899 "Element '%s' found in simple type content",
15900 cur->name);
15901 return (XML_SCHEMAV_INTERNAL);
15902 }
15903 case XML_ATTRIBUTE_NODE:
15904 case XML_DOCUMENT_NODE:
15905 case XML_DOCUMENT_TYPE_NODE:
15906 case XML_DOCUMENT_FRAG_NODE:
15907 case XML_NOTATION_NODE:
15908 case XML_HTML_DOCUMENT_NODE:
15909 case XML_DTD_NODE:
15910 case XML_ELEMENT_DECL:
15911 case XML_ATTRIBUTE_DECL:
15912 case XML_ENTITY_DECL:
15913 case XML_NAMESPACE_DECL:
15914#ifdef LIBXML_DOCB_ENABLED
15915 case XML_DOCB_DOCUMENT_NODE:
15916#endif
15917 xmlSchemaVCustomErr(ctxt,
15918 XML_SCHEMAV_INTERNAL,
15919 /* XML_SCHEMAS_ERR_INVALIDELEM, */
15920 node, NULL,
15921 "Node of unexpected type found in simple type content",
15922 NULL);
15923 return (XML_SCHEMAV_INTERNAL);
15924 }
15925 cur = cur->next;
15926 } while (cur != NULL);
15927 }
15928
William M. Brack2f2a6632004-08-20 23:09:47 +000015929 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
15930 xmlSchemaTypePtr base, anyType;
15931
15932 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
15933
15934 base = type->baseType;
15935 while ((base != NULL) &&
15936 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
15937 (base->type != XML_SCHEMA_TYPE_BASIC) &&
15938 (base != anyType)) {
15939 base = base->baseType;
15940 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015941 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015942 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015943 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015944 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15945 "validating complex type '%s'\n",
15946 type->name, NULL);
15947 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
15948 /*
15949 * Check facets.
15950 */
15951 /*
15952 * This is somehow not nice, since if an error occurs
15953 * the reported type will be the complex type; the spec
15954 * wants a simple type to be created on the complex type
15955 * if it has a simple content. For now we have to live with
15956 * it.
15957 */
15958 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15959 value, 0, fireErrors);
15960 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015961 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015962 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15963 "validating facets of complex type '%s'\n",
15964 type->name, NULL);
15965 } else if (ret > 0) {
15966 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000015967 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015968 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000015969 }
15970 }
15971 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015972
15973 if (ctxt->value != NULL) {
15974 xmlSchemaFreeValue(ctxt->value);
15975 ctxt->value = NULL;
15976 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015977 /*
15978 * STREAM-READ-CHILDREN.
15979 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015980 if ((type->builtInType == XML_SCHEMAS_NOTATION) &&
15981 (ctxt->schema != NULL)) {
15982 /*
15983 * NOTATIONs need to be processed here, since they need
15984 * to lookup in the hashtable of NOTATION declarations.
15985 */
15986 ret = xmlSchemaValidateNotation(ctxt, value, &(ctxt->value), node);
15987 } else
15988 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015989 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015990 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
15991 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
15992 else
15993 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015994 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015995 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015996 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015997 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015998 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015999 "validating built-in type '%s'\n", type->name, NULL);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016000 } else if ((ctxt->value == NULL) &&
16001 (type->builtInType == XML_SCHEMAS_STRING) &&
16002 (ctxt->nodeInfo != NULL) &&
16003 (ctxt->nodeInfo->flags & XML_SCHEMA_ELEM_INFO_VALUE_NEEDED)) {
16004#ifdef IDC_VALUE_SUPPORT
16005 xmlChar *valdup;
16006 /*
16007 * Create a precomputed string value for "string" as well if
16008 * requested.
16009 */
16010 valdup = xmlStrdup(value);
16011 ctxt->value = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
16012 BAD_CAST valdup);
16013 if ((valdup != NULL) && (ctxt->value == NULL))
16014 xmlFree(valdup);
16015#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000016016 }
16017 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
16018 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
16019 * a literal in the ·lexical space· of {base type definition}
16020 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016021 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016022 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016023 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016024 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016025 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016026 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016027 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016028 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016029 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016030 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016031 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016032 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016033 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016034 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016035 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16036 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016037 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016038 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016039 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016040 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016041 type->name, NULL);
16042 } else if (ret > 0) {
16043 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016044 /*
16045 Disabled, since the facet validation already reports errors.
16046 if (fireErrors)
16047 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16048 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016049 }
16050 }
16051 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
16052
16053 xmlSchemaTypePtr tmpType;
16054 const xmlChar *cur, *end;
16055 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016056 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016057
16058 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
16059 * of white space separated tokens, each of which ·match·es a literal
16060 * in the ·lexical space· of {item type definition}
16061 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000016062
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000016063 if (value == NULL)
16064 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000016065 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016066 cur = value;
16067 do {
16068 while (IS_BLANK_CH(*cur))
16069 cur++;
16070 end = cur;
16071 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
16072 end++;
16073 if (end == cur)
16074 break;
16075 tmp = xmlStrndup(cur, end - cur);
16076 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016077 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016078 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016079 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016080 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016081 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16082 "validating an item of list simple type '%s'\n",
16083 type->name, NULL);
16084 break;
16085 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016086 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016087 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016088 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016089 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016090 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016091 cur = end;
16092 } while (*cur != 0);
16093 /*
16094 * Check facets.
16095 */
16096 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016097 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016098 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016099 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016100 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016101 } else if ((ret == 0) && (applyFacets)) {
16102 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16103 value, len, fireErrors);
16104 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016105 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016106 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16107 "validating facets of list simple type '%s'\n",
16108 type->name, NULL);
16109 } else if (ret > 0) {
16110 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016111 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016112 Disabled, since the facet validation already reports errors.
16113 if (fireErrors)
16114 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016115 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016116 }
16117
Daniel Veillard01fa6152004-06-29 17:04:39 +000016118 }
16119 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
16120 xmlSchemaTypeLinkPtr memberLink;
16121
16122 /*
16123 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
16124 * not apply directly; however, the normalization behavior of ·union·
16125 * types is controlled by the value of whiteSpace on that one of the
16126 * ·memberTypes· against which the ·union· is successfully validated.
16127 *
16128 * This means that the value is normalized by the first validating
16129 * member type, then the facets of the union type are applied. This
16130 * needs changing of the value!
16131 */
16132
16133 /*
16134 * 1.2.3 if {variety} is ·union· then the string must ·match· a
16135 * literal in the ·lexical space· of at least one member of
16136 * {member type definitions}
16137 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016138#ifdef DEBUG_UNION_VALIDATION
16139 printf("Union ST : '%s'\n", (const char *) type->name);
16140 printf(" fireErrors : %d\n", fireErrors);
16141 printf(" applyFacets: %d\n", applyFacets);
16142#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000016143 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
16144 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016145 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016146 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016147 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016148 type->name, NULL);
16149 ret = -1;
16150 }
16151 if (ret == 0) {
16152 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016153 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
16154 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016155 if ((ret <= 0) || (ret == 0))
16156 break;
16157 memberLink = memberLink->next;
16158 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016159 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016160 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016161 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016162 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016163 type->name, NULL);
16164 } else if (ret > 0) {
16165 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016166 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016167 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016168 }
16169 }
16170 /*
16171 * Apply facets (pattern, enumeration).
16172 */
16173 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
16174 int mws;
16175 /*
16176 * The normalization behavior of ·union· types is controlled by
16177 * the value of whiteSpace on that one of the ·memberTypes·
16178 * against which the ·union· is successfully validated.
16179 */
16180 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016181 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016182 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16183 "the value was already normalized for the union simple "
16184 "type '%s'.\n", type->name, NULL);
16185 }
16186 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
16187 if (mws > ctxt->valueWS) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016188 if (mws == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000016189 normValue = xmlSchemaCollapseString(value);
16190 else
16191 normValue = xmlSchemaWhiteSpaceReplace(value);
16192 if (normValue != NULL)
16193 value = (const xmlChar *) normValue;
16194 }
16195
16196 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16197 value, 0, fireErrors);
16198 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016199 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016200 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16201 "validating facets of union simple type '%s'\n",
16202 type->name, NULL);
16203 } else if (ret > 0) {
16204 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
16205 /*
16206 if (fireErrors)
16207 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16208 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016209 }
16210 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016211 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016212 ctxt->valueWS = wtsp;
16213 if (normValue != NULL)
16214 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016215 return (ret);
16216}
16217
16218/**
16219 * xmlSchemaValidateSimpleTypeElement:
16220 * @ctxt: a schema validation context
16221 * @node: the element node to be validated.
16222 *
16223 * Validate the element against a simple type.
16224 *
16225 * Returns 0 if the element is valid, a positive error code
16226 * number otherwise and -1 in case of an internal or API error.
16227 */
16228static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016229xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016230 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016231 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016232 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016233{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016234 xmlSchemaTypePtr oldtype;
16235 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016236 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016237 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016238 int ret = 0, retval = 0;
16239
Daniel Veillard01fa6152004-06-29 17:04:39 +000016240 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016241 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16242 "Internal error: xmlSchemaValidateElementBySimpleType, "
16243 "bad arguments", NULL);
16244 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016245 }
16246
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016247 oldtype = ctxt->type;
16248 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016249 /*
16250 * cvc-type: 3.1.2 The element information item must have no element
16251 * information item [children].
16252 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016253 /*
16254 * STREAM: Child nodes are processed.
16255 */
16256 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016257 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016258 /*
16259 * TODO: Entities, will they produce elements as well?
16260 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016261 if (cur->type == XML_ELEMENT_NODE) {
16262 xmlSchemaVCustomErr(ctxt,
16263 XML_SCHEMAV_CVC_TYPE_3_1_2,
16264 node, type,
16265 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016266 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016267 }
16268 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016269 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016270
Daniel Veillard01fa6152004-06-29 17:04:39 +000016271 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016272 * cvc-type 3.1.1:
16273 *
16274 * The attributes of must be empty, excepting those whose namespace name
16275 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
16276 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016277 */
16278 /*
16279 * STREAM: Attribute nodes are processed.
16280 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016281 attr = node->properties;
16282 while (attr != NULL) {
16283 if ((attr->ns == NULL) ||
16284 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
16285 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
16286 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
16287 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
16288 (!xmlStrEqual
16289 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016290 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016291 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
16292 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016293 }
16294 attr = attr->next;
16295 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016296 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016297 * This will skip validation if the type is 'anySimpleType' and
16298 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016299 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016300 if ((! isNil) &&
16301 (valSimpleContent == 1) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016302 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
16303 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016304 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016305
16306 value = xmlNodeGetContent(node);
16307 /*
16308 * NOTE: This call will not check the content nodes, since
16309 * this should be checked here already.
16310 */
16311 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
16312 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016313 if (value != NULL)
16314 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016315 if (retval != 0)
16316 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000016317 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016318 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016319 return (ret);
16320}
Daniel Veillard4255d502002-04-16 15:50:10 +000016321
16322/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016323 * xmlSchemaValQNameAcquire:
16324 * @value: the lexical represantation of the QName value
16325 * @node: the node to search for the corresponding namespace declaration
16326 * @nsName: the resulting namespace name if found
16327 *
16328 * Checks that a value conforms to the lexical space of the type QName;
16329 * if valid, the corresponding namespace name is searched and retured
16330 * as a copy in @nsName. The local name is returned in @localName as
16331 * a copy.
16332 *
16333 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
16334 * namespace declaration was found in scope; -1 in case of an internal or
16335 * API error.
16336 */
16337static int
16338xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
16339 xmlChar **nsName, xmlChar **localName)
16340{
16341 int ret;
16342 xmlChar *local = NULL;
16343
16344 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
16345 return (-1);
16346 *nsName = NULL;
16347 *localName = NULL;
16348 ret = xmlValidateQName(value, 1);
16349 if (ret == 0) {
16350 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016351 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016352
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016353 /*
16354 * NOTE: xmlSplitQName2 will return a duplicated
16355 * string.
16356 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016357 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016358 if (local == NULL)
16359 local = xmlStrdup(value);
16360 ns = xmlSearchNs(node->doc, node, prefix);
16361 /*
16362 * A namespace need not to be found if the prefix is NULL.
16363 */
16364 if (ns != NULL) {
16365 /*
16366 * TODO: Is it necessary to duplicate the URI here?
16367 */
16368 *nsName = xmlStrdup(ns->href);
16369 } else if (prefix != NULL) {
16370 xmlFree(prefix);
16371 if (local != NULL)
16372 xmlFree(local);
16373 return (2);
16374 }
16375 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016376 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016377 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016378 } else
16379 return (1);
16380 return (ret);
16381}
16382
16383/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016384 * xmlSchemaHasElemContent:
16385 * @node: the node
16386 *
16387 * Scours the content of the given node for element
16388 * nodes.
16389 *
16390 * Returns 1 if an element node is found,
16391 * 0 otherwise.
16392 */
16393static int
16394xmlSchemaHasElemContent(xmlNodePtr node)
16395{
16396 if (node == NULL)
16397 return (0);
16398 node = node->children;
16399 while (node != NULL) {
16400 if (node->type == XML_ELEMENT_NODE)
16401 return (1);
16402 node = node->next;
16403 }
16404 return (0);
16405}
16406/**
16407 * xmlSchemaHasElemOrCharContent:
16408 * @node: the node
16409 *
16410 * Scours the content of the given node for element
16411 * and character nodes.
16412 *
16413 * Returns 1 if an element or character node is found,
16414 * 0 otherwise.
16415 */
16416static int
16417xmlSchemaHasElemOrCharContent(xmlNodePtr node)
16418{
16419 if (node == NULL)
16420 return (0);
16421 node = node->children;
16422 while (node != NULL) {
16423 switch (node->type) {
16424 case XML_ELEMENT_NODE:
16425 /*
16426 * TODO: Ask Daniel if these are all character nodes.
16427 */
16428 case XML_TEXT_NODE:
16429 case XML_CDATA_SECTION_NODE:
16430 /*
16431 * TODO: How XML_ENTITY_NODEs evaluated?
16432 */
16433 case XML_ENTITY_REF_NODE:
16434 case XML_ENTITY_NODE:
16435 return (1);
16436 break;
16437 default:
16438 break;
16439 }
16440 node = node->next;
16441 }
16442 return (0);
16443}
16444
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016445/************************************************************************
16446 * *
16447 * Identity-constraints (IDC) *
16448 * *
16449 ************************************************************************/
16450
16451#ifdef IDC_ENABLED
16452
16453/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016454 * xmlSchemaAugmentIDC:
16455 * @idcDef: the IDC definition
16456 *
16457 * Creates an augmented IDC definition item.
16458 *
16459 * Returns the item, or NULL on internal errors.
16460 */
16461static void
16462xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
16463 xmlSchemaValidCtxtPtr vctxt)
16464{
16465 xmlSchemaIDCAugPtr aidc;
16466
16467 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
16468 if (aidc == NULL) {
16469 xmlSchemaVErrMemory(vctxt,
16470 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
16471 NULL);
16472 return;
16473 }
16474 aidc->bubbleDepth = -1;
16475 aidc->def = idcDef;
16476 aidc->next = NULL;
16477 if (vctxt->aidcs == NULL)
16478 vctxt->aidcs = aidc;
16479 else {
16480 aidc->next = vctxt->aidcs;
16481 vctxt->aidcs = aidc;
16482 }
16483}
16484
16485/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016486 * xmlSchemaIDCNewBinding:
16487 * @idcDef: the IDC definition of this binding
16488 *
16489 * Creates a new IDC binding.
16490 *
16491 * Returns the new binding in case of succeeded, NULL on internal errors.
16492 */
16493static xmlSchemaPSVIIDCBindingPtr
16494xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
16495{
16496 xmlSchemaPSVIIDCBindingPtr ret;
16497
16498 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
16499 sizeof(xmlSchemaPSVIIDCBinding));
16500 if (ret == NULL) {
16501 xmlSchemaVErrMemory(NULL,
16502 "allocating a PSVI IDC binding item", NULL);
16503 return (NULL);
16504 }
16505 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
16506 ret->definition = idcDef;
16507 return (ret);
16508}
16509
16510/**
16511 * xmlSchemaIDCStoreNodeTableItem:
16512 * @vctxt: the WXS validation context
16513 * @item: the IDC node table item
16514 *
16515 * The validation context is used to store an IDC node table items.
16516 * They are stored to avoid copying them if IDC node-tables are merged
16517 * with corresponding parent IDC node-tables (bubbling).
16518 *
16519 * Returns 0 if succeeded, -1 on internal errors.
16520 */
16521static int
16522xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
16523 xmlSchemaPSVIIDCNodePtr item)
16524{
16525 /*
16526 * Add to gobal list.
16527 */
16528 if (vctxt->idcNodes == NULL) {
16529 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16530 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
16531 if (vctxt->idcNodes == NULL) {
16532 xmlSchemaVErrMemory(vctxt,
16533 "allocating the IDC node table item list", NULL);
16534 return (-1);
16535 }
16536 vctxt->sizeIdcNodes = 20;
16537 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
16538 vctxt->sizeIdcNodes *= 2;
16539 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16540 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
16541 sizeof(xmlSchemaPSVIIDCNodePtr));
16542 if (vctxt->idcNodes == NULL) {
16543 xmlSchemaVErrMemory(vctxt,
16544 "re-allocating the IDC node table item list", NULL);
16545 return (-1);
16546 }
16547 }
16548 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
16549
16550 return (0);
16551}
16552
16553/**
16554 * xmlSchemaIDCStoreKey:
16555 * @vctxt: the WXS validation context
16556 * @item: the IDC key
16557 *
16558 * The validation context is used to store an IDC key.
16559 *
16560 * Returns 0 if succeeded, -1 on internal errors.
16561 */
16562static int
16563xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
16564 xmlSchemaPSVIIDCKeyPtr key)
16565{
16566 /*
16567 * Add to gobal list.
16568 */
16569 if (vctxt->idcKeys == NULL) {
16570 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16571 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
16572 if (vctxt->idcKeys == NULL) {
16573 xmlSchemaVErrMemory(vctxt,
16574 "allocating the IDC key storage list", NULL);
16575 return (-1);
16576 }
16577 vctxt->sizeIdcKeys = 40;
16578 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
16579 vctxt->sizeIdcKeys *= 2;
16580 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16581 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
16582 sizeof(xmlSchemaPSVIIDCKeyPtr));
16583 if (vctxt->idcKeys == NULL) {
16584 xmlSchemaVErrMemory(vctxt,
16585 "re-allocating the IDC key storage list", NULL);
16586 return (-1);
16587 }
16588 }
16589 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
16590
16591 return (0);
16592}
16593
16594/**
16595 * xmlSchemaIDCAppendNodeTableItem:
16596 * @bind: the IDC binding
16597 * @ntItem: the node-table item
16598 *
16599 * Appends the IDC node-table item to the binding.
16600 *
16601 * Returns 0 on success and -1 on internal errors.
16602 */
16603static int
16604xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
16605 xmlSchemaPSVIIDCNodePtr ntItem)
16606{
16607 if (bind->nodeTable == NULL) {
16608 bind->sizeNodes = 10;
16609 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16610 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
16611 if (bind->nodeTable == NULL) {
16612 xmlSchemaVErrMemory(NULL,
16613 "allocating an array of IDC node-table items", NULL);
16614 return(-1);
16615 }
16616 } else if (bind->sizeNodes <= bind->nbNodes) {
16617 bind->sizeNodes *= 2;
16618 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16619 xmlRealloc(bind->nodeTable, bind->sizeNodes *
16620 sizeof(xmlSchemaPSVIIDCNodePtr));
16621 if (bind->nodeTable == NULL) {
16622 xmlSchemaVErrMemory(NULL,
16623 "re-allocating an array of IDC node-table items", NULL);
16624 return(-1);
16625 }
16626 }
16627 bind->nodeTable[bind->nbNodes++] = ntItem;
16628 return(0);
16629}
16630
16631/**
16632 * xmlSchemaIDCAquireBinding:
16633 * @vctxt: the WXS validation context
16634 * @matcher: the IDC matcher
16635 *
16636 * Looks up an PSVI IDC binding, for the IDC definition and
16637 * of the given matcher. If none found, a new one is created
16638 * and added to the IDC table.
16639 *
16640 * Returns an IDC binding or NULL on internal errors.
16641 */
16642static xmlSchemaPSVIIDCBindingPtr
16643xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
16644 xmlSchemaIDCMatcherPtr matcher)
16645{
16646 xmlSchemaElemInfoPtr info;
16647
16648 info = vctxt->elemInfos[matcher->depth];
16649
16650 if (info->idcTable == NULL) {
16651 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
16652 if (info->idcTable == NULL)
16653 return (NULL);
16654 return(info->idcTable);
16655 } else {
16656 xmlSchemaPSVIIDCBindingPtr bind = NULL;
16657
16658 bind = info->idcTable;
16659 do {
16660 if (bind->definition == matcher->aidc->def)
16661 return(bind);
16662 if (bind->next == NULL) {
16663 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
16664 if (bind->next == NULL)
16665 return (NULL);
16666 return(bind->next);
16667 }
16668 bind = bind->next;
16669 } while (bind != NULL);
16670 }
16671 return (NULL);
16672}
16673
16674/**
16675 * xmlSchemaIDCFreeKey:
16676 * @key: the IDC key
16677 *
16678 * Frees an IDC key together with its compiled value.
16679 */
16680static void
16681xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
16682{
16683 if (key->compValue != NULL)
16684 xmlSchemaFreeValue(key->compValue);
16685 xmlFree(key);
16686}
16687
16688/**
16689 * xmlSchemaIDCFreeBinding:
16690 *
16691 * Frees an IDC binding. Note that the node table-items
16692 * are not freed.
16693 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016694static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016695xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
16696{
16697 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016698 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
16699 int i;
16700 /*
16701 * Node-table items for keyrefs are not stored globally
16702 * to the validation context, since they are not bubbled.
16703 * We need to free them here.
16704 */
16705 for (i = 0; i < bind->nbNodes; i++) {
16706 xmlFree(bind->nodeTable[i]->keys);
16707 xmlFree(bind->nodeTable[i]);
16708 }
16709 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016710 xmlFree(bind->nodeTable);
16711 }
16712 xmlFree(bind);
16713}
16714
16715/**
16716 * xmlSchemaIDCFreeIDCTable:
16717 * @bind: the first IDC binding in the list
16718 *
16719 * Frees an IDC table, i.e. all the IDC bindings in the list.
16720 */
16721static void
16722xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
16723{
16724 xmlSchemaPSVIIDCBindingPtr prev;
16725
16726 while (bind != NULL) {
16727 prev = bind;
16728 bind = bind->next;
16729 xmlSchemaIDCFreeBinding(prev);
16730 }
16731}
16732
16733/**
16734 * xmlSchemaIDCFreeMatcherList:
16735 * @matcher: the first IDC matcher in the list
16736 *
16737 * Frees a list of IDC matchers.
16738 */
16739static void
16740xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
16741{
16742 xmlSchemaIDCMatcherPtr next;
16743
16744 while (matcher != NULL) {
16745 next = matcher->next;
16746 if (matcher->keySeqs != NULL) {
16747 int i;
16748 for (i = 0; i < matcher->sizeKeySeqs; i++)
16749 if (matcher->keySeqs[i] != NULL)
16750 xmlFree(matcher->keySeqs[i]);
16751 xmlFree(matcher->keySeqs);
16752 }
16753 xmlFree(matcher);
16754 matcher = next;
16755 }
16756}
16757
16758/**
16759 * xmlSchemaAreValuesEqual:
16760 * @ta: the first type
16761 * @a: the first value
16762 * @tb: the second type
16763 * @b: the second value
16764 *
16765 * Compares two values.
16766 *
16767 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
16768 */
16769static int
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016770xmlSchemaAreValuesEqual(xmlSchemaValidCtxtPtr vctxt,
16771 xmlSchemaTypePtr ta,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016772 xmlSchemaValPtr a,
16773 xmlSchemaTypePtr tb,
16774 xmlSchemaValPtr b)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016775{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016776 /* Same user derived/built-in derived/built-in primitive types. */
16777 if (ta == tb)
16778 goto compareValue;
16779
16780 /*
16781 * Comparison with anySimpleTypes is not supported by this implemention.
16782 */
16783 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
16784 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
16785 return(0);
16786
16787 /*
16788 * 4.2.1 equal (data-types)
16789 *
16790 * the ·value space·s of all ·primitive· datatypes are disjoint
16791 * (they do not share any values)
16792 */
16793 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
16794 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
16795 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
16796 return(0);
16797
16798 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16799 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
16800 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16801 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
16802 TODO
16803 return(0);
16804 }
16805 /*
16806 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
16807 * T then the ·value space· of T' is a subset of the ·value space· of T.
16808 */
16809 /*
16810 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
16811 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
16812 */
16813
16814 {
16815 xmlSchemaTypePtr pta = ta, ptb = tb;
16816
16817 /* Note that we will compare the primitives here. */
16818 while ((pta->builtInType == 0) ||
16819 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16820 pta = pta->baseType;
16821 while ((ptb->builtInType == 0) ||
16822 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16823 ptb = ptb->baseType;
16824 if (pta == ptb)
16825 goto compareValue;
16826 return(0);
16827 }
16828compareValue:
16829 {
16830#ifdef IDC_VALUE_SUPPORT
16831 int ret;
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016832 int aws, bws;
16833
16834 aws = xmlSchemaGetWhiteSpaceFacetValue(ta);
16835 bws = xmlSchemaGetWhiteSpaceFacetValue(tb);
16836
16837 ret = xmlSchemaCompareValuesWhtsp(
16838 a, (xmlSchemaWhitespaceValueType) aws,
16839 b, (xmlSchemaWhitespaceValueType) bws);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016840 if (ret == 0)
16841 return(1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016842 else if (ret == -2) {
16843 xmlSchemaVErr(vctxt, vctxt->node,
16844 XML_SCHEMAV_INTERNAL,
16845 "Internal error: xmlSchemaAreValuesEqual, "
16846 "failed to compare the values.\n",
16847 NULL, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016848 return(-1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016849 } else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016850 return(0);
16851#else
16852 return (1);
16853#endif
16854 }
16855}
16856
16857/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016858 * xmlSchemaIDCAddStateObject:
16859 * @vctxt: the WXS validation context
16860 * @matcher: the IDC matcher
16861 * @sel: the XPath information
16862 * @parent: the parent "selector" state object if any
16863 * @type: "selector" or "field"
16864 *
16865 * Creates/reuses and activates state objects for the given
16866 * XPath information; if the XPath expression consists of unions,
16867 * multiple state objects are created for every unioned expression.
16868 *
16869 * Returns 0 on success and -1 on internal errors.
16870 */
16871static int
16872xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
16873 xmlSchemaIDCMatcherPtr matcher,
16874 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016875 int type)
16876{
16877 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016878
16879 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016880 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016881 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016882 if (vctxt->xpathStatePool != NULL) {
16883 sto = vctxt->xpathStatePool;
16884 vctxt->xpathStatePool = sto->next;
16885 sto->next = NULL;
16886 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016887 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016888 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016889 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016890 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
16891 if (sto == NULL) {
16892 xmlSchemaVErrMemory(NULL,
16893 "allocating an IDC state object", NULL);
16894 return (-1);
16895 }
16896 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
16897 }
16898 /*
16899 * Add to global list.
16900 */
16901 if (vctxt->xpathStates != NULL)
16902 sto->next = vctxt->xpathStates;
16903 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016904
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016905 /*
16906 * Free the old xpath validation context.
16907 */
16908 if (sto->xpathCtxt != NULL)
16909 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
16910
16911 /*
16912 * Create a new XPath (pattern) validation context.
16913 */
16914 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
16915 (xmlPatternPtr) sel->xpathComp);
16916 if (sto->xpathCtxt == NULL) {
16917 xmlSchemaVErr(vctxt, vctxt->node,
16918 XML_SCHEMAV_INTERNAL,
16919 "Internal error: xmlSchemaIDCAddStateObject, "
16920 "failed to create the XPath validation context.\n",
16921 NULL, NULL);
16922 return (-1);
16923 }
16924 sto->type = type;
16925 sto->depth = vctxt->depth;
16926 sto->matcher = matcher;
16927 sto->sel = sel;
16928 sto->nbHistory = 0;
16929
16930#if DEBUG_IDC
16931 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
16932 sto->sel->xpath);
16933#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016934 return (0);
16935}
16936
16937/**
16938 * xmlSchemaXPathEvaluate:
16939 * @vctxt: the WXS validation context
16940 * @nodeType: the nodeType of the current node
16941 *
16942 * Evaluates all active XPath state objects.
16943 *
16944 * Returns the number of IC "field" state objects which resolved to
16945 * this node, 0 if none resolved and -1 on internal errors.
16946 */
16947static int
16948xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016949 xmlElementType nodeType)
16950{
16951 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016952 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016953
16954 if (vctxt->xpathStates == NULL)
16955 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016956
16957 if (nodeType == XML_ATTRIBUTE_NODE)
16958 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016959#if DEBUG_IDC
16960 {
16961 xmlChar *str = NULL;
16962 xmlGenericError(xmlGenericErrorContext,
16963 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016964 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
16965 vctxt->nodeInfo->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016966 FREE_AND_NULL(str)
16967 }
16968#endif
16969 /*
16970 * Process all active XPath state objects.
16971 */
16972 first = vctxt->xpathStates;
16973 sto = first;
16974 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016975#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016976 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016977 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
16978 sto->matcher->aidc->def->name, sto->sel->xpath);
16979 else
16980 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
16981 sto->matcher->aidc->def->name, sto->sel->xpath);
16982#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016983
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016984#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016985 if (nodeType == XML_ELEMENT_NODE)
16986 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
16987 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
16988 else
16989 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
16990 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
16991
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016992#else
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016993 res = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016994#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016995 if (res == -1) {
16996 xmlSchemaVErr(vctxt, vctxt->node,
16997 XML_SCHEMAV_INTERNAL,
16998 "Internal error: xmlSchemaXPathEvaluate, "
16999 "failed to evaluate a node.\n",
17000 NULL, NULL);
17001 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017002 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017003 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017004 goto next_sto;
17005 /*
17006 * Full match.
17007 */
17008#if DEBUG_IDC
17009 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017010 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017011#endif
17012 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017013 * Register a match in the state object history.
17014 */
17015 if (sto->history == NULL) {
17016 sto->history = (int *) xmlMalloc(5 * sizeof(int));
17017 if (sto->history == NULL) {
17018 xmlSchemaVErrMemory(NULL,
17019 "allocating the state object history", NULL);
17020 return(-1);
17021 }
17022 sto->sizeHistory = 10;
17023 } else if (sto->sizeHistory <= sto->nbHistory) {
17024 sto->sizeHistory *= 2;
17025 sto->history = (int *) xmlRealloc(sto->history,
17026 sto->sizeHistory * sizeof(int));
17027 if (sto->history == NULL) {
17028 xmlSchemaVErrMemory(NULL,
17029 "re-allocating the state object history", NULL);
17030 return(-1);
17031 }
17032 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017033 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017034
17035#ifdef DEBUG_IDC
17036 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
17037 vctxt->depth);
17038#endif
17039
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017040 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
17041 xmlSchemaIDCSelectPtr sel;
17042 /*
17043 * Activate state objects for the IDC fields of
17044 * the IDC selector.
17045 */
17046#if DEBUG_IDC
17047 xmlGenericError(xmlGenericErrorContext, "IDC: "
17048 "activating field states\n");
17049#endif
17050 sel = sto->matcher->aidc->def->fields;
17051 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017052 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
17053 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
17054 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017055 sel = sel->next;
17056 }
17057 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
17058 /*
17059 * An IDC key node was found.
17060 */
17061#if DEBUG_IDC
17062 xmlGenericError(xmlGenericErrorContext,
17063 "IDC: key found\n");
17064#endif
17065 /*
17066 * Notify that the character value of this node is
17067 * needed.
17068 */
17069 if (resolved == 0)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017070 vctxt->nodeInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017071 resolved++;
17072 }
17073next_sto:
17074 if (sto->next == NULL) {
17075 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017076 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017077 */
17078 head = first;
17079 sto = vctxt->xpathStates;
17080 } else
17081 sto = sto->next;
17082 }
17083 return (resolved);
17084}
17085
17086/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017087 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017088 * @vctxt: the WXS validation context
17089 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017090 * @compValue: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017091 *
17092 * Processes and pops the history items of the IDC state objects.
17093 * IDC key-sequences are validated/created on IDC bindings.
17094 *
17095 * Returns 0 on success and -1 on internal errors.
17096 */
17097static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017098xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017099 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017100{
17101 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017102 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017103 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017104 xmlSchemaTypePtr type = vctxt->nodeInfo->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017105
17106 if (vctxt->xpathStates == NULL)
17107 return (0);
17108 sto = vctxt->xpathStates;
17109
17110#if DEBUG_IDC
17111 {
17112 xmlChar *str = NULL;
17113 xmlGenericError(xmlGenericErrorContext,
17114 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017115 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17116 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017117 FREE_AND_NULL(str)
17118 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017119#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017120 /*
17121 * Evaluate the state objects.
17122 */
17123 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017124#ifdef IDC_XPATH_SUPPORT
17125 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
17126 #if DEBUG_IDC
17127 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
17128 sto->sel->xpath);
17129 #endif
17130#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017131 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017132 goto deregister_check;
17133
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017134 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017135
17136 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017137 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017138 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017139 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017140 sto = sto->next;
17141 continue;
17142 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017143
17144 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
17145 if (! IS_SIMPLE_TYPE(type)) {
17146 /*
17147 * Not qualified if the field resolves to a node of non
17148 * simple type.
17149 */
17150 xmlSchemaVCustomErr(vctxt,
17151 XML_SCHEMAV_CVC_IDC,
17152 vctxt->node,
17153 (xmlSchemaTypePtr) sto->matcher->aidc->def,
17154 "The field '%s' does evaluate to a node of "
17155 "non-simple type", sto->sel->xpath);
17156
17157 sto->nbHistory--;
17158 goto deregister_check;
17159 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017160 if ((key == NULL) && (vctxt->nodeInfo->value == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017161 /*
17162 * Failed to provide the normalized value; maby
17163 * the value was invalid.
17164 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017165 xmlSchemaVCustomErr(vctxt,
17166 XML_SCHEMAV_CVC_IDC,
17167 vctxt->nodeInfo->node,
17168 (xmlSchemaTypePtr) sto->matcher->aidc->def,
17169 "Warning: No precomputed value available, the value "
17170 "was either invalid or something strange happend", NULL);
17171 /*
17172 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017173 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017174 "Internal error: xmlSchemaXPathProcessHistory, "
17175 "computed value not available.\n",
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017176 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017177 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017178 sto->nbHistory--;
17179 goto deregister_check;
17180 } else {
17181 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
17182 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017183 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017184
17185 /*
17186 * The key will be anchored on the matcher's list of
17187 * key-sequences. The position in this list is determined
17188 * by the target node's depth relative to the matcher's
17189 * depth of creation (i.e. the depth of the scope element).
17190 */
17191 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017192 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017193
17194 /*
17195 * Create/grow the array of key-sequences.
17196 */
17197 if (matcher->keySeqs == NULL) {
17198 if (pos > 9)
17199 matcher->sizeKeySeqs = pos * 2;
17200 else
17201 matcher->sizeKeySeqs = 10;
17202 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17203 xmlMalloc(matcher->sizeKeySeqs *
17204 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17205 if (matcher->keySeqs == NULL) {
17206 xmlSchemaVErrMemory(NULL,
17207 "allocating an array of key-sequences",
17208 NULL);
17209 return(-1);
17210 }
17211 memset(matcher->keySeqs, 0,
17212 matcher->sizeKeySeqs *
17213 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17214 } else if (pos >= matcher->sizeKeySeqs) {
17215 int i = matcher->sizeKeySeqs;
17216
17217 matcher->sizeKeySeqs *= 2;
17218 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17219 xmlRealloc(matcher->keySeqs,
17220 matcher->sizeKeySeqs *
17221 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017222 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017223 xmlSchemaVErrMemory(NULL,
17224 "reallocating an array of key-sequences",
17225 NULL);
17226 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017227 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017228 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017229 * The array needs to be NULLed.
17230 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017231 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017232 for (; i < matcher->sizeKeySeqs; i++)
17233 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017234 }
17235
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017236 /*
17237 * Get/create the key-sequence.
17238 */
17239 keySeq = matcher->keySeqs[pos];
17240 if (keySeq == NULL) {
17241 goto create_sequence;
17242 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017243 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017244 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017245 * cvc-identity-constraint:
17246 * 3 For each node in the ·target node set· all
17247 * of the {fields}, with that node as the context
17248 * node, evaluate to either an empty node-set or
17249 * a node-set with exactly one member, which must
17250 * have a simple type.
17251 *
17252 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017253 */
17254 xmlSchemaVCustomErr(vctxt,
17255 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017256 vctxt->node, (xmlSchemaTypePtr) matcher->aidc->def,
17257 "The field '%s' evaluates to a node-set "
17258 "with more than one member", sto->sel->xpath);
17259 sto->nbHistory--;
17260 goto deregister_check;
17261 } else {
17262 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017263 }
17264 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017265
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017266create_sequence:
17267 /*
17268 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017269 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017270 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
17271 matcher->aidc->def->nbFields *
17272 sizeof(xmlSchemaPSVIIDCKeyPtr));
17273 if (keySeq == NULL) {
17274 xmlSchemaVErrMemory(NULL,
17275 "allocating an IDC key-sequence", NULL);
17276 return(-1);
17277 }
17278 memset(keySeq, 0, matcher->aidc->def->nbFields *
17279 sizeof(xmlSchemaPSVIIDCKeyPtr));
17280 matcher->keySeqs[pos] = keySeq;
17281create_key:
17282 /*
17283 * Created a key once per node only.
17284 */
17285 if (key == NULL) {
17286 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
17287 sizeof(xmlSchemaPSVIIDCKey));
17288 if (key == NULL) {
17289 xmlSchemaVErrMemory(NULL,
17290 "allocating a IDC key", NULL);
17291 xmlFree(keySeq);
17292 matcher->keySeqs[pos] = NULL;
17293 return(-1);
17294 }
17295 /*
17296 * Consume the compiled value.
17297 */
17298 key->type = type;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017299 key->compValue = vctxt->nodeInfo->value;
17300 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017301 /*
17302 * Store the key in a global list.
17303 */
17304 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
17305 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017306 return (-1);
17307 }
17308 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017309 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017310 }
17311 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017312
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017313 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
17314 xmlSchemaPSVIIDCBindingPtr bind;
17315 xmlSchemaPSVIIDCNodePtr ntItem;
17316 xmlSchemaIDCMatcherPtr matcher;
17317 xmlSchemaIDCPtr idc;
17318 int pos, i, j, nbKeys;
17319 /*
17320 * Here we have the following scenario:
17321 * An IDC 'selector' state object resolved to a target node,
17322 * during the time this target node was in the
17323 * ancestor-or-self axis, the 'field' state object(s) looked
17324 * out for matching nodes to create a key-sequence for this
17325 * target node. Now we are back to this target node and need
17326 * to put the key-sequence, together with the target node
17327 * itself, into the node-table of the corresponding IDC
17328 * binding.
17329 */
17330 matcher = sto->matcher;
17331 idc = matcher->aidc->def;
17332 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017333 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017334 /*
17335 * Check if the matcher has any key-sequences at all, plus
17336 * if it has a key-sequence for the current target node.
17337 */
17338 if ((matcher->keySeqs == NULL) ||
17339 (matcher->sizeKeySeqs <= pos)) {
17340 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17341 goto selector_key_error;
17342 else
17343 goto selector_leave;
17344 }
17345
17346 keySeq = &(matcher->keySeqs[pos]);
17347 if (*keySeq == NULL) {
17348 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17349 goto selector_key_error;
17350 else
17351 goto selector_leave;
17352 }
17353
17354 for (i = 0; i < nbKeys; i++) {
17355 if ((*keySeq)[i] == NULL) {
17356 /*
17357 * Not qualified, if not all fields did resolve.
17358 */
17359 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
17360 /*
17361 * All fields of a "key" IDC must resolve.
17362 */
17363 goto selector_key_error;
17364 }
17365 goto selector_leave;
17366 }
17367 }
17368 /*
17369 * All fields did resolve.
17370 */
17371
17372 /*
17373 * 4.1 If the {identity-constraint category} is unique(/key),
17374 * then no two members of the ·qualified node set· have
17375 * ·key-sequences· whose members are pairwise equal, as
17376 * defined by Equal in [XML Schemas: Datatypes].
17377 *
17378 * Get the IDC binding from the matcher and check for
17379 * duplicate key-sequences.
17380 */
17381 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
17382 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
17383 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017384 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017385
17386 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017387 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017388 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017389 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017390 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017391 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017392 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017393 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017394 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017395 bkey = bkeySeq[j];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017396 res = xmlSchemaAreValuesEqual(vctxt, ckey->type,
17397 ckey->compValue, bkey->type, bkey->compValue);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017398 if (res == -1) {
17399 return (-1);
17400 } else if (res == 0)
17401 break;
17402 }
17403 if (res == 1) {
17404 /*
17405 * Duplicate found.
17406 */
17407 break;
17408 }
17409 i++;
17410 } while (i < bind->nbNodes);
17411 if (i != bind->nbNodes) {
17412 /*
17413 * TODO: Try to report the key-sequence.
17414 */
17415 xmlSchemaVCustomErr(vctxt,
17416 XML_SCHEMAV_CVC_IDC,
17417 vctxt->node,
17418 (xmlSchemaTypePtr) idc,
17419 "Duplicate key-sequence found", NULL);
17420
17421 goto selector_leave;
17422 }
17423 }
17424 /*
17425 * Add a node-table item to the IDC binding.
17426 */
17427 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
17428 sizeof(xmlSchemaPSVIIDCNode));
17429 if (ntItem == NULL) {
17430 xmlSchemaVErrMemory(NULL,
17431 "allocating an IDC node-table item", NULL);
17432 xmlFree(*keySeq);
17433 *keySeq = NULL;
17434 return(-1);
17435 }
17436 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
17437
17438 /*
17439 * Store the node-table item on global list.
17440 */
17441 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
17442 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
17443 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017444 xmlFree(*keySeq);
17445 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017446 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017447 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017448 }
17449 /*
17450 * Init the node-table item. Consume the key-sequence.
17451 */
17452 ntItem->node = vctxt->node;
17453 ntItem->keys = *keySeq;
17454 *keySeq = NULL;
17455 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
17456 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17457 /*
17458 * Free the item, since keyref items won't be
17459 * put on a global list.
17460 */
17461 xmlFree(ntItem->keys);
17462 xmlFree(ntItem);
17463 }
17464 return (-1);
17465 }
17466
17467 goto selector_leave;
17468selector_key_error:
17469 /*
17470 * 4.2.1 (KEY) The ·target node set· and the
17471 * ·qualified node set· are equal, that is, every
17472 * member of the ·target node set· is also a member
17473 * of the ·qualified node set· and vice versa.
17474 */
17475 xmlSchemaVCustomErr(vctxt,
17476 XML_SCHEMAV_CVC_IDC,
17477 vctxt->node,
17478 (xmlSchemaTypePtr) idc,
17479 "All 'key' fields must evaluate to a node",
17480 NULL);
17481selector_leave:
17482 /*
17483 * Free the key-sequence if not added to the IDC table.
17484 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017485 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017486 xmlFree(*keySeq);
17487 *keySeq = NULL;
17488 }
17489 } /* if selector */
17490
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017491 sto->nbHistory--;
17492
17493deregister_check:
17494 /*
17495 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017496 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017497 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017498#if DEBUG_IDC
17499 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
17500 sto->sel->xpath);
17501#endif
17502 if (vctxt->xpathStates != sto) {
17503 xmlSchemaVErr(vctxt, vctxt->node,
17504 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017505 "Internal error: xmlSchemaXPathProcessHistory, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017506 "The state object to be removed is not the first "
17507 "in the list.\n",
17508 NULL, NULL);
17509 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017510 nextsto = sto->next;
17511 /*
17512 * Unlink from the list of active XPath state objects.
17513 */
17514 vctxt->xpathStates = sto->next;
17515 sto->next = vctxt->xpathStatePool;
17516 /*
17517 * Link it to the pool of reusable state objects.
17518 */
17519 vctxt->xpathStatePool = sto;
17520 sto = nextsto;
17521 } else
17522 sto = sto->next;
17523 } /* while (sto != NULL) */
17524 return (0);
17525}
17526
17527/**
17528 * xmlSchemaIDCRegisterMatchers:
17529 * @vctxt: the WXS validation context
17530 * @elemDecl: the element declaration
17531 *
17532 * Creates helper objects to evaluate IDC selectors/fields
17533 * successively.
17534 *
17535 * Returns 0 if OK and -1 on internal errors.
17536 */
17537static int
17538xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
17539 xmlSchemaElementPtr elemDecl)
17540{
17541 xmlSchemaIDCMatcherPtr matcher, last = NULL;
17542 xmlSchemaIDCPtr idc, refIdc;
17543 xmlSchemaIDCAugPtr aidc;
17544
17545 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
17546 if (idc == NULL)
17547 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017548
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017549#if DEBUG_IDC
17550 {
17551 xmlChar *str = NULL;
17552 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017553 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017554 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17555 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017556 FREE_AND_NULL(str)
17557 }
17558#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017559 if (vctxt->nodeInfo->idcMatchers != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017560 xmlSchemaVErr(vctxt, vctxt->node,
17561 XML_SCHEMAV_INTERNAL,
17562 "Internal error: xmlSchemaIDCRegisterMatchers: "
17563 "The chain of IDC matchers is expected to be empty.\n",
17564 NULL, NULL);
17565 return (-1);
17566 }
17567 do {
17568 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17569 /*
17570 * Since IDCs bubbles are expensive we need to know the
17571 * depth at which the bubbles should stop; this will be
17572 * the depth of the top-most keyref IDC. If no keyref
17573 * references a key/unique IDC, the bubbleDepth will
17574 * be -1, indicating that no bubbles are needed.
17575 */
17576 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
17577 if (refIdc != NULL) {
17578 /*
17579 * Lookup the augmented IDC.
17580 */
17581 aidc = vctxt->aidcs;
17582 while (aidc != NULL) {
17583 if (aidc->def == refIdc)
17584 break;
17585 aidc = aidc->next;
17586 }
17587 if (aidc == NULL) {
17588 xmlSchemaVErr(vctxt, vctxt->node,
17589 XML_SCHEMAV_INTERNAL,
17590 "Internal error: xmlSchemaIDCRegisterMatchers: "
17591 "Could not find an augmented IDC item for an IDC "
17592 "definition.\n",
17593 NULL, NULL);
17594 return (-1);
17595 }
17596 if ((aidc->bubbleDepth == -1) ||
17597 (vctxt->depth < aidc->bubbleDepth))
17598 aidc->bubbleDepth = vctxt->depth;
17599 }
17600 }
17601 /*
17602 * Lookup the augmented IDC item for the IDC definition.
17603 */
17604 aidc = vctxt->aidcs;
17605 while (aidc != NULL) {
17606 if (aidc->def == idc)
17607 break;
17608 aidc = aidc->next;
17609 }
17610 if (aidc == NULL) {
17611 xmlSchemaVErr(vctxt, vctxt->node,
17612 XML_SCHEMAV_INTERNAL,
17613 "Internal error: xmlSchemaIDCRegisterMatchers: "
17614 "Could not find an augmented IDC item for an IDC definition.\n",
17615 NULL, NULL);
17616 return (-1);
17617 }
17618 /*
17619 * Create an IDC matcher for every IDC definition.
17620 */
17621 matcher = (xmlSchemaIDCMatcherPtr)
17622 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
17623 if (matcher == NULL) {
17624 xmlSchemaVErrMemory(vctxt,
17625 "allocating an IDC matcher", NULL);
17626 return (-1);
17627 }
17628 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
17629 if (last == NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017630 vctxt->nodeInfo->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017631 else
17632 last->next = matcher;
17633 last = matcher;
17634
17635 matcher->type = IDC_MATCHER;
17636 matcher->depth = vctxt->depth;
17637 matcher->aidc = aidc;
17638#if DEBUG_IDC
17639 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
17640#endif
17641 /*
17642 * Init the automaton state object.
17643 */
17644 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017645 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017646 return (-1);
17647
17648 idc = idc->next;
17649 } while (idc != NULL);
17650 return (0);
17651}
17652
17653/**
17654 * xmlSchemaBubbleIDCNodeTables:
17655 * @depth: the current tree depth
17656 *
17657 * Merges IDC bindings of an element at @depth into the corresponding IDC
17658 * bindings of its parent element. If a duplicate note-table entry is found,
17659 * both, the parent node-table entry and child entry are discarded from the
17660 * node-table of the parent.
17661 *
17662 * Returns 0 if OK and -1 on internal errors.
17663 */
17664static int
17665xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
17666{
17667 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017668 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
17669 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017670 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
17671 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017672 int i, j, k, ret = 0, oldNum, newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017673 int duplTop;
17674
17675 /*
17676 * The node table has the following sections:
17677 *
17678 * O --> old node-table entries (first)
17679 * O
17680 * + --> new node-table entries
17681 * +
17682 * % --> new duplicate node-table entries
17683 * %
17684 * # --> old duplicate node-table entries
17685 * # (last)
17686 *
17687 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017688 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017689 if (bind == NULL) {
17690 /* Fine, no table, no bubbles. */
17691 return (0);
17692 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017693
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017694 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
17695 /*
17696 * Walk all bindings; create new or add to existing bindings.
17697 * Remove duplicate key-sequences.
17698 */
17699start_binding:
17700 while (bind != NULL) {
17701 /*
17702 * Skip keyref IDCs.
17703 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017704 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17705 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017706 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017707 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017708 /*
17709 * Check if the key/unique IDC table needs to be bubbled.
17710 */
17711 aidc = vctxt->aidcs;
17712 do {
17713 if (aidc->def == bind->definition) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017714 if (aidc->bubbleDepth >= vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017715 bind = bind->next;
17716 goto start_binding;
17717 }
17718 break;
17719 }
17720 aidc = aidc->next;
17721 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017722
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017723 if (parTable != NULL)
17724 parBind = *parTable;
17725 while (parBind != NULL) {
17726 /*
17727 * Search a matching parent binding for the
17728 * IDC definition.
17729 */
17730 if (parBind->definition == bind->definition) {
17731
17732 /*
17733 * Compare every node-table entry of the child node,
17734 * i.e. the key-sequence within, ...
17735 */
17736 oldNum = parBind->nbNodes; /* Skip newly added items. */
17737 duplTop = oldNum + parBind->nbDupls;
17738
17739 for (i = 0; i < bind->nbNodes; i++) {
17740 node = bind->nodeTable[i];
17741 if (node == NULL)
17742 continue;
17743 /*
17744 * ...with every key-sequence of the parent node, already
17745 * evaluated to be a duplicate key-sequence.
17746 */
17747 if (parBind->nbDupls != 0) {
17748 j = bind->nbNodes + newDupls;
17749 while (j < duplTop) {
17750 parNode = parBind->nodeTable[j];
17751 for (k = 0; k < bind->definition->nbFields; k++) {
17752 key = node->keys[k];
17753 parKey = parNode->keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017754 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017755 key->compValue,
17756 parKey->type, parKey->compValue);
17757 if (ret == -1) {
17758 /* TODO: Internal error */
17759 return(-1);
17760 } else if (ret == 0)
17761 break;
17762
17763 }
17764 if (ret == 1)
17765 /* Duplicate found. */
17766 break;
17767 j++;
17768 }
17769 if (j != duplTop) {
17770 /* Duplicate found. */
17771 continue;
17772 }
17773 }
17774 /*
17775 * ... and with every key-sequence of the parent node.
17776 */
17777 j = 0;
17778 while (j < oldNum) {
17779 parNode = parBind->nodeTable[j];
17780 /*
17781 * Compare key by key.
17782 */
17783 for (k = 0; k < parBind->definition->nbFields; k++) {
17784 key = node->keys[k];
17785 parKey = parNode->keys[k];
17786
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017787 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017788 key->compValue,
17789 parKey->type, parKey->compValue);
17790 if (ret == -1) {
17791 /* TODO: Internal error */
17792 } else if (ret == 0)
17793 break;
17794
17795 }
17796 if (ret == 1)
17797 /*
17798 * The key-sequences are equal.
17799 */
17800 break;
17801 j++;
17802 }
17803 if (j != oldNum) {
17804 /*
17805 * Handle duplicates.
17806 */
17807 newDupls++;
17808 oldNum--;
17809 parBind->nbNodes--;
17810 /*
17811 * Move last old item to pos of duplicate.
17812 */
17813 parBind->nodeTable[j] =
17814 parBind->nodeTable[oldNum];
17815
17816 if (parBind->nbNodes != oldNum) {
17817 /*
17818 * If new items exist, move last new item to
17819 * last of old items.
17820 */
17821 parBind->nodeTable[oldNum] =
17822 parBind->nodeTable[parBind->nbNodes];
17823 }
17824 /*
17825 * Move duplicate to last pos of new/old items.
17826 */
17827 parBind->nodeTable[parBind->nbNodes] = parNode;
17828
17829 } else {
17830 /*
17831 * Add the node-table entry (node and key-sequence) of
17832 * the child node to the node table of the parent node.
17833 */
17834 if (parBind->nodeTable == NULL) {
17835 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17836 xmlMalloc(1 * sizeof(xmlSchemaPSVIIDCNodePtr));
17837 if (parBind->nodeTable == NULL) {
17838 xmlSchemaVErrMemory(NULL,
17839 "allocating IDC list of node-table items", NULL);
17840 return(-1);
17841 }
17842 parBind->sizeNodes = 1;
17843 } else if (duplTop >= parBind->sizeNodes) {
17844 parBind->sizeNodes++;
17845 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17846 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
17847 sizeof(xmlSchemaPSVIIDCNodePtr));
17848 if (parBind->nodeTable == NULL) {
17849 xmlSchemaVErrMemory(NULL,
17850 "re-allocating IDC list of node-table items", NULL);
17851 return(-1);
17852 }
17853 }
17854
17855 /*
17856 * Move first old duplicate to last position
17857 * of old duplicates +1.
17858 */
17859 if (parBind->nbDupls != 0) {
17860 parBind->nodeTable[duplTop] =
17861 parBind->nodeTable[parBind->nbNodes + newDupls];
17862 }
17863 /*
17864 * Move first new duplicate to last position of
17865 * new duplicates +1.
17866 */
17867 if (newDupls != 0) {
17868 parBind->nodeTable[parBind->nbNodes + newDupls] =
17869 parBind->nodeTable[parBind->nbNodes];
17870 }
17871 /*
17872 * Append the new node-table entry to the 'new node-table
17873 * entries' section.
17874 */
17875 parBind->nodeTable[parBind->nbNodes] = node;
17876 parBind->nbNodes++;
17877 duplTop++;
17878 }
17879 }
17880 parBind->nbDupls += newDupls;
17881 break;
17882 }
17883 if (parBind->next == NULL)
17884 lastParBind = parBind;
17885 parBind = parBind->next;
17886 }
17887 if (parBind == NULL) {
17888 /*
17889 * No binding for the IDC was found: create a new one and
17890 * copy all node-tables.
17891 */
17892 parBind = xmlSchemaIDCNewBinding(bind->definition);
17893 if (parBind == NULL)
17894 return(-1);
17895
17896 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17897 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
17898 if (parBind->nodeTable == NULL) {
17899 xmlSchemaVErrMemory(NULL,
17900 "allocating an array of IDC node-table items", NULL);
17901 xmlSchemaIDCFreeBinding(parBind);
17902 return(-1);
17903 }
17904 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017905 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017906 memcpy(parBind->nodeTable, bind->nodeTable,
17907 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017908 if (*parTable == NULL)
17909 *parTable = parBind;
17910 else
17911 lastParBind->next = parBind;
17912 }
17913 bind = bind->next;
17914 }
17915 return (0);
17916}
17917
17918/**
17919 * xmlSchemaCheckCVCIDCKeyRef:
17920 * @vctxt: the WXS validation context
17921 * @elemDecl: the element declaration
17922 *
17923 * Check the cvc-idc-keyref constraints.
17924 */
17925static int
17926xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
17927{
17928 xmlSchemaPSVIIDCBindingPtr refbind, bind;
17929
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017930 refbind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017931 /*
17932 * Find a keyref.
17933 */
17934 while (refbind != NULL) {
17935 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17936 int i, j, k, res;
17937 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
17938 xmlSchemaPSVIIDCKeyPtr refKey, key;
17939
17940 /*
17941 * Find the referred key/unique.
17942 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017943 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017944 do {
17945 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
17946 bind->definition)
17947 break;
17948 bind = bind->next;
17949 } while (bind != NULL);
17950
17951 /*
17952 * Search for a matching key-sequences.
17953 */
17954 for (i = 0; i < refbind->nbNodes; i++) {
17955 res = 0;
17956 if (bind != NULL) {
17957 refKeys = refbind->nodeTable[i]->keys;
17958 for (j = 0; j < bind->nbNodes; j++) {
17959 keys = bind->nodeTable[j]->keys;
17960 for (k = 0; k < bind->definition->nbFields; k++) {
17961 refKey = refKeys[k];
17962 key = keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017963 res = xmlSchemaAreValuesEqual(vctxt,
17964 key->type, key->compValue,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017965 refKey->type, refKey->compValue);
17966 if (res == 0)
17967 break;
17968 else if (res == -1) {
17969 return (-1);
17970 }
17971 }
17972 if (res == 1) {
17973 /*
17974 * Match found.
17975 */
17976 break;
17977 }
17978 }
17979 }
17980 if (res == 0) {
17981 /* TODO: Report the key-sequence. */
17982 xmlSchemaVCustomErr(vctxt,
17983 XML_SCHEMAV_CVC_IDC,
17984 refbind->nodeTable[i]->node,
17985 (xmlSchemaTypePtr) refbind->definition,
17986 "No matching key-sequence found", NULL);
17987 }
17988 }
17989 }
17990 refbind = refbind->next;
17991 }
17992 return (0);
17993}
17994#endif /* IDC_ENABLED */
17995
17996#ifdef ELEM_INFO_ENABLED
17997/**
17998 * xmlSchemaBeginElement:
17999 * @vctxt: the WXS validation context
18000 *
18001 * Just a temporary workaround to simulate streaming validation
18002 * a bit.
18003 */
18004static void
18005xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
18006{
18007 vctxt->depth++;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018008 vctxt->nodeInfo = xmlSchemaGetFreshElemInfo(vctxt, vctxt->depth);
18009 vctxt->nodeInfo->node = vctxt->node;
18010 vctxt->nodeInfo->localName = vctxt->node->name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018011 if (vctxt->node->ns != NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018012 vctxt->nodeInfo->namespaceName = vctxt->node->ns->href;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018013 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018014 vctxt->nodeInfo->namespaceName = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018015}
18016
18017/**
18018 * xmlSchemaEndElement:
18019 * @vctxt: the WXS validation context
18020 *
18021 * Just a temporary workaround to simulate streaming validation
18022 * a bit.
18023 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018024static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018025xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
18026{
18027 if (vctxt->depth < 0) {
18028 /* TODO: raise error? */
18029 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018030 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018031 }
18032#ifdef IDC_ENABLED
18033 /*
18034 * Evaluate the history of changes of active state objects.
18035 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018036 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
18037 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018038
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018039 if (vctxt->nodeInfo->value != NULL) {
18040 xmlSchemaFreeValue(vctxt->nodeInfo->value);
18041 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018042 }
18043 /*
18044 * TODO: 6 The element information item must be ·valid· with respect to each of
18045 * the {identity-constraint definitions} as per Identity-constraint
18046 * Satisfied (§3.11.4).
18047 */
18048 /*
18049 * Validate IDC keyrefs.
18050 */
18051 xmlSchemaCheckCVCIDCKeyRef(vctxt);
18052#endif
18053
18054 /*
18055 * Merge/free the IDC table.
18056 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018057 if (vctxt->nodeInfo->idcTable != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018058#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018059#ifdef DEBUG_IDC
18060 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018061 vctxt->nodeInfo->namespaceName,
18062 vctxt->nodeInfo->localName,
18063 vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018064#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018065 if (vctxt->depth > 0) {
18066 /*
18067 * Merge the IDC node table with the table of the parent node.
18068 */
18069 xmlSchemaBubbleIDCNodeTables(vctxt);
18070 }
18071 /*
18072 * TODO: Don't free the PSVI IDC tables if they are
18073 * requested for the PSVI.
18074 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018075 xmlSchemaIDCFreeIDCTable(vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018076#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018077 vctxt->nodeInfo->idcTable = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018078 }
18079
18080 /*
18081 * Cleanup IDC matchers.
18082 */
18083#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018084 if (vctxt->nodeInfo->idcMatchers != NULL) {
18085 xmlSchemaIDCFreeMatcherList(vctxt->nodeInfo->idcMatchers);
18086 vctxt->nodeInfo->idcMatchers = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018087 }
18088#endif
18089
18090 /*
18091 * Skip further processing if we are on the validation root.
18092 */
18093 if (vctxt->depth == 0) {
18094 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018095 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018096 }
18097
18098 /*
18099 * Reset the bubbleDepth if needed.
18100 */
18101#ifdef IDC_ENABLED
18102 if (vctxt->aidcs != NULL) {
18103 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
18104 do {
18105 if (aidc->bubbleDepth == vctxt->depth) {
18106 /*
18107 * A bubbleDepth of a key/unique IDC matches the current
18108 * depth, this means that we are leaving the scope of the
18109 * top-most keyref IDC.
18110 */
18111 aidc->bubbleDepth = -1;
18112 }
18113 aidc = aidc->next;
18114 } while (aidc != NULL);
18115 }
18116#endif
18117 vctxt->depth--;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018118 /*
18119 * Clear the current elemInfo.
18120 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018121 if (vctxt->nodeInfo->value != NULL) {
18122 xmlSchemaFreeValue(vctxt->nodeInfo->value);
18123 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018124 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018125 vctxt->nodeInfo = vctxt->elemInfos[vctxt->depth];
18126 vctxt->node = vctxt->nodeInfo->node;
18127
18128 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018129}
18130
18131#endif /* ELEM_INFO_ENABLED */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018132
18133/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018134 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000018135 * @ctxt: a schema validation context
18136 * @node: the top node.
18137 *
18138 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018139 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000018140 *
18141 * Returns 0 if the element is schemas valid, a positive error code
18142 * number otherwise and -1 in case of internal or API error.
18143 */
18144static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018145xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
18146 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018147{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018148 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018149 int ret = 0;
18150 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018151 xmlAttrPtr attr;
18152 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018153 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000018154
18155 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018156 * This one is called by xmlSchemaValidateElementByWildcardInternal,
18157 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018158 * Note that @elemDecl will be the declaration and never the
18159 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018160 */
Daniel Veillard3646d642004-06-02 19:19:14 +000018161
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018162 if (ctxt == NULL) {
18163 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
18164 "Internal error: xmlSchemaValidateElementByDeclaration, "
18165 "bad arguments.\n",
18166 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018167 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018168 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018169
18170 elem = ctxt->node;
18171
18172 /*
18173 * cvc-elt (3.3.4) : 1
18174 */
18175 if (elemDecl == NULL) {
18176 xmlSchemaVCustomErr(ctxt,
18177 XML_SCHEMAV_CVC_ELT_1,
18178 elem, NULL,
18179 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018180 /*
18181 * Evaluate IDCs even if an error occured.
18182 */
18183#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018184 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018185 return (-1);
18186#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018187 return (ctxt->err);
18188 }
18189 /*
18190 * cvc-elt (3.3.4) : 2
18191 */
18192 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
18193 xmlSchemaVCustomErr(ctxt,
18194 XML_SCHEMAV_CVC_ELT_2,
18195 elem, NULL,
18196 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018197 /*
18198 * Evaluate IDCs even if an error occured.
18199 */
18200#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018201 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018202 return (-1);
18203#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018204 return (ctxt->err);
18205 }
18206
18207 /*
18208 * cvc-elt (3.3.4) : 3
18209 * Handle 'xsi:nil'.
18210 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018211
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018212 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018213 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018214 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18215 ctxt->node = (xmlNodePtr) attr;
18216 ctxt->cur = attr->children;
18217 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
18218 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
18219 BAD_CAST attrValue, 1, 1, 1, 1);
18220 ctxt->node = elem;
18221 ctxt->type = (xmlSchemaTypePtr) elemDecl;
18222 if (ret < 0) {
18223 xmlSchemaVCustomErr(ctxt,
18224 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018225 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018226 "Internal error: xmlSchemaValidateElementByDeclaration, "
18227 "validating the attribute 'xsi:nil'", NULL);
18228 if (attrValue != NULL)
18229 xmlFree(attrValue);
18230 return (-1);
18231 }
18232 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018233 /*
18234 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018235 */
18236 xmlSchemaVCustomErr(ctxt,
18237 XML_SCHEMAV_CVC_ELT_3_1,
18238 elem, NULL,
18239 "The element is not 'nillable'", NULL);
18240 } else {
18241 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018242 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018243 ret = 0;
18244 /*
18245 * cvc-elt (3.3.4) : 3.2.1
18246 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018247 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
18248 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018249 xmlSchemaVCustomErr(ctxt,
18250 XML_SCHEMAV_CVC_ELT_3_2_1,
18251 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018252 elem, (xmlSchemaTypePtr) elemDecl,
18253 "The 'nilled' element must have no character or "
18254 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018255 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
18256 }
18257 /*
18258 * cvc-elt (3.3.4) : 3.2.2
18259 */
18260 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
18261 (elemDecl->value != NULL)) {
18262 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
18263 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018264 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018265 "There is a fixed value constraint defined for "
18266 "the 'nilled' element", NULL);
18267 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
18268 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018269 if (ret == 0)
18270 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018271 }
18272 }
18273 if (attrValue != NULL)
18274 xmlFree(attrValue);
18275 }
18276
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018277
18278 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018279 /*
18280 * cvc-elt (3.3.4) : 4
18281 * Handle 'xsi:type'.
18282 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018283
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018284 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
18285 if (attr != NULL) {
18286 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018287
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018288 /*
18289 * TODO: We should report a *warning* that the type was overriden
18290 * by the instance.
18291 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018292
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018293 /*
18294 * cvc-elt (3.3.4) : 4.1
18295 */
18296 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18297 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
18298 &nsName, &local);
18299 if (ret < 0) {
18300 xmlSchemaVCustomErr(ctxt,
18301 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018302 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018303 "Internal error: xmlSchemaValidateElementByDeclaration, "
18304 "validating the attribute 'xsi:type'", NULL);;
18305 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018306 FREE_AND_NULL(nsName)
18307 FREE_AND_NULL(local)
18308 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018309 } else if (ret == 1) {
18310 xmlSchemaVSimpleTypeErr(ctxt,
18311 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18312 (xmlNodePtr) attr, attrValue,
18313 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
18314 } else if (ret == 2) {
18315 xmlSchemaVCustomErr(ctxt,
18316 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18317 (xmlNodePtr) attr,
18318 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18319 "The QName value '%s' has no "
18320 "corresponding namespace declaration in scope",
18321 attrValue);
18322 } else {
18323 /*
18324 * cvc-elt (3.3.4) : 4.2
18325 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018326 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
18327 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018328 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018329
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018330 xmlSchemaVCustomErr(ctxt,
18331 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018332 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018333 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18334 "The value %s does not resolve to a type "
18335 "definition",
18336 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
18337 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018338 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018339 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018340 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018341 */
18342 }
18343 }
18344 FREE_AND_NULL(attrValue)
18345 FREE_AND_NULL(nsName)
18346 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018347 }
18348 /* TODO: Change the handling of missing types according to
18349 * the spec.
18350 */
18351 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018352 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018353 XML_SCHEMAV_CVC_TYPE_1,
18354 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018355 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018356 /*
18357 * Evaluate IDCs even if an error occured.
18358 */
18359#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018360 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018361 return (-1);
18362#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018363 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018364 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018365
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018366 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018367 * Remember the actual-type definition.
18368 */
18369#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018370 ctxt->nodeInfo->typeDef = actualType;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018371#endif
18372
18373 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018374 * TODO: Since this should be already checked by the content model automaton,
18375 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
18376 * has been changed to XML_SCHEMAV_INTERNAL.
18377 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018378 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000018379 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018380 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018381 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018382 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018383 "Element %s: missing child %s\n",
18384 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018385 }
18386 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018387 }
18388 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018389 /*
18390 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018391 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018392 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000018393 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018394 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018395 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018396 "Element %s: missing child %s found %s\n",
18397 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018398 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018399 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018400 */
18401 if (elemHasContent == -1)
18402 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018403
18404 /*
18405 * IDC: Register identity-constraint XPath matchers.
18406 */
18407#ifdef IDC_ENABLED
18408 if (elemDecl->idcs != NULL)
18409 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
18410 /*
18411 * Evaluate IDCs.
18412 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018413 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018414 return (-1);
18415#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018416 /*
18417 * cvc-elt (3.3.4) : 5
18418 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018419 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018420 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018421 * cvc-elt (3.3.4) : 5.1
18422 * If the declaration has a {value constraint},
18423 * the item has neither element nor character [children] and
18424 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018425 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018426 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
18427 /*
18428 * cvc-elt (3.3.4) : 5.1.1
18429 * If the ·actual type definition· is a ·local type definition·
18430 * then the canonical lexical representation of the {value constraint}
18431 * value must be a valid default for the ·actual type definition· as
18432 * defined in Element Default Valid (Immediate) (§3.3.6).
18433 */
18434 /*
18435 * NOTE: 'local' above means types aquired by xsi:type.
18436 */
18437 ret = 0;
18438 if (actualType != elemDecl->subtypes) {
18439 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
18440 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018441 elemDecl->value, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018442 if (ret < 0) {
18443 xmlSchemaVCustomErr(ctxt,
18444 XML_SCHEMAV_INTERNAL,
18445 elem, actualType,
18446 "Internal error: xmlSchemaValidateElementByDeclaration, "
18447 "validating a default value", NULL);
18448 return (-1);
18449 }
18450 }
18451 /*
18452 * cvc-elt (3.3.4) : 5.1.2
18453 * The element information item with the canonical lexical
18454 * representation of the {value constraint} value used as its
18455 * ·normalized value· must be ·valid· with respect to the
18456 * ·actual type definition· as defined by Element Locally Valid (Type)
18457 * (§3.3.4).
18458 */
18459 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018460 * Disable validation of the simple content, if it was already
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018461 * done above.
18462 */
18463 if (ret == 0) {
18464 if (actualType != elemDecl->subtypes)
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018465 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018466 else
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018467 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018468 ctxt->node = elem;
18469 if (ret < 0) {
18470 xmlSchemaVCustomErr(ctxt,
18471 XML_SCHEMAV_INTERNAL,
18472 elem, actualType,
18473 "Internal error: xmlSchemaValidateElementByDeclaration, "
18474 "validating against the type", NULL);
18475 return (-1);
18476 }
18477 /*
18478 * PSVI: Create a text node on the instance element.
18479 */
18480 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
18481 xmlNodePtr textChild;
18482
18483 textChild = xmlNewText(elemDecl->value);
18484 if (textChild == NULL) {
18485 xmlSchemaVCustomErr(ctxt,
18486 XML_SCHEMAV_INTERNAL,
18487 elem, actualType,
18488 "Internal error: xmlSchemaValidateElementByDeclaration, "
18489 "could not create a default text node for the instance",
18490 NULL);
18491 } else
18492 xmlAddChild(elem, textChild);
18493 }
18494 }
18495
18496 } else {
18497 /*
18498 * 5.2.1 The element information item must be ·valid· with respect
18499 * to the ·actual type definition· as defined by Element Locally
18500 * Valid (Type) (§3.3.4).
18501 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018502 ret = xmlSchemaValidateElementByType(ctxt, actualType, nilled, 1);
18503 /*
18504 * Consume the computed value for IDCs, ect. Note that default
18505 * values are not supported yet.
18506 */
18507#ifdef ELEM_INFO_ENABLED
18508 if (ctxt->value != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018509 ctxt->nodeInfo->value = ctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018510 ctxt->value = NULL;
18511 }
18512#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018513 ctxt->node = elem;
18514 if (ret < 0) {
18515 xmlSchemaVCustomErr(ctxt,
18516 XML_SCHEMAV_INTERNAL,
18517 elem, actualType,
18518 "Internal error: xmlSchemaValidateElementByDeclaration, "
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018519 "calling validation by type", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018520 return (-1);
18521 }
18522 /*
18523 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
18524 * not applied, all of the following must be true:
18525 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018526 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
18527 /*
18528 * 5.2.2.1 The element information item must have no element
18529 * information item [children].
18530 *
18531 * TODO REDUNDANT: If the actual type exists, the above call to
18532 * xmlSchemaValidateElementByType will already check for element
18533 * nodes.
18534 */
18535 if (xmlSchemaHasElemContent(elem)) {
18536 xmlSchemaVCustomErr(ctxt,
18537 XML_SCHEMAV_CVC_ELT_5_2_2_1,
18538 elem, (xmlSchemaTypePtr) elemDecl,
18539 "Elements in the content are not allowed if it is "
18540 "constrained by a fixed value", NULL);
18541 } else {
18542 /*
18543 * 5.2.2.2 The appropriate case among the following must
18544 * be true:
18545 */
18546
18547 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
18548 xmlChar *value;
18549 /*
18550 * 5.2.2.2.1 If the {content type} of the ·actual type
18551 * definition· is mixed, then the *initial value* of the
18552 * item must match the canonical lexical representation
18553 * of the {value constraint} value.
18554 *
18555 * ... the *initial value* of an element information
18556 * item is the string composed of, in order, the
18557 * [character code] of each character information item in
18558 * the [children] of that element information item.
18559 */
18560 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18561 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18562 /*
18563 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018564 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018565 */
18566 xmlSchemaVCustomErr(ctxt,
18567 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
18568 elem, (xmlSchemaTypePtr) elemDecl,
18569 "The value does not match the cononical "
18570 "lexical representation of the fixed constraint",
18571 NULL);
18572 }
18573 if (value != NULL)
18574 xmlFree(value);
18575 } else if ((actualType->contentType ==
18576 XML_SCHEMA_CONTENT_SIMPLE) ||
18577 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
18578 xmlChar *value;
18579
18580 /*
18581 * 5.2.2.2.2 If the {content type} of the ·actual type
18582 * definition· is a simple type definition, then the
18583 * *actual value* of the item must match the canonical
18584 * lexical representation of the {value constraint} value.
18585 */
18586 /*
18587 * TODO: *actual value* is the normalized value, impl. this.
18588 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018589 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018590 *
18591 */
18592 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18593 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18594 xmlSchemaVCustomErr(ctxt,
18595 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
18596 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018597 "The normalized value does not match the canonical "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018598 "lexical representation of the fixed constraint",
18599 NULL);
18600 }
18601 if (value != NULL)
18602 xmlFree(value);
18603
18604 }
18605 /*
18606 * TODO: What if the content type is not 'mixed' or simple?
18607 */
18608
18609 }
18610
18611 }
18612 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018613 /*
18614 * TODO: 7 If the element information item is the ·validation root·, it must be
18615 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
18616 */
18617
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018618 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018619}
18620
Daniel Veillard4255d502002-04-16 15:50:10 +000018621/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018622 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018623 * @ctxt: a schema validation context
18624 * @node: the top node.
18625 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018626 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
18627 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018628 *
18629 * Returns 0 if the element is valid, a positive error code
18630 * number otherwise and -1 in case of an internal error.
18631 */
18632static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018633xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
18634 xmlSchemaWildcardPtr wild,
18635 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018636{
18637 const xmlChar *uri;
18638 int ret = 0;
18639 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018640
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018641 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018642 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
18643 if (ret == -1) {
18644 xmlSchemaVCustomErr(ctxt,
18645 XML_SCHEMAV_INTERNAL,
18646 ctxt->node, NULL,
18647 "Internal error: xmlSchemaValidateElement, "
18648 "assembling schema by xsi", NULL);
18649 return (-1);
18650 }
18651 /*
18652 * NOTE: We won't react on schema parser errors here.
18653 * TODO: But a warning would be nice.
18654 */
18655 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018656 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
18657 xmlSchemaElementPtr decl = NULL;
18658
18659 if (node->ns != NULL)
18660 decl = xmlHashLookup3(ctxt->schema->elemDecl,
18661 node->name, node->ns->href, NULL);
18662 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018663 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
18664 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018665 if (decl != NULL) {
18666 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018667 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018668 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018669 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018670 "Internal error: xmlSchemaValidateAnyInternal, "
18671 "validating an element in the context of a wildcard.",
18672 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000018673 }
18674 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018675 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
18676 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018677 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018678 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018679 /*
18680 * Evaluate IDCs even if a validation error occured.
18681 */
18682#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018683 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018684 return(-1);
18685#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018686 return (ctxt->err);
18687 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018688 /*
18689 * Evaluate IDCs; we need to know if an IDC field resolves to
18690 * such a node. This node has no type definition and will
18691 * definitely result in an IDC validation error if an IDC field
18692 * resolves.
18693 */
18694#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018695 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018696 return(-1);
18697#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018698 }
18699 if (node->children != NULL) {
18700 child = node->children;
18701 do {
18702 if (child->type == XML_ELEMENT_NODE) {
18703 if (child->ns != NULL)
18704 uri = child->ns->href;
18705 else
18706 uri = NULL;
18707 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018708 /* TODO: error code. */
18709 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018710 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018711 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000018712 return (ctxt->err);
18713 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018714#ifdef ELEM_INFO_ENABLED
18715 ctxt->node = child;
18716 xmlSchemaBeginElement(ctxt);
18717#endif
18718 /*
18719 * Recurse over the children.
18720 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018721 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
18722 wild, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018723 if (ret == -1)
18724 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018725#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018726 if (xmlSchemaEndElement(ctxt) == -1)
18727 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018728#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018729 if (ret != 0)
18730 return (ret);
18731 }
18732 child = child->next;
18733 } while (child != NULL);
18734 }
18735 return (0);
18736}
18737
18738/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018739 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018740 * @ctxt: a schema validation context
18741 *
18742 * Returns 0 if the element is valid, a positive error code
18743 * number otherwise and -1 in case of an internal or API error.
18744 */
18745static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018746xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
18747 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018748{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018749 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
18750 (ctxt->node == NULL)) {
18751 xmlSchemaVCustomErr(ctxt,
18752 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
18753 "Internal error: xmlSchemaValidateElementByWildcard, "
18754 "bad arguments", NULL);
18755 return (-1);
18756 }
18757 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
18758 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000018759}
18760
18761/**
William M. Brack2f2a6632004-08-20 23:09:47 +000018762 * xmlSchemaValidateAnyTypeContent:
18763 * @ctxt: a schema validation context
18764 * @node: the current element
18765 *
18766 * This one validates the content of an element of the type
18767 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
18768 * thus elements in the subtree will be validated, if a corresponding
18769 * declaration in the schema exists.
18770 *
18771 * Returns 0 if the element and its subtree is valid, a positive error code
18772 * otherwise and -1 in case of an internal or API error.
18773 */
18774static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018775xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
18776 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000018777{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018778 xmlSchemaTypePtr oldtype;
18779 xmlNodePtr top, cur;
18780 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000018781 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018782
18783 if ((type == NULL) || (ctxt->node == NULL))
18784 return (-1);
18785
18786 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018787 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018788
18789 oldtype = ctxt->type;
18790 top = ctxt->node;
18791 /*
18792 * STREAM: Child nodes are processed.
18793 */
18794 cur = ctxt->node->children;
18795 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018796 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018797 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018798 /*
18799 * The process contents of the wildcard is "lax", thus
18800 * we need to validate the element if a declaration
18801 * exists.
18802 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018803 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018804 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018805 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018806 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018807 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018808 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018809 ctxt->node = cur;
18810 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
18811 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000018812 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018813 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000018814 "Internal error: xmlSchemaValidateAnyTypeContent, "
18815 "validating an element in the context of a wildcard.",
18816 NULL, NULL);
18817 return (ret);
18818 } else if (ret > 0)
18819 return (ret);
18820 skipContent = 1;
18821 }
18822 }
18823 /*
18824 * Browse the full subtree, deep first.
18825 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018826 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018827 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018828 cur = cur->children;
18829 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018830 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018831 cur = cur->next;
18832 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018833 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018834 while (cur != top) {
18835 if (cur->parent != NULL)
18836 cur = cur->parent;
18837 if ((cur != top) && (cur->next != NULL)) {
18838 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000018839 break;
18840 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018841 if (cur->parent == NULL) {
18842 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018843 break;
18844 }
18845 }
18846 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018847 if (cur == top)
18848 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018849 } else
18850 break;
18851 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018852 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000018853 return (0);
18854}
18855
18856/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018857 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000018858 * @ctxt: a schema validation context
18859 * @node: the top node.
18860 *
18861 * Validate the content of an element expected to be a complex type type
18862 * xmlschema-1.html#cvc-complex-type
18863 * Validation Rule: Element Locally Valid (Complex Type)
18864 *
18865 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000018866 * number otherwise and -1 in case of internal or API error.
18867 * Note on reported errors: Although it might be nice to report
18868 * the name of the simple/complex type, used to validate the content
18869 * of a node, it is quite unnecessary: for global defined types
18870 * the local name of the element is equal to the NCName of the type,
18871 * for local defined types it makes no sense to output the internal
18872 * computed name of the type. TODO: Instead, one should attach the
18873 * struct of the type involved to the error handler - this allows
18874 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000018875 */
18876static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018877xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018878 xmlSchemaTypePtr type,
18879 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018880{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018881 xmlSchemaTypePtr oldtype;
18882 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018883 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000018884 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018885 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000018886
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018887 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
18888 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018889
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018890 oldtype = ctxt->type;
18891 ctxt->type = type;
18892 elem = ctxt->node;
18893
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018894 /*
18895 * Verify the attributes
18896 */
18897 /*
18898 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018899 */
18900 /* NOTE: removed, since a check for abstract is
18901 * done in the cvc-type constraint.
18902 *
18903 *
18904 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
18905 * xmlSchemaVComplexTypeErr(ctxt,
18906 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
18907 * elem, type,
18908 * "The type definition is abstract");
18909 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
18910 *}
18911 */
18912
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018913 attrs = ctxt->attr;
18914 attrTop = ctxt->attrTop;
18915 /*
18916 * STREAM: Attribute nodes are processed.
18917 */
18918 xmlSchemaRegisterAttributes(ctxt, elem->properties);
18919 xmlSchemaValidateAttributes(ctxt, elem, type);
18920 if (ctxt->attr != NULL)
18921 xmlSchemaFreeAttributeStates(ctxt->attr);
18922 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018923 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018924
18925 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018926 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018927 * model was defined. Somehow ->contModel is always not NULL
18928 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018929 * TODO: Check if the obove still occurs.
18930 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018931 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018932 case XML_SCHEMA_CONTENT_EMPTY: {
18933 /*
18934 * 1 If the {content type} is empty, then the element information
18935 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000018936 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018937 /*
18938 * TODO: Is the entity stuff correct?
18939 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018940 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018941 xmlSchemaVComplexTypeErr(ctxt,
18942 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018943 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018944 "Character or element content is not allowed, "
18945 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018946 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018947 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018948 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018949 case XML_SCHEMA_CONTENT_MIXED:
18950 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018951 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018952 /*
18953 * The type has 'anyType' as its base and no content model
18954 * is defined -> use 'anyType' as the type to validate
18955 * against.
18956 */
18957 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
18958 /* TODO: Handle -1. */
18959 break;
18960 }
18961 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018962 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018963 {
18964 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018965 xmlChar *values[10];
18966 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018967
18968 /*
18969 * Content model check initialization.
18970 */
18971 if (type->contModel != NULL) {
18972 oldregexp = ctxt->regexp;
18973 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
18974 (xmlRegExecCallbacks)
18975 xmlSchemaValidateCallback, ctxt);
18976#ifdef DEBUG_AUTOMATA
18977 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
18978#endif
18979 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018980 /*
18981 * STREAM: Children are processed.
18982 */
18983 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018984 while (child != NULL) {
18985 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018986 if (child->ns != NULL)
18987 nsUri = child->ns->href;
18988 else
18989 nsUri = NULL;
18990 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018991 child->name, nsUri, child);
18992 if (ctxt->err == XML_SCHEMAV_INTERNAL)
18993 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018994 /*
18995 * URGENT TODO: Could we anchor an error report
18996 * here to notify of invalid elements?
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018997 * TODO: Perhaps it would be better to report
18998 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018999 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019000#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000019001 if (ret < 0)
19002 xmlGenericError(xmlGenericErrorContext,
19003 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000019004 else
19005 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019006 " --> %s\n", child->name);
19007#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019008 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019009 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
19010 &values[0], &terminal);
19011 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019012 XML_SCHEMAV_ELEMENT_CONTENT,
19013 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019014 "This element is not expected",
19015 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019016 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019017 /*
19018 * Note that this will skip further validation of the
19019 * content.
19020 */
19021 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019022 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019023 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
19024 /*
19025 * TODO: Ask Daniel if this are all character nodes.
19026 */
19027 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
19028 (child->type == XML_ENTITY_NODE) ||
19029 (child->type == XML_ENTITY_REF_NODE) ||
19030 (child->type == XML_CDATA_SECTION_NODE))) {
19031 /*
19032 * 2.3 If the {content type} is element-only, then the
19033 * element information item has no character information
19034 * item [children] other than those whose [character
19035 * code] is defined as a white space in [XML 1.0 (Second
19036 * Edition)].
19037 */
William M. Brack2f2a6632004-08-20 23:09:47 +000019038 xmlSchemaVComplexTypeErr(ctxt,
19039 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019040 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019041 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019042 "because the content type is element-only");
19043 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019044 break;
19045 }
19046 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019047 }
19048 /*
19049 * Content model check finalization.
19050 */
19051 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019052 if (ret == 0) {
19053 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
19054 &values[0], &terminal);
19055 if (nbval + nbneg != 0) {
19056 /*
19057 * If a next value still exists, I does not have to
19058 * mean that there's an element missing, since it
19059 * might be an optional element. So double check it.
19060 */
19061 ret = xmlRegExecPushString(ctxt->regexp,
19062 NULL, NULL);
19063 if (ret <= 0) {
19064 ret = 1;
19065 xmlSchemaVComplexTypeElemErr(ctxt,
19066 XML_SCHEMAV_ELEMENT_CONTENT,
19067 elem, type, "Missing child element(s)",
19068 nbval, nbneg, values);
19069 } else
19070 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019071#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019072 xmlGenericError(xmlGenericErrorContext,
19073 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019074#endif
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019075 }
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019076#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019077 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019078 xmlGenericError(xmlGenericErrorContext,
19079 "Element %s content check succeeded\n",
19080 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019081#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019082 }
19083 xmlRegFreeExecCtxt(ctxt->regexp);
19084 ctxt->regexp = oldregexp;
19085 }
19086 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019087 break;
19088 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019089 case XML_SCHEMA_CONTENT_BASIC:
19090 /*
19091 * If the simple content was already validated
19092 * (e.g. a default value), the content need not
19093 * to be validated again.
19094 */
19095 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019096 xmlChar *value = NULL;
19097 /*
19098 * We hit a complexType with a simpleContent resolving
19099 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000019100 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019101 /*
19102 * 2.2 If the {content type} is a simple type definition,
19103 * then the element information item has no element
19104 * information item [children], and the ·normalized value·
19105 * of the element information item is ·valid· with respect
19106 * to that simple type definition as defined by String
19107 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019108 */
19109 /*
19110 * STREAM: Children are processed.
19111 */
19112 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019113 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019114 /*
19115 * TODO: Could the entity stuff produce elements
19116 * as well?
19117 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019118 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019119 xmlSchemaVComplexTypeErr(ctxt,
19120 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019121 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019122 "Element content is not allowed, because "
19123 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019124 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19125 break;
19126 }
19127 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019128 }
19129 ctxt->node = elem;
19130 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019131 if (ret == 0) {
19132 /*
19133 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000019134 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019135 /*
19136 * STREAM: Children are processed.
19137 */
19138 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000019139 value = NULL;
19140 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019141 value = xmlNodeGetContent(elem);
19142 /*
19143 * URGENT TODO: Should facets for the simple type validation be
19144 * disabled, if the derivation of facets for complex types
19145 * is implemented?
19146 */
19147 /*
19148 * NOTE: This call won't check the correct types of the
19149 * content nodes, since this should be done here.
19150 */
19151 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000019152 if (ret > 0) {
19153 /*
19154 * NOTE: Although an error will be reported by
19155 * xmlSchemaValidateSimpleTypeValue, the spec wants
19156 * a specific complex type error to be reported
19157 * additionally.
19158 */
19159 xmlSchemaVComplexTypeErr(ctxt,
19160 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019161 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019162 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019163 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19164 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019165 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019166 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019167 "Element '%s': Error while validating character "
19168 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019169 elem->name, type->name);
19170 if (value != NULL)
19171 xmlFree(value);
19172 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019173 return (-1);
19174 }
William M. Brack2f2a6632004-08-20 23:09:47 +000019175 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019176 if (ret == 0) {
19177 /*
19178 * Apply facets of the complexType. Be sure to pass the
19179 * built-in type to xmlSchemaValidateFacetsInternal.
19180 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019181 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000019182 * are used, or if the facets, defined by this complex type,
19183 * are to be used only. This here applies both facet sets.
19184 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000019185
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019186 ret = xmlSchemaValidateFacetsInternal(ctxt,
19187 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019188 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019189 xmlSchemaVComplexTypeErr(ctxt,
19190 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019191 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019192 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019193 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19194 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019195 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019196 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019197 "Element '%s': Error while validating character "
19198 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000019199 "apply facets.\n",
19200 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019201 if (value != NULL)
19202 xmlFree(value);
19203 ctxt->type = oldtype;
19204 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019205 }
19206 }
19207 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019208 xmlFree(value);
19209
Daniel Veillard01fa6152004-06-29 17:04:39 +000019210 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019211 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019212 default:
19213 TODO xmlGenericError(xmlGenericErrorContext,
19214 "unimplemented content type %d\n",
19215 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000019216 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019217 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019218 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019219}
19220
19221/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019222 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000019223 * @ctxt: a schema validation context
19224 * @elem: an element
19225 * @type: the list of type declarations
19226 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019227 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000019228 *
19229 * Returns 0 if the element is schemas valid, a positive error code
19230 * number otherwise and -1 in case of internal or API error.
19231 */
19232static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019233xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019234 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019235 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019236 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019237{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019238 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000019239
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019240
19241 if ((ctxt == NULL) || (type == NULL)) {
19242 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
19243 "Internal error: xmlSchemaValidateElementByType, "
19244 "bad arguments", NULL);
19245 return (-1);
19246 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019247 /*
19248 * This one is called by "xmlSchemaValidateElementByDeclaration".
19249 * It will forward to the proper validation
19250 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019251 */
19252 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019253 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019254 XML_SCHEMAV_CVC_TYPE_1,
19255 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019256 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019257 return (XML_SCHEMAV_CVC_TYPE_1);
19258 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019259
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019260 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019261 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019262 XML_SCHEMAV_CVC_TYPE_2,
19263 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019264 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019265 return (XML_SCHEMAV_CVC_TYPE_2);
19266 }
19267
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019268 switch (type->type) {
19269 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019270 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
19271 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019272 break;
19273 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019274 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019275 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019276 break;
19277 case XML_SCHEMA_TYPE_BASIC:
19278 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
19279 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
19280 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019281 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019282 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019283 break;
19284 default:
19285 ret = -1;
19286 break;
19287 }
19288 if (ret == -1)
19289 return (-1);
19290 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019291 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019292}
19293
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019294static int
19295xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019296 xmlSchemaAttrStatePtr state)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019297{
19298 xmlChar *value;
19299 const xmlChar *defValue;
19300 xmlSchemaValPtr defVal;
19301 int fixed;
19302 int ret;
19303
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019304 if (ctxt->attrInfo->typeDef == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019305 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
19306 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
19307 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019308 ctxt->node = ctxt->attrInfo->node;
19309 ctxt->cur = ctxt->node->children;
19310 value = xmlNodeListGetString(ctxt->node->doc, ctxt->cur, 1);
19311
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019312 /*
19313 * NOTE: This call also checks the content nodes for correct type.
19314 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019315 ret = xmlSchemaValidateSimpleTypeValue(ctxt, ctxt->attrInfo->typeDef,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019316 value, 1, 1, 1, 1);
19317
19318 /*
19319 * Handle 'fixed' attributes.
19320 */
19321 if (ret > 0) {
19322 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
19323 /*
19324 * NOTE: Fixed value constraints will be not
19325 * applied if the value was invalid, because:
19326 * 1. The validation process does not return a precomputed
19327 * value.
19328 * 2. An invalid value implies a violation of a fixed
19329 * value constraint.
19330 */
19331 } else if (ret == 0) {
19332 state->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019333 if (xmlSchemaGetEffectiveValueConstraint(
19334 (xmlSchemaAttributePtr) ctxt->attrInfo->decl,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019335 &fixed, &defValue, &defVal) && (fixed == 1)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019336
19337 int ws = xmlSchemaGetWhiteSpaceFacetValue(
19338 ctxt->attrInfo->typeDef);
19339
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019340 /*
19341 * cvc-au : Attribute Locally Valid (Use)
19342 * For an attribute information item to be·valid·
19343 * with respect to an attribute use its ·normalized
19344 * value· must match the canonical lexical representation
19345 * of the attribute use's {value constraint} value, if it
19346 * is present and fixed.
19347 */
19348 /*
19349 * NOTE: the validation context holds in ctxt->value the
19350 * precomputed value of the attribute; well for some types,
19351 * fallback to string comparison if no computed value
19352 * exists.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019353 * TODO: Use the *normalized* value and the *canonical* fixed
19354 * value.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019355 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019356 if (ctxt->value != NULL) {
19357 if (defVal == NULL) {
19358 xmlSchemaTypePtr prim;
19359 /*
19360 * Oops, the value was not computed.
19361 */
19362 prim = xmlSchemaGetPrimitiveType(ctxt->attrInfo->typeDef);
19363 if (prim->builtInType == XML_SCHEMAS_STRING) {
19364 xmlSchemaTypePtr builtIn;
19365
19366 builtIn = xmlSchemaGetBuiltInTypeAncestor(
19367 ctxt->attrInfo->typeDef);
19368 defVal = xmlSchemaNewStringValue(
19369 builtIn->builtInType, value);
19370 ((xmlSchemaAttributePtr) ctxt->attrInfo->decl)->defVal =
19371 defVal;
19372 value = NULL;
19373 } else {
19374 xmlSchemaVErr(ctxt, ctxt->attrInfo->node,
19375 XML_SCHEMAV_INTERNAL,
19376 "Internal error: xmlSchemaCheckAttrLocallyValid, "
19377 "could not aquire a precomputed vale",
19378 NULL, NULL);
19379 }
19380 }
19381 if (defVal != NULL) {
19382 if (xmlSchemaCompareValuesWhtsp(ctxt->value,
19383 (xmlSchemaWhitespaceValueType) ws,
19384 defVal, (xmlSchemaWhitespaceValueType) ws) != 0)
19385 state->state =
19386 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
19387 }
19388 } else if (! xmlStrEqual(defValue, BAD_CAST value)) {
19389 /*
19390 * TODO: Remove this and ensure computed values to be
19391 * existent.
19392 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019393 state->state =
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019394 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019395 }
19396 }
19397 }
19398 if (value != NULL) {
19399 xmlFree(value);
19400 }
19401 return (ret);
19402}
19403
Daniel Veillard4255d502002-04-16 15:50:10 +000019404/**
19405 * xmlSchemaValidateAttributes:
19406 * @ctxt: a schema validation context
19407 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000019408 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000019409 *
19410 * Validate the attributes of an element.
19411 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000019412 * 1. Existent, invalid attributes are reported in the form
19413 * "prefix:localName".
19414 * Reason: readability - it is easier to find the actual XML
19415 * representation of the attributes QName.
19416 * 2. Missing attributes are reported in the form
19417 * {"URI", "localName"}.
19418 * This is necessary, since the the prefix need not to be declared
19419 * at all, and thus is not computable.
19420 *
Daniel Veillard4255d502002-04-16 15:50:10 +000019421 * Returns 0 if the element is schemas valid, a positive error code
19422 * number otherwise and -1 in case of internal or API error.
19423 */
19424static int
Daniel Veillard3646d642004-06-02 19:19:14 +000019425xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019426{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019427 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000019428 int ret;
19429 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019430 const xmlChar *defValue;
19431 xmlSchemaValPtr defVal;
19432 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019433 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000019434 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019435 int found;
William M. Brack803812b2004-06-03 02:11:24 +000019436 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019437 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019438 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000019439#ifdef DEBUG_ATTR_VALIDATION
19440 int redundant = 0;
19441#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000019442
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019443
Daniel Veillardc0826a72004-08-10 14:17:33 +000019444 /*
19445 * Allow all attributes if the type is anyType.
19446 */
19447 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
19448 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019449
19450 oldnode = ctxt->node;
19451 if (type != NULL)
19452 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000019453 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019454 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000019455 attrDecl = attrUse->attr;
19456#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019457 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000019458 printf("attr use - use: %d\n", attrDecl->occurs);
19459#endif
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019460 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019461
19462 if (curState->decl == attrUse->attr) {
19463#ifdef DEBUG_ATTR_VALIDATION
19464 redundant = 1;
19465#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019466 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019467 attr = curState->attr;
19468#ifdef DEBUG_ATTR_VALIDATION
19469 printf("attr - name: %s\n", attr->name);
19470 if (attr->ns != NULL)
19471 printf("attr - ns: %s\n", attr->ns->href);
19472 else
19473 printf("attr - ns: none\n");
19474#endif
19475 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019476 if (attr == NULL)
19477 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019478 if (attrDecl->ref != NULL) {
19479 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019480 continue;
19481 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019482 if ((attrDecl->refNs == NULL) ||
19483 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019484 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019485 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019486 continue;
19487 }
19488 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019489 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019490 continue;
19491 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019492 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019493 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019494 if (attr->ns == NULL) {
19495 /*
William M. Bracke7091952004-05-11 15:09:58 +000019496 * accept an unqualified attribute only if the target
19497 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019498 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019499 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000019500 /*
19501 * This check was removed, since the target namespace
19502 * was evaluated during parsing and already took
19503 * "attributeFormDefault" into account.
19504 */
19505 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019506 continue;
19507 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019508 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019509 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019510 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019511 attr->ns->href))
19512 continue;
19513 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019514 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019515#ifdef DEBUG_ATTR_VALIDATION
19516 printf("found\n");
19517#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019518 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000019519 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019520 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
19521 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019522 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019523 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019524 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019525 if (!found) {
19526 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
19527 xmlSchemaAttrStatePtr tmp;
19528
Daniel Veillard3646d642004-06-02 19:19:14 +000019529#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019530 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019531#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019532 /*
19533 * Add a new dummy attribute state.
19534 */
19535 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
19536 if (tmp == NULL) {
19537 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
19538 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019539 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019540 }
19541 tmp->attr = NULL;
19542 tmp->state = XML_SCHEMAS_ATTR_MISSING;
19543 tmp->decl = attrDecl;
19544 tmp->next = NULL;
19545
19546 if (reqAttrStates == NULL) {
19547 reqAttrStates = tmp;
19548 reqAttrStatesTop = tmp;
19549 } else {
19550 reqAttrStatesTop->next = tmp;
19551 reqAttrStatesTop = tmp;
19552 }
19553 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
19554 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
19555 &fixed, &defValue, &defVal))) {
19556 xmlSchemaAttrStatePtr tmp;
19557 /*
19558 * Handle non existent default/fixed attributes.
19559 */
19560 tmp = (xmlSchemaAttrStatePtr)
19561 xmlMalloc(sizeof(xmlSchemaAttrState));
19562 if (tmp == NULL) {
19563 xmlSchemaVErrMemory(ctxt,
19564 "registering schema specified attributes", NULL);
19565 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019566 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019567 }
19568 tmp->attr = NULL;
19569 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
19570 tmp->decl = attrDecl;
19571 tmp->value = defValue;
19572 tmp->next = NULL;
19573
19574 if (defAttrStates == NULL) {
19575 defAttrStates = tmp;
19576 defAttrStates = tmp;
19577 } else {
19578 defAttrStates->next = tmp;
19579 defAttrStatesTop = tmp;
19580 }
19581 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019582 }
19583 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000019584 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019585 /*
19586 * Add required attributes to the attribute states of the context.
19587 */
19588 if (reqAttrStates != NULL) {
19589 if (ctxt->attr == NULL) {
19590 ctxt->attr = reqAttrStates;
19591 } else {
19592 ctxt->attrTop->next = reqAttrStates;
19593 }
19594 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019595 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019596 /*
19597 * Process wildcards.
19598 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019599
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019600 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019601#ifdef DEBUG_ATTR_VALIDATION
19602 xmlSchemaWildcardNsPtr ns;
19603 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019604 if (type->attributeWildcard->processContents ==
19605 XML_SCHEMAS_ANY_LAX)
19606 printf("processContents: lax\n");
19607 else if (type->attributeWildcard->processContents ==
19608 XML_SCHEMAS_ANY_STRICT)
19609 printf("processContents: strict\n");
19610 else
19611 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019612 if (type->attributeWildcard->any)
19613 printf("type: any\n");
19614 else if (type->attributeWildcard->negNsSet != NULL) {
19615 printf("type: negated\n");
19616 if (type->attributeWildcard->negNsSet->value == NULL)
19617 printf("ns: (absent)\n");
19618 else
19619 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
19620 } else if (type->attributeWildcard->nsSet != NULL) {
19621 printf("type: set\n");
19622 ns = type->attributeWildcard->nsSet;
19623 while (ns != NULL) {
19624 if (ns->value == NULL)
19625 printf("ns: (absent)\n");
19626 else
19627 printf("ns: %s\n", ns->value);
19628 ns = ns->next;
19629 }
19630 } else
19631 printf("empty\n");
19632
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019633
19634#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000019635 curState = ctxt->attr;
19636 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019637 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
19638 if (curState->attr->ns != NULL)
19639 nsURI = curState->attr->ns->href;
19640 else
19641 nsURI = NULL;
19642 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
19643 nsURI)) {
19644 /*
19645 * Handle processContents.
19646 */
19647 if ((type->attributeWildcard->processContents ==
19648 XML_SCHEMAS_ANY_LAX) ||
19649 (type->attributeWildcard->processContents ==
19650 XML_SCHEMAS_ANY_STRICT)) {
19651
19652 attr = curState->attr;
19653 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019654 attr->name, nsURI);
19655 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019656 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019657 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019658 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
19659 /* TODO
19660 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
19661 */
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019662 } else if (type->attributeWildcard->processContents ==
19663 XML_SCHEMAS_ANY_LAX) {
19664 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019665 } else
19666 curState->state = XML_SCHEMAS_ATTR_WILD_NO_DECL;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019667 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000019668 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019669 }
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019670 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019671 curState = curState->next;
19672 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019673 }
19674
Daniel Veillardc0826a72004-08-10 14:17:33 +000019675 if (ctxt->attr != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019676 int valueNeeded;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019677
19678 /*
19679 * Validate the value of the attribute.
19680 */
19681 if (ctxt->value != NULL) {
19682 xmlSchemaFreeValue(ctxt->value);
19683 ctxt->value = NULL;
19684 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019685 curState = ctxt->attr;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019686 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019687 valueNeeded = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019688 switch (curState->state) {
19689 case XML_SCHEMAS_ATTR_VALIDATE_VALUE:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019690
19691 /*
19692 * Create an attribute info if needed.
19693 */
19694 if (ctxt->attrInfo == NULL) {
19695 ctxt->attrInfo = (xmlSchemaElemInfoPtr)
19696 xmlMalloc(sizeof(xmlSchemaElemInfo));
19697 if (ctxt->attrInfo == NULL) {
19698 xmlSchemaVErrMemory(ctxt,
19699 "allocating an attribute info", NULL);
19700 goto fatal_exit;
19701 }
19702 }
19703 /*
19704 * Init the attribute info.
19705 */
19706 ctxt->attrInfo->flags = 0;
19707 ctxt->attrInfo->node = (xmlNodePtr) curState->attr;
19708 ctxt->attrInfo->decl = (xmlSchemaTypePtr) curState->decl;
19709 ctxt->attrInfo->value = NULL;
19710 if (curState->decl != NULL)
19711 ctxt->attrInfo->typeDef = curState->decl->subtypes;
19712 else
19713 ctxt->attrInfo->typeDef = NULL;
19714 if (curState->attr->ns != NULL)
19715 ctxt->attrInfo->namespaceName =
19716 curState->attr->ns->href;
19717 else
19718 ctxt->attrInfo->namespaceName = NULL;
19719 ctxt->attrInfo->localName = curState->attr->name;
19720
19721 ctxt->nodeInfo = ctxt->attrInfo;
19722
19723#ifdef IDC_ENABLED
19724 /*
19725 * Evaluate IDCs.
19726 */
19727 if (ctxt->xpathStates != NULL) {
19728 ret = xmlSchemaXPathEvaluate(ctxt,
19729 XML_ATTRIBUTE_NODE);
19730 if (ret == -1)
19731 goto fatal_exit;
19732 }
19733
19734#endif
19735 ret = xmlSchemaCheckAttrLocallyValid(ctxt, curState);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019736 if (ret == -1)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019737 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019738 if ((ret != 0) && (ctxt->value != NULL)) {
19739 xmlSchemaFreeValue(ctxt->value);
19740 ctxt->value = NULL;
19741 }
19742 /* No break on purpose. */
19743 case XML_SCHEMAS_ATTR_CHECKED:
19744#ifdef IDC_ENABLED
19745 if (ctxt->xpathStates != NULL) {
19746 /*
19747 * Evaluate IDCs.
19748 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019749 if (ctxt->value != NULL) {
19750 ctxt->attrInfo->value = ctxt->value;
19751 ctxt->value = NULL;
19752 }
19753 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
19754 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019755 }
19756 break;
19757#endif
19758 default:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019759 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019760 }
19761 curState = curState->next;
19762 }
19763
19764 /*
19765 * Report missing and illegal attributes.
19766 */
19767 curState = ctxt->attr;
19768 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019769 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
19770 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019771 if (curState->decl != NULL) {
19772 if (curState->decl->ref != NULL)
19773 attrDecl = curState->decl->refDecl;
19774 else
19775 attrDecl = curState->decl;
19776 } else
19777 attrDecl = NULL;
19778 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
19779 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
19780 } else if (curState->state ==
19781 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
19782 xmlSchemaVCustomErr(ctxt,
19783 XML_SCHEMAV_CVC_ATTRIBUTE_2,
19784 (xmlNodePtr) attr,
19785 (xmlSchemaTypePtr) attrDecl,
19786 "The type definition is absent",
19787 NULL);
19788 } else if (curState->state ==
19789 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
19790 xmlSchemaVCustomErr(ctxt,
19791 XML_SCHEMAV_CVC_AU,
19792 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
19793 "The value does not match the fixed value "
19794 "constraint", NULL);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019795 } else if (curState->state == XML_SCHEMAS_ATTR_WILD_NO_DECL) {
19796 xmlSchemaVWildcardErr(ctxt,
19797 XML_SCHEMAV_CVC_WILDCARD,
19798 (xmlNodePtr) attr,
19799 type->attributeWildcard,
19800 "No global attribute declaration found, but "
19801 "stipulated by the strict processContents of "
19802 "the wildcard");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019803 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019804 /* TODO: "prohibited" won't ever be touched here!.
19805 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
19806 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019807 /*
19808 * TODO: One might report different error messages
19809 * for the following errors.
19810 */
19811 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019812 xmlSchemaVIllegalAttrErr(ctxt,
19813 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
19814 } else {
19815 xmlSchemaVIllegalAttrErr(ctxt,
19816 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
19817 }
19818 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019819 }
19820 curState = curState->next;
19821 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019822 }
19823
19824 /*
19825 * Add missing default/fixed attributes.
19826 */
19827 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
19828 curState = defAttrStates;
19829 while (curState != NULL) {
19830 attrDecl = curState->decl;
19831 if (attrDecl->ref != NULL)
19832 attrDecl = attrDecl->refDecl;
19833 /*
19834 * PSVI: Add a new attribute node to the current element.
19835 */
19836 if (attrDecl->targetNamespace == NULL) {
19837 xmlNewProp(elem, attrDecl->name, curState->value);
19838 } else {
19839 xmlNsPtr ns;
19840
19841 ns = xmlSearchNsByHref(elem->doc, elem,
19842 attrDecl->targetNamespace);
19843 if (ns == NULL) {
19844 xmlChar prefix[12];
19845 int counter = 1;
19846
19847 attr = curState->attr;
19848 /*
19849 * Create a namespace declaration on the validation
19850 * root node if no namespace declaration is in scope.
19851 */
19852 snprintf((char *) prefix, sizeof(prefix), "p");
19853 /*
19854 * This is somehow not performant, since the ancestor
19855 * axis beyond @elem will be searched as well.
19856 */
19857 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
19858 while (ns != NULL) {
19859 if (counter > 1000) {
19860 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
19861 XML_SCHEMAV_INTERNAL,
19862 "Internal error: xmlSchemaValidateAttributes, "
19863 "could not compute a ns prefix for "
19864 "default/fixed attribute '%s'.\n",
19865 attrDecl->name, NULL);
19866
19867 break;
19868 }
19869 snprintf((char *) prefix,
19870 sizeof(prefix), "p%d", counter++);
19871 ns = xmlSearchNs(elem->doc, elem,
19872 BAD_CAST prefix);
19873 }
19874 if (ns == NULL) {
19875 ns = xmlNewNs(ctxt->validationRoot,
19876 attrDecl->targetNamespace, BAD_CAST prefix);
19877 xmlNewNsProp(elem, ns, attrDecl->name,
19878 curState->value);
19879 }
19880 } else {
19881 xmlNewNsProp(elem, ns, attrDecl->name,
19882 curState->value);
19883 }
19884 }
19885 curState = curState->next;
19886 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019887 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019888 ret = ctxt->err;
19889 goto exit;
19890
19891fatal_exit:
19892 ret = -1;
19893
19894exit:
19895
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019896 if (defAttrStates != NULL)
19897 xmlSchemaFreeAttributeStates(defAttrStates);
19898
Daniel Veillard3646d642004-06-02 19:19:14 +000019899#ifdef DEBUG_ATTR_VALIDATION
19900 if (redundant)
19901 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019902 "xmlSchemaValidateAttributes: redundant call by "
19903 "type: %s\n", type->name);
Daniel Veillard3646d642004-06-02 19:19:14 +000019904#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019905 ctxt->nodeInfo = ctxt->elemInfos[ctxt->depth];
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019906 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019907 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019908}
19909
19910/**
19911 * xmlSchemaValidateElement:
19912 * @ctxt: a schema validation context
19913 * @elem: an element
19914 *
19915 * Validate an element in a tree
19916 *
19917 * Returns 0 if the element is schemas valid, a positive error code
19918 * number otherwise and -1 in case of internal or API error.
19919 */
19920static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019921xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019922{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019923 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019924 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000019925
Daniel Veillardc0826a72004-08-10 14:17:33 +000019926 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019927 * This one is called by xmlSchemaValidateDocument and
19928 * xmlSchemaValidateOneElement.
19929 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019930 if (ctxt->schema == NULL) {
19931 /*
19932 * No schema was specified at time of creation of the validation
19933 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
19934 * of the instance to build a schema.
19935 */
19936 if (ctxt->pctxt == NULL)
19937 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
19938 if (ctxt->pctxt == NULL)
19939 return (-1);
19940 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
19941 if (ctxt->schema == NULL)
19942 return (-1);
19943 /* TODO: assign user data. */
19944 ctxt->pctxt->error = ctxt->error;
19945 ctxt->pctxt->warning = ctxt->warning;
19946 ctxt->xsiAssemble = 1;
19947 } else
19948 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019949 /*
19950 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000019951 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019952 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019953 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
19954 if (ret == -1) {
19955 xmlSchemaVCustomErr(ctxt,
19956 XML_SCHEMAV_INTERNAL,
19957 ctxt->node, NULL,
19958 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019959 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019960 }
19961 /*
19962 * NOTE: We won't react on schema parser errors here.
19963 * TODO: But a warning would be nice.
19964 */
19965 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019966 if (ret != -1) {
19967 if (ctxt->node->ns != NULL)
19968 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
19969 ctxt->node->ns->href);
19970 else
19971 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
19972
19973 if (elemDecl == NULL) {
19974 xmlSchemaVCustomErr(ctxt,
19975 XML_SCHEMAV_CVC_ELT_1,
19976 ctxt->node, NULL,
19977 "No matching global declaration available", NULL);
19978 ret = XML_SCHEMAV_CVC_ELT_1;
19979 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019980#ifdef IDC_ENABLED
19981 /*
19982 * Augment the IDC definitions.
19983 */
19984 if (ctxt->schema->idcDef != NULL) {
19985 xmlHashScan(ctxt->schema->idcDef,
19986 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
19987 }
19988#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019989#ifdef ELEM_INFO_ENABLED
19990 ctxt->depth = -1;
19991 xmlSchemaBeginElement(ctxt);
19992#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019993 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019994#ifdef ELEM_INFO_ENABLED
19995 xmlSchemaEndElement(ctxt);
19996#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019997 if (ret < 0) {
19998 xmlSchemaVCustomErr(ctxt,
19999 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
20000 "Internal error: xmlSchemaValidateElement, "
20001 "calling validation by declaration", NULL);
20002 }
20003 }
20004 }
20005 /* ctxt->xsiAssemble = 0; */
20006 if (ctxt->xsiAssemble) {
20007 if (ctxt->schema != NULL) {
20008 xmlSchemaFree(ctxt->schema);
20009 ctxt->schema = NULL;
20010 }
Daniel Veillard4255d502002-04-16 15:50:10 +000020011 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020012 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020013}
20014
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020015
Daniel Veillard4255d502002-04-16 15:50:10 +000020016/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020017 * xmlSchemaValidateOneElement:
20018 * @ctxt: a schema validation context
20019 * @elem: an element node
20020 *
20021 * Validate a branch of a tree, starting with the given @elem.
20022 *
20023 * Returns 0 if the element and its subtree is valid, a positive error
20024 * code number otherwise and -1 in case of an internal or API error.
20025 */
20026int
20027xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
20028{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020029 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020030 return (-1);
20031
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020032 if (ctxt->schema == NULL) {
20033 xmlSchemaVErr(ctxt, NULL,
20034 XML_SCHEMAV_INTERNAL,
20035 "API error: xmlSchemaValidateOneElement, "
20036 "no schema specified.\n", NULL, NULL);
20037 return (-1);
20038 }
20039
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020040 ctxt->doc = elem->doc;
20041 ctxt->err = 0;
20042 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020043 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020044 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020045 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020046}
20047
20048/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020049 * xmlSchemaValidateDocument:
20050 * @ctxt: a schema validation context
20051 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020052 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000020053 *
20054 * Validate a document tree in memory.
20055 *
20056 * Returns 0 if the document is schemas valid, a positive error code
20057 * number otherwise and -1 in case of internal or API error.
20058 */
20059static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020060xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
20061{
Daniel Veillard4255d502002-04-16 15:50:10 +000020062 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000020063
Daniel Veillard4255d502002-04-16 15:50:10 +000020064 root = xmlDocGetRootElement(doc);
20065 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020066 xmlSchemaVCustomErr(ctxt,
20067 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
20068 (xmlNodePtr) doc, NULL,
20069 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020070 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020071 }
Daniel Veillard4255d502002-04-16 15:50:10 +000020072 /*
20073 * Okay, start the recursive validation
20074 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020075 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020076 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020077 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000020078
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020079 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000020080}
20081
20082/************************************************************************
20083 * *
20084 * SAX Validation code *
20085 * *
20086 ************************************************************************/
20087
20088/************************************************************************
20089 * *
20090 * Validation interfaces *
20091 * *
20092 ************************************************************************/
20093
20094/**
20095 * xmlSchemaNewValidCtxt:
20096 * @schema: a precompiled XML Schemas
20097 *
20098 * Create an XML Schemas validation context based on the given schema
20099 *
20100 * Returns the validation context or NULL in case of error
20101 */
20102xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020103xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
20104{
Daniel Veillard4255d502002-04-16 15:50:10 +000020105 xmlSchemaValidCtxtPtr ret;
20106
20107 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
20108 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020109 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000020110 return (NULL);
20111 }
20112 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000020113 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000020114 ret->attrTop = NULL;
20115 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000020116 return (ret);
20117}
20118
20119/**
20120 * xmlSchemaFreeValidCtxt:
20121 * @ctxt: the schema validation context
20122 *
20123 * Free the resources associated to the schema validation context
20124 */
20125void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020126xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
20127{
Daniel Veillard4255d502002-04-16 15:50:10 +000020128 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020129 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000020130 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000020131 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000020132 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020133 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020134 if (ctxt->pctxt != NULL) {
20135 xmlSchemaFreeParserCtxt(ctxt->pctxt);
20136 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020137
20138#ifdef IDC_ENABLED
20139 if (ctxt->idcNodes != NULL) {
20140 int i;
20141 xmlSchemaPSVIIDCNodePtr item;
20142
20143 for (i = 0; i < ctxt->nbIdcNodes; i++) {
20144 item = ctxt->idcNodes[i];
20145 xmlFree(item->keys);
20146 xmlFree(item);
20147 }
20148 xmlFree(ctxt->idcNodes);
20149 }
20150
20151 if (ctxt->idcKeys != NULL) {
20152 int i;
20153 for (i = 0; i < ctxt->nbIdcKeys; i++)
20154 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
20155 xmlFree(ctxt->idcKeys);
20156 }
20157
20158 if (ctxt->xpathStates != NULL)
20159 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
20160 if (ctxt->xpathStatePool != NULL)
20161 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
20162
20163 /*
20164 * Augmented IDC information.
20165 */
20166 if (ctxt->aidcs != NULL) {
20167 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
20168 do {
20169 next = cur->next;
20170 xmlFree(cur);
20171 cur = next;
20172 } while (cur != NULL);
20173 }
20174#endif /* IDC_ENABLED */
20175#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020176 if (ctxt->attrInfo != NULL) {
20177 if (ctxt->attrInfo->value != NULL)
20178 xmlSchemaFreeValue(ctxt->attrInfo->value);
20179 xmlFree(ctxt->attrInfo);
20180 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020181 if (ctxt->elemInfos != NULL) {
20182 int i;
20183 xmlSchemaElemInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020184
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020185 for (i = 0; i < ctxt->sizeElemInfos; i++) {
20186 info = ctxt->elemInfos[i];
20187 if (info == NULL)
20188 continue;
20189 if (info->value != NULL)
20190 xmlSchemaFreeValue(info->value);
20191#ifdef IDC_ENABLED
20192 if (info->idcMatchers != NULL)
20193 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
20194#endif
20195 /*
20196 * TODO: Free the IDC table if still existent.
20197 */
20198
20199 /*
20200 xmlFree(info->localName);
20201 if (info->namespaceName != NULL)
20202 xmlFree(info->namespaceName);
20203 */
20204 xmlFree(info);
20205 }
20206 xmlFree(ctxt->elemInfos);
20207 }
20208#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000020209 xmlFree(ctxt);
20210}
20211
20212/**
20213 * xmlSchemaSetValidErrors:
20214 * @ctxt: a schema validation context
20215 * @err: the error function
20216 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000020217 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000020218 *
William M. Brack2f2a6632004-08-20 23:09:47 +000020219 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000020220 */
20221void
20222xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020223 xmlSchemaValidityErrorFunc err,
20224 xmlSchemaValidityWarningFunc warn, void *ctx)
20225{
Daniel Veillard4255d502002-04-16 15:50:10 +000020226 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020227 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000020228 ctxt->error = err;
20229 ctxt->warning = warn;
20230 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020231 if (ctxt->pctxt != NULL)
20232 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000020233}
20234
20235/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000020236 * xmlSchemaGetValidErrors:
20237 * @ctxt: a XML-Schema validation context
20238 * @err: the error function result
20239 * @warn: the warning function result
20240 * @ctx: the functions context result
20241 *
20242 * Get the error and warning callback informations
20243 *
20244 * Returns -1 in case of error and 0 otherwise
20245 */
20246int
20247xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
20248 xmlSchemaValidityErrorFunc * err,
20249 xmlSchemaValidityWarningFunc * warn, void **ctx)
20250{
20251 if (ctxt == NULL)
20252 return (-1);
20253 if (err != NULL)
20254 *err = ctxt->error;
20255 if (warn != NULL)
20256 *warn = ctxt->warning;
20257 if (ctx != NULL)
20258 *ctx = ctxt->userData;
20259 return (0);
20260}
20261
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020262
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020263/**
Daniel Veillard6927b102004-10-27 17:29:04 +000020264 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020265 * @ctxt: a schema validation context
20266 * @options: a combination of xmlSchemaValidOption
20267 *
20268 * Sets the options to be used during the validation.
20269 *
20270 * Returns 0 in case of success, -1 in case of an
20271 * API error.
20272 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020273int
20274xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
20275 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020276
20277{
20278 int i;
20279
20280 if (ctxt == NULL)
20281 return (-1);
20282 /*
20283 * WARNING: Change the start value if adding to the
20284 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020285 * TODO: Is there an other, more easy to maintain,
20286 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020287 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020288 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020289 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020290 xmlSchemaVErr(ctxt, NULL,
20291 XML_SCHEMAV_INTERNAL,
20292 "Internal error: xmlSchemaSetValidOptions, "
20293 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020294 return (-1);
20295 }
20296 }
20297 ctxt->options = options;
20298 return (0);
20299}
20300
20301/**
Daniel Veillard6927b102004-10-27 17:29:04 +000020302 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020303 * @ctxt: a schema validation context
20304 *
William M. Brack21e4ef22005-01-02 09:53:13 +000020305 * Get the validation context options.
20306 *
20307 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020308 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020309int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020310xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
20311
20312{
20313 if (ctxt == NULL)
20314 return (-1);
20315 else
20316 return (ctxt->options);
20317}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020318
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020319
Daniel Veillard259f0df2004-08-18 09:13:18 +000020320/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020321 * xmlSchemaValidateDoc:
20322 * @ctxt: a schema validation context
20323 * @doc: a parsed document tree
20324 *
20325 * Validate a document tree in memory.
20326 *
20327 * Returns 0 if the document is schemas valid, a positive error code
20328 * number otherwise and -1 in case of internal or API error.
20329 */
20330int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020331xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
20332{
Daniel Veillard4255d502002-04-16 15:50:10 +000020333 int ret;
20334
20335 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020336 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020337
20338 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000020339 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020340 ctxt->nberrors = 0;
20341
20342 /*
20343 if (ctxt->schema == NULL) {
20344 xmlSchemaVErr(ctxt, NULL,
20345 XML_SCHEMAV_INTERNAL,
20346 "API error: xmlSchemaValidateDoc, "
20347 "no schema specified and assembling of schemata "
20348 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
20349 "is not enabled.\n", NULL, NULL);
20350 return (-1);
20351 }
20352 */
Daniel Veillard4255d502002-04-16 15:50:10 +000020353 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020354 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020355}
20356
20357/**
20358 * xmlSchemaValidateStream:
20359 * @ctxt: a schema validation context
20360 * @input: the input to use for reading the data
20361 * @enc: an optional encoding information
20362 * @sax: a SAX handler for the resulting events
20363 * @user_data: the context to provide to the SAX handler.
20364 *
20365 * Validate a document tree in memory.
20366 *
20367 * Returns 0 if the document is schemas valid, a positive error code
20368 * number otherwise and -1 in case of internal or API error.
20369 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020370int
Daniel Veillard4255d502002-04-16 15:50:10 +000020371xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020372 xmlParserInputBufferPtr input, xmlCharEncoding enc,
20373 xmlSAXHandlerPtr sax, void *user_data)
20374{
Daniel Veillard4255d502002-04-16 15:50:10 +000020375 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020376 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020377 ctxt->input = input;
20378 ctxt->enc = enc;
20379 ctxt->sax = sax;
20380 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020381 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020382}
20383
20384#endif /* LIBXML_SCHEMAS_ENABLED */