blob: cd49a1ee4593c99a5fbced2ab8524e4fb43abfab [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),
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00004201 NULL, NULL, "The ID '%s' is already defined",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004202 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;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00005227
5228 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5229 node, BAD_CAST "id");
5230
5231 if (IS_SCHEMA(child, "annotation")) {
5232 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5233 child = child->next;
5234 }
5235
Daniel Veillard4255d502002-04-16 15:50:10 +00005236 child = node->children;
5237 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005238 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5239 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005240 }
5241 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005242 xmlSchemaPErr2(ctxt, node, child,
5243 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
5244 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005245 }
5246
5247 return (ret);
5248}
5249
5250/**
5251 * xmlSchemaParseAnyAttribute:
5252 * @ctxt: a schema validation context
5253 * @schema: the schema being built
5254 * @node: a subtree containing XML Schema informations
5255 *
5256 * parse a XML schema AnyAttrribute declaration
5257 * *WARNING* this interface is highly subject to change
5258 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005259 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00005260 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005261static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005262xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5263 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005264{
Daniel Veillard3646d642004-06-02 19:19:14 +00005265 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005266 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005267 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005268
5269 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5270 return (NULL);
5271
Daniel Veillard3646d642004-06-02 19:19:14 +00005272 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005273 if (ret == NULL) {
5274 return (NULL);
5275 }
William M. Bracke7091952004-05-11 15:09:58 +00005276 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005277 /*
5278 * Check for illegal attributes.
5279 */
5280 attr = node->properties;
5281 while (attr != NULL) {
5282 if (attr->ns == NULL) {
5283 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5284 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
5285 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
5286 xmlSchemaPIllegalAttrErr(ctxt,
5287 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5288 NULL, NULL, attr);
5289 }
5290 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5291 xmlSchemaPIllegalAttrErr(ctxt,
5292 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5293 NULL, NULL, attr);
5294 }
5295 attr = attr->next;
5296 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005297 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5298 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005299 /*
5300 * Parse the namespace list.
5301 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005302 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
5303 xmlSchemaFreeWildcard(ret);
5304 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005305 }
5306 /*
5307 * And now for the children...
5308 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005309 child = node->children;
5310 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005311 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5312 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005313 }
5314 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005315 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005316 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5317 NULL, NULL, node, child,
5318 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005319 }
5320
5321 return (ret);
5322}
5323
5324
5325/**
5326 * xmlSchemaParseAttribute:
5327 * @ctxt: a schema validation context
5328 * @schema: the schema being built
5329 * @node: a subtree containing XML Schema informations
5330 *
5331 * parse a XML schema Attrribute declaration
5332 * *WARNING* this interface is highly subject to change
5333 *
William M. Bracke7091952004-05-11 15:09:58 +00005334 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005335 */
5336static xmlSchemaAttributePtr
5337xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005338 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005339{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005340 const xmlChar *name, *attrValue;
5341 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00005342 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005343 xmlNodePtr child = NULL;
5344 xmlAttrPtr attr, nameAttr;
5345 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005346
5347 /*
5348 * Note that the w3c spec assumes the schema to be validated with schema
5349 * for schemas beforehand.
5350 *
5351 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00005352 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005353
5354 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5355 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005356 attr = xmlSchemaGetPropNode(node, "ref");
5357 nameAttr = xmlSchemaGetPropNode(node, "name");
5358
5359 if ((attr == NULL) && (nameAttr == NULL)) {
5360 /*
5361 * 3.2.3 : 3.1
5362 * One of ref or name must be present, but not both
5363 */
5364 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5365 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
5366 "One of the attributes 'ref' or 'name' must be present");
5367 return (NULL);
5368 }
5369 if ((topLevel) || (attr == NULL)) {
5370 if (nameAttr == NULL) {
5371 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
5372 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5373 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005374 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005375 }
5376 } else
5377 isRef = 1;
5378
5379 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005380 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005381 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
5382
5383 /*
5384 * Parse as attribute reference.
5385 */
5386 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
5387 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
5388 &refPrefix, &ref) != 0) {
5389 return (NULL);
5390 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005391 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005392 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005393 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005394 if (ret == NULL) {
5395 if (repName != NULL)
5396 xmlFree(repName);
5397 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005398 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005399 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5400 ret->node = node;
5401 ret->refNs = refNs;
5402 ret->refPrefix = refPrefix;
5403 ret->ref = ref;
5404 /*
5405 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
5406 */
5407 if (nameAttr != NULL)
5408 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5409 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5410 "ref", "name");
5411 /*
5412 * Check for illegal attributes.
5413 */
5414 attr = node->properties;
5415 while (attr != NULL) {
5416 if (attr->ns == NULL) {
5417 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
5418 xmlStrEqual(attr->name, BAD_CAST "form")) {
5419 /*
5420 * 3.2.3 : 3.2
5421 * If ref is present, then all of <simpleType>,
5422 * form and type must be absent.
5423 */
5424 xmlSchemaPIllegalAttrErr(ctxt,
5425 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
5426 (xmlSchemaTypePtr) ret, attr);
5427 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
5428 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
5429 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5430 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5431 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5432 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
5433 xmlSchemaPIllegalAttrErr(ctxt,
5434 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5435 &repName, (xmlSchemaTypePtr) ret, attr);
5436 }
5437 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5438 xmlSchemaPIllegalAttrErr(ctxt,
5439 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5440 &repName, (xmlSchemaTypePtr) ret, attr);
5441 }
5442 attr = attr->next;
5443 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005444 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005445 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005446
5447 /*
5448 * Parse as attribute declaration.
5449 */
5450 if (xmlSchemaPValAttrNode(ctxt,
5451 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
5452 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5453 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005454 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005455 /*
5456 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
5457 */
5458 /*
5459 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
5460 */
5461 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
5462 xmlSchemaPSimpleTypeErr(ctxt,
5463 XML_SCHEMAP_NO_XMLNS,
5464 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005465 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005466 "The value must not match 'xmlns'",
5467 NULL, NULL);
5468 if (repName != NULL)
5469 xmlFree(repName);
5470 return (NULL);
5471 }
5472 /*
5473 * Evaluate the target namespace
5474 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005475 if (topLevel) {
5476 ns = schema->targetNamespace;
5477 } else {
5478 attr = xmlSchemaGetPropNode(node, "form");
5479 if (attr != NULL) {
5480 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5481 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
5482 ns = schema->targetNamespace;
5483 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5484 xmlSchemaPSimpleTypeErr(ctxt,
5485 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5486 &repName, NULL, (xmlNodePtr) attr,
5487 NULL, "(qualified | unqualified)",
5488 attrValue, NULL, NULL, NULL);
5489 }
5490 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
5491 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005492 }
5493 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005494 if (ret == NULL) {
5495 if (repName != NULL)
5496 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00005497 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005498 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005499 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005500 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005501 if (topLevel)
5502 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
5503 /*
5504 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
5505 */
5506 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
5507 xmlSchemaPCustomErr(ctxt,
5508 XML_SCHEMAP_NO_XSI,
5509 &repName, (xmlSchemaTypePtr) ret, node,
5510 "The target namespace must not match '%s'",
5511 xmlSchemaInstanceNs);
5512 }
5513 /*
5514 * Check for illegal attributes.
5515 */
5516 attr = node->properties;
5517 while (attr != NULL) {
5518 if (attr->ns == NULL) {
5519 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5520 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5521 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5522 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5523 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
5524 if ((topLevel) ||
5525 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
5526 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
5527 xmlSchemaPIllegalAttrErr(ctxt,
5528 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5529 &repName, (xmlSchemaTypePtr) ret, attr);
5530 }
5531 }
5532 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5533 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5534 &repName, (xmlSchemaTypePtr) ret, attr);
5535 }
5536 attr = attr->next;
5537 }
5538 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
5539 node, "type", &ret->typeNs, NULL, &ret->typeName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005540 }
5541 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5542 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00005543 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005544 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00005545 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005546 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
5547 if (ret->defValue != NULL)
5548 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
5549 /*
5550 * Attribute "default".
5551 */
5552 attr = xmlSchemaGetPropNode(node, "default");
5553 if (attr != NULL) {
5554 /*
5555 * 3.2.3 : 1
5556 * default and fixed must not both be present.
5557 */
5558 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
5559 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
5560 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
5561 } else
5562 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5563 }
5564 if (topLevel == 0) {
5565 /*
5566 * Attribute "use".
5567 */
5568 attr = xmlSchemaGetPropNode(node, "use");
5569 if (attr != NULL) {
5570 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5571 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
5572 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5573 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
5574 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
5575 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
5576 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
5577 else
5578 xmlSchemaPSimpleTypeErr(ctxt,
5579 XML_SCHEMAP_INVALID_ATTR_USE,
5580 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005581 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005582 attrValue, NULL, NULL, NULL);
5583 } else
5584 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5585 /*
5586 * 3.2.3 : 2
5587 * If default and use are both present, use must have
5588 * the actual value optional.
5589 */
5590 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
5591 (ret->defValue != NULL) &&
5592 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
5593 xmlSchemaPSimpleTypeErr(ctxt,
5594 XML_SCHEMAP_SRC_ATTRIBUTE_2,
5595 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005596 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005597 "The value must be 'optional' if the attribute "
5598 "'default' is present as well", NULL, NULL);
5599 }
5600 }
5601 /*
5602 * And now for the children...
5603 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005604 child = node->children;
5605 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005606 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5607 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005608 }
5609 if (isRef) {
5610 if (child != NULL) {
5611 if (IS_SCHEMA(child, "simpleType"))
5612 /*
5613 * 3.2.3 : 3.2
5614 * If ref is present, then all of <simpleType>,
5615 * form and type must be absent.
5616 */
5617 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
5618 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5619 "(annotation?)");
5620 else
5621 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5622 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5623 "(annotation?)");
5624 }
5625 } else {
5626 if (IS_SCHEMA(child, "simpleType")) {
5627 if (ret->typeName != NULL) {
5628 /*
5629 * 3.2.3 : 4
5630 * type and <simpleType> must not both be present.
5631 */
5632 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
5633 &repName, (xmlSchemaTypePtr) ret, node, child,
5634 "The attribute 'type' and the <simpleType> child "
5635 "are mutually exclusive", NULL);
5636 } else
5637 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5638 child = child->next;
5639 }
5640 if (child != NULL)
5641 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5642 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5643 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005644 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005645 /*
5646 * Cleanup.
5647 */
5648 if (repName != NULL)
5649 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005650 return (ret);
5651}
5652
5653/**
5654 * xmlSchemaParseAttributeGroup:
5655 * @ctxt: a schema validation context
5656 * @schema: the schema being built
5657 * @node: a subtree containing XML Schema informations
5658 *
5659 * parse a XML schema Attribute Group declaration
5660 * *WARNING* this interface is highly subject to change
5661 *
5662 * Returns the attribute group or NULL in case of error.
5663 */
5664static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005665xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005666 xmlSchemaPtr schema, xmlNodePtr node,
5667 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005668{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005669 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005670 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005671 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005672 const xmlChar *oldcontainer;
5673 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005674
5675 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5676 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005677
5678 nameAttr = xmlSchemaGetPropNode(node, "name");
5679 attr = xmlSchemaGetPropNode(node, "ref");
5680 if ((topLevel) || (attr == NULL)) {
5681 /*
5682 * Parse as an attribute group definition.
5683 * Note that those are allowed at top level only.
5684 */
5685 if (nameAttr == NULL) {
5686 xmlSchemaPMissingAttrErr(ctxt,
5687 XML_SCHEMAP_S4S_ATTR_MISSING,
5688 NULL, NULL, node, "name", NULL);
5689 return (NULL);
5690 }
5691 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5692 /*
5693 * The name is crucial, exit if invalid.
5694 */
5695 if (xmlSchemaPValAttrNode(ctxt,
5696 NULL, NULL, nameAttr,
5697 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5698 return (NULL);
5699 }
5700 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5701 if (ret == NULL)
5702 return (NULL);
5703 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5704 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5705 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005706 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005707 } else {
5708 char buf[50];
5709 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5710
5711 /*
5712 * Parse as an attribute group definition reference.
5713 */
5714 if (attr == NULL) {
5715 xmlSchemaPMissingAttrErr(ctxt,
5716 XML_SCHEMAP_S4S_ATTR_MISSING,
5717 NULL, NULL, node, "ref", NULL);
5718 }
5719 xmlSchemaPValAttrNodeQName(ctxt, schema,
5720 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5721
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005722 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005723 name = (const xmlChar *) buf;
5724 if (name == NULL) {
5725 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5726 "attribute group definition reference", node);
5727 return (NULL);
5728 }
5729 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5730 if (ret == NULL)
5731 return (NULL);
5732 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5733 ret->ref = ref;
5734 ret->refNs = refNs;
5735 /* TODO: Is @refPrefix currently used? */
5736 ret->refPrefix = refPrefix;
5737 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005738 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005739 /*
5740 * Check for illegal attributes.
5741 */
5742 attr = node->properties;
5743 while (attr != NULL) {
5744 if (attr->ns == NULL) {
5745 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5746 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5747 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5748 {
5749 xmlSchemaPIllegalAttrErr(ctxt,
5750 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5751 NULL, NULL, attr);
5752 }
5753 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5754 xmlSchemaPIllegalAttrErr(ctxt,
5755 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5756 NULL, NULL, attr);
5757 }
5758 attr = attr->next;
5759 }
5760 /* TODO: Validate "id" ? */
5761 /*
5762 * And now for the children...
5763 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005764 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005765 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005766 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005767 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005768 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5769 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005770 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005771 if (topLevel) {
5772 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5773 if (IS_SCHEMA(child, "anyAttribute")) {
5774 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5775 child = child->next;
5776 }
5777 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005778 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005779 xmlSchemaPContentErr(ctxt,
5780 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5781 NULL, NULL, node, child, NULL,
5782 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005783 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005784 ctxt->container = oldcontainer;
5785 return (ret);
5786}
5787
5788/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005789 * xmlSchemaPValAttrFormDefault:
5790 * @value: the value
5791 * @flags: the flags to be modified
5792 * @flagQualified: the specific flag for "qualified"
5793 *
5794 * Returns 0 if the value is valid, 1 otherwise.
5795 */
5796static int
5797xmlSchemaPValAttrFormDefault(const xmlChar *value,
5798 int *flags,
5799 int flagQualified)
5800{
5801 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5802 if ((*flags & flagQualified) == 0)
5803 *flags |= flagQualified;
5804 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5805 return (1);
5806
5807 return (0);
5808}
5809
5810/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005811 * xmlSchemaPValAttrBlockFinal:
5812 * @value: the value
5813 * @flags: the flags to be modified
5814 * @flagAll: the specific flag for "#all"
5815 * @flagExtension: the specific flag for "extension"
5816 * @flagRestriction: the specific flag for "restriction"
5817 * @flagSubstitution: the specific flag for "substitution"
5818 * @flagList: the specific flag for "list"
5819 * @flagUnion: the specific flag for "union"
5820 *
5821 * Validates the value of the attribute "final" and "block". The value
5822 * is converted into the specified flag values and returned in @flags.
5823 *
5824 * Returns 0 if the value is valid, 1 otherwise.
5825 */
5826
5827static int
5828xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5829 int *flags,
5830 int flagAll,
5831 int flagExtension,
5832 int flagRestriction,
5833 int flagSubstitution,
5834 int flagList,
5835 int flagUnion)
5836{
5837 int ret = 0;
5838
5839 /*
5840 * TODO: This does not check for dublicate entries.
5841 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005842 if (value == NULL)
5843 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005844 if (xmlStrEqual(value, BAD_CAST "#all")) {
5845 if (flagAll != -1)
5846 *flags |= flagAll;
5847 else {
5848 if (flagExtension != -1)
5849 *flags |= flagExtension;
5850 if (flagRestriction != -1)
5851 *flags |= flagRestriction;
5852 if (flagSubstitution != -1)
5853 *flags |= flagSubstitution;
5854 if (flagList != -1)
5855 *flags |= flagList;
5856 if (flagUnion != -1)
5857 *flags |= flagUnion;
5858 }
5859 } else {
5860 const xmlChar *end, *cur = value;
5861 xmlChar *item;
5862
5863 do {
5864 while (IS_BLANK_CH(*cur))
5865 cur++;
5866 end = cur;
5867 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5868 end++;
5869 if (end == cur)
5870 break;
5871 item = xmlStrndup(cur, end - cur);
5872 if (xmlStrEqual(item, BAD_CAST "extension")) {
5873 if (flagExtension != -1) {
5874 if ((*flags & flagExtension) == 0)
5875 *flags |= flagExtension;
5876 } else
5877 ret = 1;
5878 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5879 if (flagRestriction != -1) {
5880 if ((*flags & flagRestriction) == 0)
5881 *flags |= flagRestriction;
5882 } else
5883 ret = 1;
5884 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5885 if (flagSubstitution != -1) {
5886 if ((*flags & flagSubstitution) == 0)
5887 *flags |= flagSubstitution;
5888 } else
5889 ret = 1;
5890 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5891 if (flagList != -1) {
5892 if ((*flags & flagList) == 0)
5893 *flags |= flagList;
5894 } else
5895 ret = 1;
5896 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5897 if (flagUnion != -1) {
5898 if ((*flags & flagUnion) == 0)
5899 *flags |= flagUnion;
5900 } else
5901 ret = 1;
5902 } else
5903 ret = 1;
5904 if (item != NULL)
5905 xmlFree(item);
5906 cur = end;
5907 } while ((ret == 0) && (*cur != 0));
5908 }
5909
5910 return (ret);
5911}
5912
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005913#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005914static int
5915xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005916 xmlSchemaIDCPtr idc,
5917 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005918 xmlAttrPtr attr,
5919 int isField)
5920{
5921 xmlNodePtr node;
5922
5923 /*
5924 * c-selector-xpath:
5925 * Schema Component Constraint: Selector Value OK
5926 *
5927 * TODO: 1 The {selector} must be a valid XPath expression, as defined
5928 * in [XPath].
5929 */
5930 if (selector == NULL) {
5931 xmlSchemaPErr(ctxt, idc->node,
5932 XML_SCHEMAP_INTERNAL,
5933 "Internal error: xmlSchemaCheckCSelectorXPath, "
5934 "the selector is not specified.\n", NULL, NULL);
5935 return (-1);
5936 }
5937 if (attr == NULL)
5938 node = idc->node;
5939 else
5940 node = (xmlNodePtr) attr;
5941 if (selector->xpath == NULL) {
5942 xmlSchemaPCustomErr(ctxt,
5943 /* TODO: Adjust error code. */
5944 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5945 NULL, NULL, node,
5946 "The XPath expression of the selector is not valid", NULL);
5947 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
5948 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00005949 const xmlChar **nsArray = NULL;
5950 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005951 /*
5952 * Compile the XPath expression.
5953 */
5954 /*
5955 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00005956 * TODO: Call xmlPatterncompile with different options for selector/
5957 * field.
5958 */
5959 nsList = xmlGetNsList(attr->doc, attr->parent);
5960 /*
5961 * Build an array of prefixes and namespaces.
5962 */
5963 if (nsList != NULL) {
5964 int i, count = 0;
5965 xmlNsPtr ns;
5966
5967 for (i = 0; nsList[i] != NULL; i++)
5968 count++;
5969
5970 nsArray = (const xmlChar **) xmlMalloc(
5971 (count * 2 + 1) * sizeof(const xmlChar *));
5972 if (nsArray == NULL) {
5973 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
5974 NULL);
5975 return (-1);
5976 }
5977 for (i = 0; i < count; i++) {
5978 ns = nsList[i];
5979 nsArray[2 * i] = nsList[i]->href;
5980 nsArray[2 * i + 1] = nsList[i]->prefix;
5981 }
5982 nsArray[count * 2] = NULL;
5983 xmlFree(nsList);
5984 }
5985 if (isField)
5986 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
5987 NULL, 0, nsArray);
5988 else
5989 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
5990 NULL, 0, nsArray);
5991 if (nsArray != NULL)
5992 xmlFree((xmlChar **) nsArray);
5993
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005994#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00005995 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005996 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005997 /* TODO: Adjust error code? */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005998 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5999 NULL, NULL, node,
6000 "The XPath expression '%s' could not be "
6001 "compiled", selector->xpath);
6002 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6003 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006004#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006005 }
6006 return (0);
6007}
6008
6009/**
6010 * xmlSchemaAssignAnnotation:
6011 * @item: the schema component
6012 * @annot: the annotation
6013 *
6014 * Adds the annotation to the given schema component.
6015 *
6016 * Returns the given annotaion.
6017 */
6018static xmlSchemaAnnotPtr
6019xmlSchemaAssignAnnotation(xmlSchemaBasicItemPtr item,
6020 xmlSchemaAnnotPtr annot)
6021{
6022 xmlSchemaAnnotPtr cur = item->annot;
6023
6024 if (item->annot == NULL) {
6025 item->annot = annot;
6026 return (annot);
6027 }
6028 cur = item->annot;
6029 if (cur->next != NULL) {
6030 cur = cur->next;
6031 }
6032 cur->next = annot;
6033 return (annot);
6034}
6035
6036/**
6037 * xmlSchemaParseIDCSelectorAndField:
6038 * @ctxt: a schema validation context
6039 * @schema: the schema being built
6040 * @node: a subtree containing XML Schema informations
6041 *
6042 * Parses a XML Schema identity-contraint definition's
6043 * <selector> and <field> elements.
6044 *
6045 * Returns the parsed identity-constraint definition.
6046 */
6047static xmlSchemaIDCSelectPtr
6048xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
6049 xmlSchemaPtr schema,
6050 xmlSchemaIDCPtr idc,
6051 xmlNodePtr node,
6052 int isField)
6053{
6054 xmlSchemaIDCSelectPtr item;
6055 xmlNodePtr child = NULL;
6056 xmlAttrPtr attr;
6057
6058 /*
6059 * Check for illegal attributes.
6060 */
6061 attr = node->properties;
6062 while (attr != NULL) {
6063 if (attr->ns == NULL) {
6064 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6065 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
6066 xmlSchemaPIllegalAttrErr(ctxt,
6067 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6068 NULL, NULL, attr);
6069 }
6070 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6071 xmlSchemaPIllegalAttrErr(ctxt,
6072 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6073 NULL, NULL, attr);
6074 }
6075 attr = attr->next;
6076 }
6077 /*
6078 * Create the item.
6079 */
6080 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
6081 if (item == NULL) {
6082 xmlSchemaPErrMemory(ctxt,
6083 "allocating a 'selector' of an identity-constraint definition",
6084 NULL);
6085 return (NULL);
6086 }
6087 memset(item, 0, sizeof(xmlSchemaIDCSelect));
6088 /*
6089 * Attribute "xpath" (mandatory).
6090 */
6091 attr = xmlSchemaGetPropNode(node, "xpath");
6092 if (attr == NULL) {
6093 xmlSchemaPMissingAttrErr(ctxt,
6094 XML_SCHEMAP_S4S_ATTR_MISSING,
6095 NULL, NULL, node,
6096 "name", NULL);
6097 } else {
6098 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6099 /*
6100 * URGENT TODO: "field"s have an other syntax than "selector"s.
6101 */
6102
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006103 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
6104 isField) == -1) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006105 xmlSchemaPErr(ctxt,
6106 (xmlNodePtr) attr,
6107 XML_SCHEMAP_INTERNAL,
6108 "Internal error: xmlSchemaParseIDCSelectorAndField, "
6109 "validating the XPath expression of a IDC selector.\n",
6110 NULL, NULL);
6111 }
6112
6113 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006114 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006115 /*
6116 * And now for the children...
6117 */
6118 child = node->children;
6119 if (IS_SCHEMA(child, "annotation")) {
6120 /*
6121 * Add the annotation to the parent IDC.
6122 */
6123 xmlSchemaAssignAnnotation((xmlSchemaBasicItemPtr) idc,
6124 xmlSchemaParseAnnotation(ctxt, schema, child));
6125 child = child->next;
6126 }
6127 if (child != NULL) {
6128 xmlSchemaPContentErr(ctxt,
6129 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6130 NULL, NULL, node, child,
6131 NULL, "(annotation?)");
6132 }
6133
6134 return (item);
6135}
6136
6137/**
6138 * xmlSchemaParseIDC:
6139 * @ctxt: a schema validation context
6140 * @schema: the schema being built
6141 * @node: a subtree containing XML Schema informations
6142 *
6143 * Parses a XML Schema identity-contraint definition.
6144 *
6145 * Returns the parsed identity-constraint definition.
6146 */
6147static xmlSchemaIDCPtr
6148xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
6149 xmlSchemaPtr schema,
6150 xmlNodePtr node,
6151 xmlSchemaTypeType idcCategory,
6152 const xmlChar *targetNamespace)
6153{
6154 xmlSchemaIDCPtr item = NULL;
6155 xmlNodePtr child = NULL;
6156 xmlAttrPtr attr;
6157 const xmlChar *name = NULL;
6158 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
6159 int resAdd;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006160
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006161 /*
6162 * Check for illegal attributes.
6163 */
6164 attr = node->properties;
6165 while (attr != NULL) {
6166 if (attr->ns == NULL) {
6167 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6168 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6169 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
6170 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
6171 xmlSchemaPIllegalAttrErr(ctxt,
6172 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6173 NULL, NULL, attr);
6174 }
6175 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6176 xmlSchemaPIllegalAttrErr(ctxt,
6177 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6178 NULL, NULL, attr);
6179 }
6180 attr = attr->next;
6181 }
6182 /*
6183 * Attribute "name" (mandatory).
6184 */
6185 attr = xmlSchemaGetPropNode(node, "name");
6186 if (attr == NULL) {
6187 xmlSchemaPMissingAttrErr(ctxt,
6188 XML_SCHEMAP_S4S_ATTR_MISSING,
6189 NULL, NULL, node,
6190 "name", NULL);
6191 return (NULL);
6192 } else if (xmlSchemaPValAttrNode(ctxt,
6193 NULL, NULL, attr,
6194 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6195 return (NULL);
6196 }
6197 /*
6198 * Create the component.
6199 */
6200 if (schema->idcDef == NULL)
6201 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
6202 if (schema->idcDef == NULL)
6203 return (NULL);
6204
6205 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
6206 if (item == NULL) {
6207 xmlSchemaPErrMemory(ctxt,
6208 "allocating an identity-constraint definition", NULL);
6209 return (NULL);
6210 }
6211 /*
6212 * Add the IDC to the list of IDCs on the schema component.
6213 */
6214 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
6215 if (resAdd != 0) {
6216 xmlSchemaPCustomErrExt(ctxt,
6217 XML_SCHEMAP_REDEFINED_TYPE,
6218 NULL, NULL, node,
6219 "An identity-constraint definition with the name '%s' "
6220 "and targetNamespace '%s' does already exist",
6221 name, targetNamespace, NULL);
6222 xmlFree(item);
6223 return (NULL);
6224 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006225 memset(item, 0, sizeof(xmlSchemaIDC));
6226 item->name = name;
6227 item->type = idcCategory;
6228 item->node = node;
6229 /*
6230 * The target namespace of the parent element declaration.
6231 */
6232 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006233 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
6234 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006235 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
6236 /*
6237 * Attribute "refer" (mandatory).
6238 */
6239 attr = xmlSchemaGetPropNode(node, "refer");
6240 if (attr == NULL) {
6241 xmlSchemaPMissingAttrErr(ctxt,
6242 XML_SCHEMAP_S4S_ATTR_MISSING,
6243 NULL, NULL, node,
6244 "refer", NULL);
6245 } else {
6246 /*
6247 * Create a reference item.
6248 */
6249 item->ref = (xmlSchemaItemQNRefPtr) xmlMalloc(
6250 sizeof(xmlSchemaItemQNRef));
6251 if (item->ref == NULL) {
6252 xmlSchemaPErrMemory(ctxt,
6253 "allocating a QName reference item", NULL);
6254 return (NULL);
6255 }
6256 memset(item->ref, 0, sizeof(xmlSchemaItemQNRef));
6257 xmlSchemaPValAttrNodeQName(ctxt, schema,
6258 NULL, NULL, attr,
6259 &(item->ref->targetNamespace), 0,
6260 &(item->ref->name));
6261 }
6262 }
6263 /*
6264 * And now for the children...
6265 */
6266 child = node->children;
6267 if (IS_SCHEMA(child, "annotation")) {
6268 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6269 child = child->next;
6270 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006271 if (child == NULL) {
6272 xmlSchemaPContentErr(ctxt,
6273 XML_SCHEMAP_S4S_ELEM_MISSING,
6274 NULL, NULL, node, child,
6275 "A child element is missing",
6276 "(annotation?, (selector, field+))");
6277 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006278 /*
6279 * Child element <selector>.
6280 */
6281 if (IS_SCHEMA(child, "selector")) {
6282 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6283 item, child, 0);
6284 child = child->next;
6285 /*
6286 * Child elements <field>.
6287 */
6288 if (IS_SCHEMA(child, "field")) {
6289 do {
6290 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6291 item, child, 1);
6292 if (field != NULL) {
6293 field->index = item->nbFields;
6294 item->nbFields++;
6295 if (lastField != NULL)
6296 lastField->next = field;
6297 else
6298 item->fields = field;
6299 lastField = field;
6300 }
6301 child = child->next;
6302 } while (IS_SCHEMA(child, "field"));
6303 } else {
6304 xmlSchemaPContentErr(ctxt,
6305 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6306 NULL, NULL, node, child,
6307 NULL, "(annotation?, (selector, field+))");
6308 }
6309 }
6310 if (child != NULL) {
6311 xmlSchemaPContentErr(ctxt,
6312 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6313 NULL, NULL, node, child,
6314 NULL, "(annotation?, (selector, field+))");
6315 }
6316
6317 return (item);
6318}
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006319#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006320
Daniel Veillardc0826a72004-08-10 14:17:33 +00006321/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006322 * xmlSchemaParseElement:
6323 * @ctxt: a schema validation context
6324 * @schema: the schema being built
6325 * @node: a subtree containing XML Schema informations
6326 *
6327 * parse a XML schema Element declaration
6328 * *WARNING* this interface is highly subject to change
6329 *
William M. Bracke7091952004-05-11 15:09:58 +00006330 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006331 */
6332static xmlSchemaElementPtr
6333xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006334 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006335{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006336 const xmlChar *name = NULL;
6337 const xmlChar *attrValue;
6338 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006339 xmlSchemaElementPtr ret;
6340 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006341 const xmlChar *oldcontainer;
6342 xmlAttrPtr attr, nameAttr;
6343 int minOccurs, maxOccurs;
6344 int isRef = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006345#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006346 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006347#endif
William M. Bracke7091952004-05-11 15:09:58 +00006348
6349 /* 3.3.3 Constraints on XML Representations of Element Declarations */
6350 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006351
Daniel Veillard4255d502002-04-16 15:50:10 +00006352 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6353 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006354
Daniel Veillardc0826a72004-08-10 14:17:33 +00006355 oldcontainer = ctxt->container;
6356
6357 nameAttr = xmlSchemaGetPropNode(node, "name");
6358 attr = xmlSchemaGetPropNode(node, "ref");
6359 if ((topLevel) || (attr == NULL)) {
6360 if (nameAttr == NULL) {
6361 xmlSchemaPMissingAttrErr(ctxt,
6362 XML_SCHEMAP_S4S_ATTR_MISSING,
6363 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
6364 "name", NULL);
6365 return (NULL);
6366 }
6367 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
6368 } else {
6369 isRef = 1;
6370
6371 }
6372 /*
6373 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
6374 * to no component at all
6375 * TODO: It might be better to validate the element, even if it won't be
6376 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006377 */
6378 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6379 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006380 if ((minOccurs == 0) && (maxOccurs == 0))
6381 return (NULL);
6382 /*
6383 * If we get a "ref" attribute on a local <element> we will assume it's
6384 * a reference - even if there's a "name" attribute; this seems to be more
6385 * robust.
6386 */
6387 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006388 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006389 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6390
6391 /*
6392 * Parse as a particle.
6393 */
6394 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006395 (xmlChar **) &xmlSchemaElemDesElemRef,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006396 NULL, attr, &refNs, &refPrefix, &ref);
6397
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006398 snprintf(buf, 49, "#eRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006399 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006400 if (ret == NULL) {
6401 if (repName != NULL)
6402 xmlFree(repName);
6403 return (NULL);
6404 }
6405 ret->type = XML_SCHEMA_TYPE_ELEMENT;
6406 ret->node = node;
6407 ret->ref = ref;
6408 ret->refNs = refNs;
6409 ret->refPrefix = refPrefix;
6410 ret->flags |= XML_SCHEMAS_ELEM_REF;
6411 /*
6412 * Check for illegal attributes.
6413 */
6414 /*
6415 * 3.3.3 : 2.1
6416 * One of ref or name must be present, but not both
6417 */
6418 if (nameAttr != NULL) {
6419 xmlSchemaPMutualExclAttrErr(ctxt,
6420 XML_SCHEMAP_SRC_ELEMENT_2_1,
6421 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6422 "ref", "name");
6423 }
6424 /* 3.3.3 : 2.2 */
6425 attr = node->properties;
6426 while (attr != NULL) {
6427 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006428 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
6429 xmlStrEqual(attr->name, BAD_CAST "name") ||
6430 xmlStrEqual(attr->name, BAD_CAST "id") ||
6431 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
6432 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
6433 {
6434 attr = attr->next;
6435 continue;
6436 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006437 xmlSchemaPCustomAttrErr(ctxt,
6438 XML_SCHEMAP_SRC_ELEMENT_2_2,
6439 &repName, (xmlSchemaTypePtr) ret, attr,
6440 "Only the attributes 'minOccurs', 'maxOccurs' and "
6441 "'id' are allowed in addition to 'ref'");
6442 break;
6443 }
6444 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6445 xmlSchemaPIllegalAttrErr(ctxt,
6446 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6447 &repName, (xmlSchemaTypePtr) ret, attr);
6448 }
6449 attr = attr->next;
6450 }
6451 } else {
6452 const xmlChar *ns = NULL, *fixed;
6453
6454 /*
6455 * Parse as an element declaration.
6456 */
6457 if (xmlSchemaPValAttrNode(ctxt,
6458 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
6459 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
6460 return (NULL);
6461 /*
6462 * Evaluate the target namespace.
6463 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006464 if (topLevel) {
6465 ns = schema->targetNamespace;
6466 } else {
6467 attr = xmlSchemaGetPropNode(node, "form");
6468 if (attr != NULL) {
6469 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6470 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00006471 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006472 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6473 xmlSchemaPSimpleTypeErr(ctxt,
6474 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6475 &repName, NULL, (xmlNodePtr) attr,
6476 NULL, "(qualified | unqualified)",
6477 attrValue, NULL, NULL, NULL);
6478 }
6479 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6480 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00006481 }
6482 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006483 if (ret == NULL) {
6484 if (repName != NULL)
6485 xmlFree(repName);
6486 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006487 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006488 ret->type = XML_SCHEMA_TYPE_ELEMENT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006489 ret->node = node;
6490 ret->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006491 /*
6492 * Check for illegal attributes.
6493 */
William M. Bracke7091952004-05-11 15:09:58 +00006494 attr = node->properties;
6495 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006496 if (attr->ns == NULL) {
6497 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6498 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6499 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6500 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6501 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6502 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006503 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
6504 {
6505 if (topLevel == 0) {
6506 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006507 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006508 (!xmlStrEqual(attr->name, BAD_CAST "form")))
6509 {
6510 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
6511 /*
6512 * 3.3.6 : 3 If there is a non-·absent· {substitution
6513 * group affiliation}, then {scope} must be global.
6514 * TODO: This one is redundant, since the S4S does
6515 * prohibit this attribute on local declarations already;
6516 * so why an explicit error code? Weird spec.
6517 * TODO: Move this to the proper constraint layer.
6518 * TODO: Or better wait for spec 1.1 to come.
6519 */
6520 xmlSchemaPIllegalAttrErr(ctxt,
6521 XML_SCHEMAP_E_PROPS_CORRECT_3,
6522 &repName, (xmlSchemaTypePtr) ret, attr);
6523 } else {
6524 xmlSchemaPIllegalAttrErr(ctxt,
6525 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6526 &repName, (xmlSchemaTypePtr) ret, attr);
6527 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006528 }
6529 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
6530 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
6531 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
6532
6533 xmlSchemaPIllegalAttrErr(ctxt,
6534 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6535 &repName, (xmlSchemaTypePtr) ret, attr);
6536 }
6537 }
6538 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6539
6540 xmlSchemaPIllegalAttrErr(ctxt,
6541 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6542 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00006543 }
6544 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006545 }
William M. Bracke7091952004-05-11 15:09:58 +00006546 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006547 * Extract/validate attributes.
6548 */
6549 if (topLevel) {
6550 /*
6551 * Process top attributes of global element declarations here.
6552 */
6553 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
6554 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
6555 xmlSchemaPValAttrQName(ctxt, schema, &repName,
6556 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
6557 &(ret->substGroupNs), NULL, &(ret->substGroup));
6558 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6559 node, "abstract", 0))
6560 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
6561 /*
6562 * Attribute "final".
6563 */
6564 attr = xmlSchemaGetPropNode(node, "final");
6565 if (attr == NULL) {
6566 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
6567 } else {
6568 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6569 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6570 -1,
6571 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
6572 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
6573 xmlSchemaPSimpleTypeErr(ctxt,
6574 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6575 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006576 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006577 attrValue, NULL, NULL, NULL);
6578 }
6579 }
6580 }
6581 /*
6582 * Attribute "block".
6583 */
6584 attr = xmlSchemaGetPropNode(node, "block");
6585 if (attr == NULL) {
6586 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
6587 } else {
6588 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6589 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6590 -1,
6591 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
6592 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
6593 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
6594 xmlSchemaPSimpleTypeErr(ctxt,
6595 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6596 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006597 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00006598 "restriction | substitution))", attrValue,
6599 NULL, NULL, NULL);
6600 }
6601 }
6602 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6603 node, "nillable", 0))
6604 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006605
Daniel Veillardc0826a72004-08-10 14:17:33 +00006606 xmlSchemaPValAttrQName(ctxt, schema,
6607 &repName, (xmlSchemaTypePtr) ret, node,
6608 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00006609
Daniel Veillardc0826a72004-08-10 14:17:33 +00006610 ret->value = xmlSchemaGetProp(ctxt, node, "default");
6611 attr = xmlSchemaGetPropNode(node, "fixed");
6612 if (attr != NULL) {
6613 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6614 if (ret->value != NULL) {
6615 /*
6616 * 3.3.3 : 1
6617 * default and fixed must not both be present.
6618 */
6619 xmlSchemaPMutualExclAttrErr(ctxt,
6620 XML_SCHEMAP_SRC_ELEMENT_1,
6621 &repName, (xmlSchemaTypePtr) ret, attr,
6622 "default", "fixed");
6623 } else {
6624 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
6625 ret->value = fixed;
6626 }
6627 }
6628 }
6629 /*
6630 * Extract/validate common attributes.
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006631 */
6632 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6633 node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006634 ret->minOccurs = minOccurs;
6635 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006636 if (topLevel != 1)
6637 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
6638 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006639 /*
6640 * And now for the children...
6641 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006642 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006643 child = node->children;
6644 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006645 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6646 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006647 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006648 if (isRef) {
6649 if (child != NULL) {
6650 xmlSchemaPContentErr(ctxt,
6651 XML_SCHEMAP_SRC_ELEMENT_2_2,
6652 &repName, (xmlSchemaTypePtr) ret, node, child,
6653 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00006654 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006655 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006656 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006657 /*
6658 * 3.3.3 : 3
6659 * "type" and either <simpleType> or <complexType> are mutually
6660 * exclusive
6661 */
William M. Bracke7091952004-05-11 15:09:58 +00006662 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006663 xmlSchemaPContentErr(ctxt,
6664 XML_SCHEMAP_SRC_ELEMENT_3,
6665 &repName, (xmlSchemaTypePtr) ret, node, child,
6666 "The attribute 'type' and the <complexType> child are "
6667 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006668 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006669 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006670 child = child->next;
6671 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006672 /*
6673 * 3.3.3 : 3
6674 * "type" and either <simpleType> or <complexType> are
6675 * mutually exclusive
6676 */
William M. Bracke7091952004-05-11 15:09:58 +00006677 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006678 xmlSchemaPContentErr(ctxt,
6679 XML_SCHEMAP_SRC_ELEMENT_3,
6680 &repName, (xmlSchemaTypePtr) ret, node, child,
6681 "The attribute 'type' and the <simpleType> child are "
6682 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006683 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006684 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006685 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006686 }
William M. Bracke7091952004-05-11 15:09:58 +00006687 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006688 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006689#ifdef IDC_ENABLED
6690 if (IS_SCHEMA(child, "unique")) {
6691 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6692 XML_SCHEMA_TYPE_IDC_UNIQUE, ret->targetNamespace);
6693 } else if (IS_SCHEMA(child, "key")) {
6694 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6695 XML_SCHEMA_TYPE_IDC_KEY, ret->targetNamespace);
6696 } else if (IS_SCHEMA(child, "keyref")) {
6697 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6698 XML_SCHEMA_TYPE_IDC_KEYREF, ret->targetNamespace);
6699 }
6700 if (lastIDC != NULL)
6701 lastIDC->next = curIDC;
6702 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006703 ret->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006704 lastIDC = curIDC;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006705#else
6706 TODO
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006707#endif
6708 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00006709 }
6710 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006711 xmlSchemaPContentErr(ctxt,
6712 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6713 &repName, (xmlSchemaTypePtr) ret, node, child,
6714 NULL, "(annotation?, ((simpleType | complexType)?, "
6715 "(unique | key | keyref)*))");
6716 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006717
Daniel Veillardc0826a72004-08-10 14:17:33 +00006718 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006719 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006720 /*
6721 * Cleanup.
6722 */
6723 if (repName != NULL)
6724 xmlFree(repName);
6725 /*
6726 * NOTE: Element Declaration Representation OK 4. will be checked at a
6727 * different layer.
6728 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006729 return (ret);
6730}
6731
6732/**
6733 * xmlSchemaParseUnion:
6734 * @ctxt: a schema validation context
6735 * @schema: the schema being built
6736 * @node: a subtree containing XML Schema informations
6737 *
6738 * parse a XML schema Union definition
6739 * *WARNING* this interface is highly subject to change
6740 *
William M. Bracke7091952004-05-11 15:09:58 +00006741 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006742 * 1 in case of success.
6743 */
6744static xmlSchemaTypePtr
6745xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006746 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006747{
6748 xmlSchemaTypePtr type, subtype, last = NULL;
6749 xmlNodePtr child = NULL;
6750 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006751 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006752
6753 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6754 return (NULL);
6755
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006756 snprintf((char *) name, 30, "#union%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006757 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006758 if (type == NULL)
6759 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006760 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00006761 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00006762 /*
6763 * Check for illegal attributes.
6764 */
6765 attr = node->properties;
6766 while (attr != NULL) {
6767 if (attr->ns == NULL) {
6768 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6769 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
6770 xmlSchemaPIllegalAttrErr(ctxt,
6771 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6772 NULL, type, attr);
6773 }
6774 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6775 xmlSchemaPIllegalAttrErr(ctxt,
6776 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6777 NULL, type, attr);
6778 }
6779 attr = attr->next;
6780 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006781 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006782 /*
6783 * Attribute "memberTypes". This is a list of QNames.
6784 * TODO: Validate the QNames.
6785 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00006786 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00006787 /*
6788 * And now for the children...
6789 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006790 child = node->children;
6791 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006792 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6793 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006794 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006795 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006796 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00006797 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006798 if (subtype != NULL) {
6799 if (last == NULL) {
6800 type->subtypes = subtype;
6801 last = subtype;
6802 } else {
6803 last->next = subtype;
6804 last = subtype;
6805 }
6806 last->next = NULL;
6807 }
6808 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006809 }
6810 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006811 /* TODO: Think about the error code. */
6812 xmlSchemaPContentErr(ctxt,
6813 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
6814 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006815 }
6816 return (type);
6817}
6818
6819/**
6820 * xmlSchemaParseList:
6821 * @ctxt: a schema validation context
6822 * @schema: the schema being built
6823 * @node: a subtree containing XML Schema informations
6824 *
6825 * parse a XML schema List definition
6826 * *WARNING* this interface is highly subject to change
6827 *
William M. Bracke7091952004-05-11 15:09:58 +00006828 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006829 * 1 in case of success.
6830 */
6831static xmlSchemaTypePtr
6832xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006833 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006834{
6835 xmlSchemaTypePtr type, subtype;
6836 xmlNodePtr child = NULL;
6837 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006838 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006839
6840 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6841 return (NULL);
6842
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006843 snprintf((char *) name, 30, "#list%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006844 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006845 if (type == NULL)
6846 return (NULL);
6847 type->node = node;
6848 type->type = XML_SCHEMA_TYPE_LIST;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006849 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006850 /*
6851 * Check for illegal attributes.
6852 */
6853 attr = node->properties;
6854 while (attr != NULL) {
6855 if (attr->ns == NULL) {
6856 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6857 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
6858 xmlSchemaPIllegalAttrErr(ctxt,
6859 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6860 NULL, type, attr);
6861 }
6862 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6863 xmlSchemaPIllegalAttrErr(ctxt,
6864 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6865 NULL, type, attr);
6866 }
6867 attr = attr->next;
6868 }
6869 /*
6870 * Attribute "itemType".
6871 */
6872 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
6873 node, "itemType", &(type->baseNs), NULL, &(type->base));
6874 /*
6875 * And now for the children...
6876 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006877 child = node->children;
6878 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006879 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6880 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00006881 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006882 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006883 if (IS_SCHEMA(child, "simpleType")) {
6884 if (type->base != NULL) {
6885 xmlSchemaPCustomErr(ctxt,
6886 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
6887 NULL, type, node,
6888 "The attribute 'itemType' and the <simpleType> child "
6889 "are mutually exclusive", NULL);
6890 } else {
6891 subtype = (xmlSchemaTypePtr)
6892 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6893 type->subtypes = subtype;
6894 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006895 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006896 }
6897 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006898 /* TODO: Think about the error code. */
6899 xmlSchemaPContentErr(ctxt,
6900 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
6901 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006902 }
6903 return (type);
6904}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006905
Daniel Veillard4255d502002-04-16 15:50:10 +00006906/**
6907 * xmlSchemaParseSimpleType:
6908 * @ctxt: a schema validation context
6909 * @schema: the schema being built
6910 * @node: a subtree containing XML Schema informations
6911 *
6912 * parse a XML schema Simple Type definition
6913 * *WARNING* this interface is highly subject to change
6914 *
William M. Bracke7091952004-05-11 15:09:58 +00006915 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00006916 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00006917 */
6918static xmlSchemaTypePtr
6919xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006920 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006921{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006922 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00006923 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006924 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006925 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006926 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006927
6928 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6929 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006930
Daniel Veillardc0826a72004-08-10 14:17:33 +00006931 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006932 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006933 if (attr == NULL) {
6934 xmlSchemaPMissingAttrErr(ctxt,
6935 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006936 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006937 "name", NULL);
6938 return (NULL);
6939 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006940 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006941 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00006942 return (NULL);
6943 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006944 }
6945
6946 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006947 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006948
Daniel Veillard01fa6152004-06-29 17:04:39 +00006949 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006950 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00006951 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006952 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006953 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006954 if (type == NULL)
6955 return (NULL);
6956 type->node = node;
6957 type->type = XML_SCHEMA_TYPE_SIMPLE;
6958 /*
6959 * Check for illegal attributes.
6960 */
6961 attr = node->properties;
6962 while (attr != NULL) {
6963 if (attr->ns == NULL) {
6964 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
6965 xmlSchemaPIllegalAttrErr(ctxt,
6966 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006967 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00006968 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006969 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6970 xmlSchemaPIllegalAttrErr(ctxt,
6971 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006972 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006973 }
6974 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006975 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006976 } else {
6977 /*
6978 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006979 *
6980 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006981 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006982 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006983 if (type == NULL)
6984 return (NULL);
6985 type->node = node;
6986 type->type = XML_SCHEMA_TYPE_SIMPLE;
6987 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
6988 /*
6989 * Check for illegal attributes.
6990 */
6991 attr = node->properties;
6992 while (attr != NULL) {
6993 if (attr->ns == NULL) {
6994 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6995 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006996 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006997 xmlSchemaPIllegalAttrErr(ctxt,
6998 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006999 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007000 }
7001 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7002 xmlSchemaPIllegalAttrErr(ctxt,
7003 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007004 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007005 }
7006 attr = attr->next;
7007 }
7008 /*
7009 * Attribute "final".
7010 */
7011 attr = xmlSchemaGetPropNode(node, "final");
7012 if (attr == NULL) {
7013 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
7014 } else {
7015 attrValue = xmlSchemaGetProp(ctxt, node, "final");
7016 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
7017 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
7018 XML_SCHEMAS_TYPE_FINAL_LIST,
7019 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
7020
7021 xmlSchemaPSimpleTypeErr(ctxt,
7022 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007023 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007024 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007025 attrValue, NULL, NULL, NULL);
7026 }
7027 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007028 }
7029 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007030 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007031 /*
7032 * And now for the children...
7033 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007034 oldCtxtType = ctxt->ctxtType;
7035 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007036 ctxt->ctxtType = type;
7037 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007038 child = node->children;
7039 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007040 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7041 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007042 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007043 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007044 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007045 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007046 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007047 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007048 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007049 subtype = (xmlSchemaTypePtr)
7050 xmlSchemaParseList(ctxt, schema, child);
7051 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007052 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007053 subtype = (xmlSchemaTypePtr)
7054 xmlSchemaParseUnion(ctxt, schema, child);
7055 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007056 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007057 type->subtypes = subtype;
7058 if ((child != NULL) || (subtype == NULL)) {
7059 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007060 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007061 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007062 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007063 ctxt->parentItem = oldParentItem;
7064 ctxt->ctxtType = oldCtxtType;
7065 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00007066
Daniel Veillard4255d502002-04-16 15:50:10 +00007067 return (type);
7068}
7069
7070
7071/**
7072 * xmlSchemaParseGroup:
7073 * @ctxt: a schema validation context
7074 * @schema: the schema being built
7075 * @node: a subtree containing XML Schema informations
7076 *
7077 * parse a XML schema Group definition
7078 * *WARNING* this interface is highly subject to change
7079 *
William M. Bracke7091952004-05-11 15:09:58 +00007080 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007081 * 1 in case of success.
7082 */
7083static xmlSchemaTypePtr
7084xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007085 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007086{
7087 xmlSchemaTypePtr type, subtype;
7088 xmlNodePtr child = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007089 const xmlChar *name, *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007090 const xmlChar *ref = NULL, *refNs = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007091 char buf[50];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00007092 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00007093
7094 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7095 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00007096 /*
7097 * TODO: Validate the element even if no item is created
7098 * (i.e. min/maxOccurs == 0).
7099 */
7100 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7101 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
7102 if ((minOccurs == 0) && (maxOccurs == 0)) {
7103 return (NULL);
7104 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007105 if (topLevel)
7106 ns = schema->targetNamespace;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007107 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00007108 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007109 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
7110 if (ref == NULL) {
7111 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007112 XML_SCHEMAP_GROUP_NONAME_NOREF,
7113 "Group definition or particle: One of the attributes \"name\" "
7114 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007115 return (NULL);
7116 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007117 if (refNs == NULL)
7118 refNs = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007119 snprintf(buf, 49, "#grRef%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007120 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00007121 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007122 type = xmlSchemaAddGroup(ctxt, schema, name, ns, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007123 if (type == NULL)
7124 return (NULL);
7125 type->node = node;
7126 type->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007127 if (topLevel)
7128 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007129 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007130 type->ref = ref;
7131 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00007132 type->minOccurs = minOccurs;
7133 type->maxOccurs = maxOccurs;
7134 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007135 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00007136
7137 child = node->children;
7138 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007139 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7140 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007141 }
7142 subtype = NULL;
7143 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007144 subtype = (xmlSchemaTypePtr)
7145 xmlSchemaParseAll(ctxt, schema, child);
7146 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007147 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007148 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7149 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007150 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007151 subtype = (xmlSchemaTypePtr)
7152 xmlSchemaParseSequence(ctxt, schema, child);
7153 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007154 }
7155 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007156 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007157 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007158 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007159 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007160 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007161 }
7162
7163 return (type);
7164}
7165
7166/**
7167 * xmlSchemaParseAll:
7168 * @ctxt: a schema validation context
7169 * @schema: the schema being built
7170 * @node: a subtree containing XML Schema informations
7171 *
7172 * parse a XML schema All definition
7173 * *WARNING* this interface is highly subject to change
7174 *
William M. Bracke7091952004-05-11 15:09:58 +00007175 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007176 * 1 in case of success.
7177 */
7178static xmlSchemaTypePtr
7179xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007180 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007181{
7182 xmlSchemaTypePtr type, subtype, last = NULL;
7183 xmlNodePtr child = NULL;
7184 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007185 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007186
7187 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7188 return (NULL);
7189
7190
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007191 snprintf((char *) name, 30, "#all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007192 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007193 if (type == NULL)
7194 return (NULL);
7195 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00007196 type->type = XML_SCHEMA_TYPE_ALL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007197
7198 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007199
7200 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
7201 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007202
7203 oldcontainer = ctxt->container;
7204 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007205 child = node->children;
7206 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007207 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7208 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007209 }
7210 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007211 subtype = (xmlSchemaTypePtr)
7212 xmlSchemaParseElement(ctxt, schema, child, 0);
7213 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00007214 if (subtype->minOccurs > 1)
7215 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007216 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007217 NULL, NULL);
7218 if (subtype->maxOccurs > 1)
7219 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007220 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007221 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007222 if (last == NULL) {
7223 type->subtypes = subtype;
7224 last = subtype;
7225 } else {
7226 last->next = subtype;
7227 last = subtype;
7228 }
7229 last->next = NULL;
7230 }
7231 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007232 }
7233 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007234 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007235 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007236 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007237 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007238 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007239 return (type);
7240}
7241
7242/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007243 * xmlSchemaCleanupDoc:
7244 * @ctxt: a schema validation context
7245 * @node: the root of the document.
7246 *
7247 * removes unwanted nodes in a schemas document tree
7248 */
7249static void
7250xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
7251{
7252 xmlNodePtr delete, cur;
7253
7254 if ((ctxt == NULL) || (root == NULL)) return;
7255
7256 /*
7257 * Remove all the blank text nodes
7258 */
7259 delete = NULL;
7260 cur = root;
7261 while (cur != NULL) {
7262 if (delete != NULL) {
7263 xmlUnlinkNode(delete);
7264 xmlFreeNode(delete);
7265 delete = NULL;
7266 }
7267 if (cur->type == XML_TEXT_NODE) {
7268 if (IS_BLANK_NODE(cur)) {
7269 if (xmlNodeGetSpacePreserve(cur) != 1) {
7270 delete = cur;
7271 }
7272 }
7273 } else if ((cur->type != XML_ELEMENT_NODE) &&
7274 (cur->type != XML_CDATA_SECTION_NODE)) {
7275 delete = cur;
7276 goto skip_children;
7277 }
7278
7279 /*
7280 * Skip to next node
7281 */
7282 if (cur->children != NULL) {
7283 if ((cur->children->type != XML_ENTITY_DECL) &&
7284 (cur->children->type != XML_ENTITY_REF_NODE) &&
7285 (cur->children->type != XML_ENTITY_NODE)) {
7286 cur = cur->children;
7287 continue;
7288 }
7289 }
7290 skip_children:
7291 if (cur->next != NULL) {
7292 cur = cur->next;
7293 continue;
7294 }
7295
7296 do {
7297 cur = cur->parent;
7298 if (cur == NULL)
7299 break;
7300 if (cur == root) {
7301 cur = NULL;
7302 break;
7303 }
7304 if (cur->next != NULL) {
7305 cur = cur->next;
7306 break;
7307 }
7308 } while (cur != NULL);
7309 }
7310 if (delete != NULL) {
7311 xmlUnlinkNode(delete);
7312 xmlFreeNode(delete);
7313 delete = NULL;
7314 }
7315}
7316
William M. Brack2f2a6632004-08-20 23:09:47 +00007317
7318/**
7319 * xmlSchemaImportSchema
7320 *
7321 * @ctxt: a schema validation context
7322 * @schemaLocation: an URI defining where to find the imported schema
7323 *
7324 * import a XML schema
7325 * *WARNING* this interface is highly subject to change
7326 *
7327 * Returns -1 in case of error and 1 in case of success.
7328 */
7329#if 0
7330static xmlSchemaImportPtr
7331xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
7332 const xmlChar *schemaLocation)
7333{
7334 xmlSchemaImportPtr import;
7335 xmlSchemaParserCtxtPtr newctxt;
7336
7337 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7338 if (newctxt == NULL) {
7339 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
7340 NULL);
7341 return (NULL);
7342 }
7343 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
7344 /* Keep the same dictionnary for parsing, really */
7345 xmlDictReference(ctxt->dict);
7346 newctxt->dict = ctxt->dict;
7347 newctxt->includes = 0;
7348 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
7349
7350 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
7351 ctxt->userData);
7352
7353 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7354 if (import == NULL) {
7355 xmlSchemaPErrMemory(NULL, "allocating imported schema",
7356 NULL);
7357 xmlSchemaFreeParserCtxt(newctxt);
7358 return (NULL);
7359 }
7360
7361 memset(import, 0, sizeof(xmlSchemaImport));
7362 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7363 import->schema = xmlSchemaParse(newctxt);
7364
7365 if (import->schema == NULL) {
7366 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00007367 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00007368 "Failed to import schema from location \"%s\".\n",
7369 schemaLocation, NULL);
7370
7371 xmlSchemaFreeParserCtxt(newctxt);
7372 /* The schemaLocation is held by the dictionary.
7373 if (import->schemaLocation != NULL)
7374 xmlFree((xmlChar *)import->schemaLocation);
7375 */
7376 xmlFree(import);
7377 return NULL;
7378 }
7379
7380 xmlSchemaFreeParserCtxt(newctxt);
7381 return import;
7382}
7383#endif
7384
7385static void
7386xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
7387{
7388 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7389 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
7390
7391 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
7392 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
7393
7394 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7395 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
7396 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7397 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
7398 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
7399 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
7400 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
7401 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
7402
7403 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7404 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
7405 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7406 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
7407 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7408 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
7409}
7410
7411static void
7412xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
7413 xmlSchemaPtr schema,
7414 xmlNodePtr node)
7415{
7416 xmlAttrPtr attr;
7417 const xmlChar *val;
7418
7419 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
7420 if (attr != NULL) {
7421 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7422 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7423 XML_SCHEMAS_QUALIF_ELEM) != 0) {
7424 xmlSchemaPSimpleTypeErr(ctxt,
7425 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
7426 NULL, NULL, (xmlNodePtr) attr, NULL,
7427 "(qualified | unqualified)", val, NULL, NULL, NULL);
7428 }
7429 }
7430
7431 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
7432 if (attr != NULL) {
7433 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7434 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7435 XML_SCHEMAS_QUALIF_ATTR) != 0) {
7436 xmlSchemaPSimpleTypeErr(ctxt,
7437 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
7438 NULL, NULL, (xmlNodePtr) attr, NULL,
7439 "(qualified | unqualified)", val, NULL, NULL, NULL);
7440 }
7441 }
7442
7443 attr = xmlSchemaGetPropNode(node, "finalDefault");
7444 if (attr != NULL) {
7445 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7446 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7447 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
7448 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
7449 -1,
7450 XML_SCHEMAS_FINAL_DEFAULT_LIST,
7451 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
7452 xmlSchemaPSimpleTypeErr(ctxt,
7453 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7454 NULL, NULL, (xmlNodePtr) attr, NULL,
7455 "(#all | List of (extension | restriction | list | union))",
7456 val, NULL, NULL, NULL);
7457 }
7458 }
7459
7460 attr = xmlSchemaGetPropNode(node, "blockDefault");
7461 if (attr != NULL) {
7462 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7463 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7464 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
7465 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
7466 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
7467 xmlSchemaPSimpleTypeErr(ctxt,
7468 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7469 NULL, NULL, (xmlNodePtr) attr, NULL,
7470 "(#all | List of (extension | restriction | substitution))",
7471 val, NULL, NULL, NULL);
7472 }
7473 }
7474}
7475
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007476/**
7477 * xmlSchemaParseSchemaTopLevel:
7478 * @ctxt: a schema validation context
7479 * @schema: the schemas
7480 * @nodes: the list of top level nodes
7481 *
7482 * Returns the internal XML Schema structure built from the resource or
7483 * NULL in case of error
7484 */
7485static void
7486xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
7487 xmlSchemaPtr schema, xmlNodePtr nodes)
7488{
7489 xmlNodePtr child;
7490 xmlSchemaAnnotPtr annot;
7491
7492 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
7493 return;
7494
7495 child = nodes;
7496 while ((IS_SCHEMA(child, "include")) ||
7497 (IS_SCHEMA(child, "import")) ||
7498 (IS_SCHEMA(child, "redefine")) ||
7499 (IS_SCHEMA(child, "annotation"))) {
7500 if (IS_SCHEMA(child, "annotation")) {
7501 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7502 if (schema->annot == NULL)
7503 schema->annot = annot;
7504 else
7505 xmlSchemaFreeAnnot(annot);
7506 } else if (IS_SCHEMA(child, "import")) {
7507 xmlSchemaParseImport(ctxt, schema, child);
7508 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007509 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007510 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007511 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007512 } else if (IS_SCHEMA(child, "redefine")) {
7513 TODO
7514 }
7515 child = child->next;
7516 }
7517 while (child != NULL) {
7518 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007519 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007520 child = child->next;
7521 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007522 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007523 child = child->next;
7524 } else if (IS_SCHEMA(child, "element")) {
7525 xmlSchemaParseElement(ctxt, schema, child, 1);
7526 child = child->next;
7527 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00007528 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007529 child = child->next;
7530 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007531 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007532 child = child->next;
7533 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007534 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007535 child = child->next;
7536 } else if (IS_SCHEMA(child, "notation")) {
7537 xmlSchemaParseNotation(ctxt, schema, child);
7538 child = child->next;
7539 } else {
7540 xmlSchemaPErr2(ctxt, NULL, child,
7541 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007542 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007543 child->name, NULL);
7544 child = child->next;
7545 }
7546 while (IS_SCHEMA(child, "annotation")) {
7547 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7548 if (schema->annot == NULL)
7549 schema->annot = annot;
7550 else
7551 xmlSchemaFreeAnnot(annot);
7552 child = child->next;
7553 }
7554 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007555 ctxt->parentItem = NULL;
7556 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007557}
7558
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007559static xmlSchemaImportPtr
7560xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
7561 xmlHashTablePtr *imports,
7562 const xmlChar *nsName)
7563{
7564 xmlSchemaImportPtr ret;
7565
7566 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00007567 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007568 if (*imports == NULL) {
7569 xmlSchemaPCustomErr(ctxt,
7570 XML_SCHEMAP_FAILED_BUILD_IMPORT,
7571 NULL, NULL, (xmlNodePtr) ctxt->doc,
7572 "Internal error: failed to build the import table",
7573 NULL);
7574 return (NULL);
7575 }
7576 }
7577 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7578 if (ret == NULL) {
7579 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
7580 return (NULL);
7581 }
7582 memset(ret, 0, sizeof(xmlSchemaImport));
7583 if (nsName == NULL)
7584 nsName = XML_SCHEMAS_NO_NAMESPACE;
7585 xmlHashAddEntry(*imports, nsName, ret);
7586
7587 return (ret);
7588}
7589
7590static int
7591xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007592 xmlSchemaPtr schema,
7593 xmlNodePtr node,
7594 const xmlChar *nsName,
7595 const xmlChar *location,
7596 xmlDocPtr *doc,
7597 const xmlChar **targetNamespace,
7598 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007599{
7600 xmlParserCtxtPtr parserCtxt;
7601 xmlSchemaImportPtr import;
7602 const xmlChar *ns;
7603 xmlNodePtr root;
7604
7605 /*
7606 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
7607 * <xsi:noNamespaceSchemaLocation>.
7608 */
7609 *doc = NULL;
7610 /*
7611 * Given that the schemaLocation [attribute] is only a hint, it is open
7612 * to applications to ignore all but the first <import> for a given
7613 * namespace, regardless of the ·actual value· of schemaLocation, but
7614 * such a strategy risks missing useful information when new
7615 * schemaLocations are offered.
7616 *
7617 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
7618 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
7619 * valid or not.
7620 * We will follow XSV here.
7621 */
7622 if (location == NULL) {
7623 /*
7624 * Schema Document Location Strategy:
7625 *
7626 * 3 Based on the namespace name, identify an existing schema document,
7627 * either as a resource which is an XML document or a <schema> element
7628 * information item, in some local schema repository;
7629 *
7630 * 5 Attempt to resolve the namespace name to locate such a resource.
7631 *
7632 * NOTE: Those stategies are not supported, so we will skip.
7633 */
7634 return (0);
7635 }
7636 if (nsName == NULL)
7637 ns = XML_SCHEMAS_NO_NAMESPACE;
7638 else
7639 ns = nsName;
7640
7641 import = xmlHashLookup(schema->schemasImports, ns);
7642 if (import != NULL) {
7643 /*
7644 * There was a valid resource for the specified namespace already
7645 * defined, so skip.
7646 * TODO: This might be changed someday to allow import of
7647 * components from multiple documents for a single target namespace.
7648 */
7649 return (0);
7650 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007651
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007652 /*
7653 * Schema Document Location Strategy:
7654 *
7655 * 2 Based on the location URI, identify an existing schema document,
7656 * either as a resource which is an XML document or a <schema> element
7657 * information item, in some local schema repository;
7658 *
7659 * 4 Attempt to resolve the location URI, to locate a resource on the
7660 * web which is or contains or references a <schema> element;
7661 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
7662 *
7663 */
7664 if ((absolute == 0) && (node != NULL)) {
7665 xmlChar *base, *URI;
7666
7667 base = xmlNodeGetBase(node->doc, node);
7668 if (base == NULL) {
7669 URI = xmlBuildURI(location, node->doc->URL);
7670 } else {
7671 URI = xmlBuildURI(location, base);
7672 xmlFree(base);
7673 }
7674 if (URI != NULL) {
7675 location = xmlDictLookup(ctxt->dict, URI, -1);
7676 xmlFree(URI);
7677 }
7678 }
7679 parserCtxt = xmlNewParserCtxt();
7680 if (parserCtxt == NULL) {
7681 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
7682 "allocating a parser context", NULL);
7683 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007684 }
7685
7686 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7687 xmlDictFree(parserCtxt->dict);
7688 parserCtxt->dict = ctxt->dict;
7689 xmlDictReference(parserCtxt->dict);
7690 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007691
7692 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
7693 NULL, SCHEMAS_PARSE_OPTIONS);
7694
7695 /*
7696 * 2.1 The referent is (a fragment of) a resource which is an
7697 * XML document (see clause 1.1), which in turn corresponds to
7698 * a <schema> element information item in a well-formed information
7699 * set, which in turn corresponds to a valid schema.
7700 * TODO: What to do with the "fragment" stuff?
7701 *
7702 * 2.2 The referent is a <schema> element information item in
7703 * a well-formed information set, which in turn corresponds
7704 * to a valid schema.
7705 * NOTE: 2.2 won't apply, since only XML documents will be processed
7706 * here.
7707 */
7708 if (*doc == NULL) {
7709 xmlErrorPtr lerr;
7710 /*
7711 * It is *not* an error for the application schema reference
7712 * strategy to fail.
7713 *
7714 * If the doc is NULL and the parser error is an IO error we
7715 * will assume that the resource could not be located or accessed.
7716 *
7717 * TODO: Try to find specific error codes to react only on
7718 * localisation failures.
7719 *
7720 * TODO, FIXME: Check the spec: is a namespace added to the imported
7721 * namespaces, even if the schemaLocation did not provide
7722 * a resource? I guess so, since omitting the "schemaLocation"
7723 * attribute, imports a namespace as well.
7724 */
7725 lerr = xmlGetLastError();
7726 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
7727 xmlFreeParserCtxt(parserCtxt);
7728 return(0);
7729 }
7730
7731 xmlSchemaPCustomErr(ctxt,
7732 XML_SCHEMAP_SRC_IMPORT_2_1,
7733 NULL, NULL, node,
7734 "Failed to parse the resource '%s' for import",
7735 location);
7736 xmlFreeParserCtxt(parserCtxt);
7737 return(XML_SCHEMAP_SRC_IMPORT_2_1);
7738 }
7739 xmlFreeParserCtxt(parserCtxt);
7740
7741 root = xmlDocGetRootElement(*doc);
7742 if (root == NULL) {
7743 xmlSchemaPCustomErr(ctxt,
7744 XML_SCHEMAP_SRC_IMPORT_2_1,
7745 NULL, NULL, node,
7746 "The XML document '%s' to be imported has no document "
7747 "element", location);
7748 xmlFreeDoc(*doc);
7749 *doc = NULL;
7750 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7751 }
7752
7753 xmlSchemaCleanupDoc(ctxt, root);
7754
7755 if (!IS_SCHEMA(root, "schema")) {
7756 xmlSchemaPCustomErr(ctxt,
7757 XML_SCHEMAP_SRC_IMPORT_2_1,
7758 NULL, NULL, node,
7759 "The XML document '%s' to be imported is not a XML schema document",
7760 location);
7761 xmlFreeDoc(*doc);
7762 *doc = NULL;
7763 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7764 }
7765 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
7766 /*
7767 * Schema Representation Constraint: Import Constraints and Semantics
7768 */
7769 if (nsName == NULL) {
7770 if (*targetNamespace != NULL) {
7771 xmlSchemaPCustomErr(ctxt,
7772 XML_SCHEMAP_SRC_IMPORT_3_2,
7773 NULL, NULL, node,
7774 "The XML schema to be imported is not expected "
7775 "to have a target namespace; this differs from "
7776 "its target namespace of '%s'", *targetNamespace);
7777 xmlFreeDoc(*doc);
7778 *doc = NULL;
7779 return (XML_SCHEMAP_SRC_IMPORT_3_2);
7780 }
7781 } else {
7782 if (*targetNamespace == NULL) {
7783 xmlSchemaPCustomErr(ctxt,
7784 XML_SCHEMAP_SRC_IMPORT_3_1,
7785 NULL, NULL, node,
7786 "The XML schema to be imported is expected to have a target "
7787 "namespace of '%s'", nsName);
7788 xmlFreeDoc(*doc);
7789 *doc = NULL;
7790 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7791 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
7792 xmlSchemaPCustomErrExt(ctxt,
7793 XML_SCHEMAP_SRC_IMPORT_3_1,
7794 NULL, NULL, node,
7795 "The XML schema to be imported is expected to have a "
7796 "target namespace of '%s'; this differs from "
7797 "its target namespace of '%s'",
7798 nsName, *targetNamespace, NULL);
7799 xmlFreeDoc(*doc);
7800 *doc = NULL;
7801 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7802 }
7803 }
7804
7805 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
7806 if (import == NULL) {
7807 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
7808 NULL, NULL, NULL,
7809 "Internal error: xmlSchemaAcquireSchemaDoc, "
7810 "failed to build import table", NULL);
7811 xmlFreeDoc(*doc);
7812 *doc = NULL;
7813 return (-1);
7814 }
7815 import->schemaLocation = location;
7816 import->doc = *doc;
7817 return (0);
7818}
William M. Brack2f2a6632004-08-20 23:09:47 +00007819
7820/**
7821 * xmlSchemaParseImport:
7822 * @ctxt: a schema validation context
7823 * @schema: the schema being built
7824 * @node: a subtree containing XML Schema informations
7825 *
7826 * parse a XML schema Import definition
7827 * *WARNING* this interface is highly subject to change
7828 *
7829 * Returns 0 in case of success, a positive error code if
7830 * not valid and -1 in case of an internal error.
7831 */
7832static int
7833xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7834 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007835{
7836 xmlNodePtr child;
7837 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007838 const xmlChar *schemaLocation = NULL;
7839 const xmlChar *targetNamespace, *oldTNS, *url;
7840 xmlAttrPtr attr;
7841 xmlDocPtr doc;
7842 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007843 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007844
7845
7846 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7847 return (-1);
7848
7849 /*
7850 * Check for illegal attributes.
7851 */
7852 attr = node->properties;
7853 while (attr != NULL) {
7854 if (attr->ns == NULL) {
7855 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7856 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7857 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7858 xmlSchemaPIllegalAttrErr(ctxt,
7859 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7860 NULL, NULL, attr);
7861 }
7862 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7863 xmlSchemaPIllegalAttrErr(ctxt,
7864 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7865 NULL, NULL, attr);
7866 }
7867 attr = attr->next;
7868 }
7869 /*
7870 * Extract and validate attributes.
7871 */
7872 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7873 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7874 &namespace) != 0) {
7875 xmlSchemaPSimpleTypeErr(ctxt,
7876 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
7877 NULL, NULL, node,
7878 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7879 NULL, namespace, NULL, NULL, NULL);
7880 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
7881 }
7882
7883 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7884 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7885 &schemaLocation) != 0) {
7886 xmlSchemaPSimpleTypeErr(ctxt,
7887 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
7888 NULL, NULL, node,
7889 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7890 NULL, namespace, NULL, NULL, NULL);
7891 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
7892 }
7893 /*
7894 * And now for the children...
7895 */
7896 child = node->children;
7897 if (IS_SCHEMA(child, "annotation")) {
7898 /*
7899 * the annotation here is simply discarded ...
7900 */
7901 child = child->next;
7902 }
7903 if (child != NULL) {
7904 xmlSchemaPContentErr(ctxt,
7905 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
7906 NULL, NULL, node, child, NULL,
7907 "(annotation?)");
7908 }
7909 /*
7910 * Apply additional constraints.
7911 */
7912 if (namespace != NULL) {
7913 /*
7914 * 1.1 If the namespace [attribute] is present, then its ·actual value·
7915 * must not match the ·actual value· of the enclosing <schema>'s
7916 * targetNamespace [attribute].
7917 */
7918 if (xmlStrEqual(schema->targetNamespace, namespace)) {
7919 xmlSchemaPCustomErr(ctxt,
7920 XML_SCHEMAP_SRC_IMPORT_1_1,
7921 NULL, NULL, node,
7922 "The value of the attribute 'namespace' must not match "
7923 "the target namespace '%s' of the importing schema",
7924 schema->targetNamespace);
7925 return (XML_SCHEMAP_SRC_IMPORT_1_1);
7926 }
7927 } else {
7928 /*
7929 * 1.2 If the namespace [attribute] is not present, then the enclosing
7930 * <schema> must have a targetNamespace [attribute].
7931 */
7932 if (schema->targetNamespace == NULL) {
7933 xmlSchemaPCustomErr(ctxt,
7934 XML_SCHEMAP_SRC_IMPORT_1_2,
7935 NULL, NULL, node,
7936 "The attribute 'namespace' must be existent if "
7937 "the importing schema has no target namespace",
7938 NULL);
7939 return (XML_SCHEMAP_SRC_IMPORT_1_2);
7940 }
7941 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007942 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007943 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00007944 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007945 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
7946 schemaLocation, &doc, &targetNamespace, 0);
7947 if (ret != 0) {
7948 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00007949 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007950 return (ret);
7951 } else if (doc != NULL) {
7952 /*
7953 * Save and reset the context & schema.
7954 */
7955 url = ctxt->URL;
7956 /* TODO: Is using the doc->URL here correct? */
7957 ctxt->URL = doc->URL;
7958 flags = schema->flags;
7959 oldTNS = schema->targetNamespace;
7960 /*
7961 * Parse the schema.
7962 */
7963 root = xmlDocGetRootElement(doc);
7964 xmlSchemaClearSchemaDefaults(schema);
7965 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
7966 schema->targetNamespace = targetNamespace;
7967 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
7968 /*
7969 * Restore the context & schema.
7970 */
7971 schema->flags = flags;
7972 schema->targetNamespace = oldTNS;
7973 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00007974 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007975
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007976 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007977}
7978
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007979/**
7980 * xmlSchemaParseInclude:
7981 * @ctxt: a schema validation context
7982 * @schema: the schema being built
7983 * @node: a subtree containing XML Schema informations
7984 *
7985 * parse a XML schema Include definition
7986 *
William M. Bracke7091952004-05-11 15:09:58 +00007987 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007988 * 1 in case of success.
7989 */
7990static int
7991xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7992 xmlNodePtr node)
7993{
7994 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007995 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007996 xmlDocPtr doc;
7997 xmlNodePtr root;
7998 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007999 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00008000 xmlAttrPtr attr;
8001 int saveFlags;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008002 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008003
8004
8005 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8006 return (-1);
8007
8008 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00008009 * Check for illegal attributes.
8010 */
8011 attr = node->properties;
8012 while (attr != NULL) {
8013 if (attr->ns == NULL) {
8014 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8015 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
8016 xmlSchemaPIllegalAttrErr(ctxt,
8017 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8018 NULL, NULL, attr);
8019 }
8020 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8021 xmlSchemaPIllegalAttrErr(ctxt,
8022 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8023 NULL, NULL, attr);
8024 }
8025 attr = attr->next;
8026 }
8027 /*
8028 * Extract and validate attributes.
8029 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008030 xmlSchemaPValAttrID(ctxt, NULL, NULL,
8031 node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008032 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008033 * Preliminary step, extract the URI-Reference for the include and
8034 * make an URI from the base.
8035 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008036 attr = xmlSchemaGetPropNode(node, "schemaLocation");
8037 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008038 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008039 xmlChar *uri = NULL;
8040
8041 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8042 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
8043 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008044 base = xmlNodeGetBase(node->doc, node);
8045 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008046 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008047 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00008048 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008049 xmlFree(base);
8050 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008051 if (uri != NULL) {
8052 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
8053 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008054 }
8055 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00008056 xmlSchemaPMissingAttrErr(ctxt,
8057 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
8058 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008059 return (-1);
8060 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008061 /*
8062 * And now for the children...
8063 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008064 child = node->children;
8065 while (IS_SCHEMA(child, "annotation")) {
8066 /*
8067 * the annotations here are simply discarded ...
8068 */
8069 child = child->next;
8070 }
8071 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008072 xmlSchemaPContentErr(ctxt,
8073 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
8074 NULL, NULL, node, child, NULL,
8075 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008076 }
8077
8078 /*
8079 * First step is to parse the input document into an DOM/Infoset
8080 */
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008081 /*
8082 * TODO: Use xmlCtxtReadFile to share the dictionary.
8083 */
8084 parserCtxt = xmlNewParserCtxt();
8085 if (parserCtxt == NULL) {
8086 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
8087 "allocating a parser context", NULL);
8088 return(-1);
8089 }
8090
8091 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
8092 xmlDictFree(parserCtxt->dict);
8093 parserCtxt->dict = ctxt->dict;
8094 xmlDictReference(parserCtxt->dict);
8095 }
8096
8097 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
8098 NULL, SCHEMAS_PARSE_OPTIONS);
8099 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008100 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008101 /*
8102 * TODO: It is not an error for the ·actual value· of the
8103 * schemaLocation [attribute] to fail to resolve it all, in which
8104 * case no corresponding inclusion is performed.
8105 * So do we need a warning report here?
8106 */
8107 xmlSchemaPCustomErr(ctxt,
8108 XML_SCHEMAP_FAILED_LOAD,
8109 NULL, NULL, node,
8110 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008111 return(-1);
8112 }
8113
8114 /*
8115 * Then extract the root of the schema
8116 */
8117 root = xmlDocGetRootElement(doc);
8118 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008119 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008120 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00008121 NULL, NULL, node,
8122 "The included document '%s' has no document "
8123 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008124 xmlFreeDoc(doc);
8125 return (-1);
8126 }
8127
8128 /*
8129 * Remove all the blank text nodes
8130 */
8131 xmlSchemaCleanupDoc(ctxt, root);
8132
8133 /*
8134 * Check the schemas top level element
8135 */
8136 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008137 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008138 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00008139 NULL, NULL, node,
8140 "The document '%s' to be included is not a schema document",
8141 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008142 xmlFreeDoc(doc);
8143 return (-1);
8144 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008145
William M. Brack2f2a6632004-08-20 23:09:47 +00008146 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008147 /*
8148 * 2.1 SII has a targetNamespace [attribute], and its ·actual
8149 * value· is identical to the ·actual value· of the targetNamespace
8150 * [attribute] of SIIÂ’ (which must have such an [attribute]).
8151 */
8152 if (targetNamespace != NULL) {
8153 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008154 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008155 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008156 NULL, NULL, node,
8157 "The target namespace of the included schema "
8158 "'%s' has to be absent, since the including schema "
8159 "has no target namespace",
8160 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008161 xmlFreeDoc(doc);
8162 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008163 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
8164 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008165 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008166 NULL, NULL, node,
8167 "The target namespace '%s' of the included schema '%s' "
8168 "differs from '%s' of the including schema",
8169 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008170 xmlFreeDoc(doc);
8171 return (-1);
8172 }
8173 } else if (schema->targetNamespace != NULL) {
8174 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
8175 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
8176 } else
8177 wasConvertingNs = 1;
8178 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008179 /*
8180 * register the include
8181 */
8182 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
8183 if (include == NULL) {
8184 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
8185 xmlFreeDoc(doc);
8186 return (-1);
8187 }
8188
8189 memset(include, 0, sizeof(xmlSchemaInclude));
8190 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8191 include->doc = doc;
8192 include->next = schema->includes;
8193 schema->includes = include;
8194
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008195 /*
8196 * parse the declarations in the included file like if they
8197 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008198 */
8199 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00008200 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008201 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008202 /*
8203 * The default values ("blockDefault", "elementFormDefault", etc.)
8204 * are set to the values of the included schema and restored afterwards.
8205 */
8206 saveFlags = schema->flags;
8207 xmlSchemaClearSchemaDefaults(schema);
8208 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008209 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00008210 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008211 /*
8212 * Remove the converting flag.
8213 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008214 if ((wasConvertingNs == 0) &&
8215 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00008216 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008217 return (1);
8218}
8219
8220/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008221 * xmlSchemaParseChoice:
8222 * @ctxt: a schema validation context
8223 * @schema: the schema being built
8224 * @node: a subtree containing XML Schema informations
8225 *
8226 * parse a XML schema Choice definition
8227 * *WARNING* this interface is highly subject to change
8228 *
William M. Bracke7091952004-05-11 15:09:58 +00008229 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008230 * 1 in case of success.
8231 */
8232static xmlSchemaTypePtr
8233xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008234 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008235{
8236 xmlSchemaTypePtr type, subtype, last = NULL;
8237 xmlNodePtr child = NULL;
8238 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008239 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008240 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008241
8242 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8243 return (NULL);
8244
8245
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008246 snprintf((char *) name, 30, "#ch%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008247 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008248 if (type == NULL)
8249 return (NULL);
8250 type->node = node;
8251 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008252 /*
8253 * Check for illegal attributes.
8254 */
8255 attr = node->properties;
8256 while (attr != NULL) {
8257 if (attr->ns == NULL) {
8258 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8259 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8260 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8261 xmlSchemaPIllegalAttrErr(ctxt,
8262 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8263 NULL, type, attr);
8264 }
8265 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8266 xmlSchemaPIllegalAttrErr(ctxt,
8267 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8268 NULL, type, attr);
8269 }
8270 attr = attr->next;
8271 }
8272 /*
8273 * Extract and validate attributes.
8274 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008275 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008276 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8277 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8278 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008279 /*
8280 * And now for the children...
8281 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008282 oldcontainer = ctxt->container;
8283 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008284 child = node->children;
8285 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008286 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8287 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008288 }
8289 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008290 (IS_SCHEMA(child, "group")) ||
8291 (IS_SCHEMA(child, "any")) ||
8292 (IS_SCHEMA(child, "choice")) ||
8293 (IS_SCHEMA(child, "sequence"))) {
8294 subtype = NULL;
8295 if (IS_SCHEMA(child, "element")) {
8296 subtype = (xmlSchemaTypePtr)
8297 xmlSchemaParseElement(ctxt, schema, child, 0);
8298 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008299 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008300 } else if (IS_SCHEMA(child, "any")) {
8301 subtype = xmlSchemaParseAny(ctxt, schema, child);
8302 } else if (IS_SCHEMA(child, "sequence")) {
8303 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8304 } else if (IS_SCHEMA(child, "choice")) {
8305 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8306 }
8307 if (subtype != NULL) {
8308 if (last == NULL) {
8309 type->subtypes = subtype;
8310 last = subtype;
8311 } else {
8312 last->next = subtype;
8313 last = subtype;
8314 }
8315 last->next = NULL;
8316 }
8317 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008318 }
8319 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008320 /* TODO: error code. */
8321 xmlSchemaPContentErr(ctxt,
8322 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
8323 NULL, type, node, child, NULL,
8324 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008325 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008326 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008327 return (type);
8328}
8329
8330/**
8331 * xmlSchemaParseSequence:
8332 * @ctxt: a schema validation context
8333 * @schema: the schema being built
8334 * @node: a subtree containing XML Schema informations
8335 *
8336 * parse a XML schema Sequence definition
8337 * *WARNING* this interface is highly subject to change
8338 *
William M. Bracke7091952004-05-11 15:09:58 +00008339 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008340 * 1 in case of success.
8341 */
8342static xmlSchemaTypePtr
8343xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008344 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008345{
8346 xmlSchemaTypePtr type, subtype, last = NULL;
8347 xmlNodePtr child = NULL;
8348 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008349 xmlAttrPtr attr;
8350 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008351
8352 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8353 return (NULL);
8354
William M. Brack2f2a6632004-08-20 23:09:47 +00008355 oldcontainer = ctxt->container;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008356 snprintf((char *) name, 30, "#seq%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008357 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008358 if (type == NULL)
8359 return (NULL);
8360 type->node = node;
8361 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008362 /*
8363 * Check for illegal attributes.
8364 */
8365 attr = node->properties;
8366 while (attr != NULL) {
8367 if (attr->ns == NULL) {
8368 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8369 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8370 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8371 xmlSchemaPIllegalAttrErr(ctxt,
8372 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8373 NULL, type, attr);
8374 }
8375 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8376 xmlSchemaPIllegalAttrErr(ctxt,
8377 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8378 NULL, type, attr);
8379 }
8380 attr = attr->next;
8381 }
8382 /*
8383 * Extract and validate attributes.
8384 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008385 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008386 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8387 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8388 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008389 /*
8390 * And now for the children...
8391 */
8392 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008393 child = node->children;
8394 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008395 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8396 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008397 }
8398 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008399 (IS_SCHEMA(child, "group")) ||
8400 (IS_SCHEMA(child, "any")) ||
8401 (IS_SCHEMA(child, "choice")) ||
8402 (IS_SCHEMA(child, "sequence"))) {
8403 subtype = NULL;
8404 if (IS_SCHEMA(child, "element")) {
8405 subtype = (xmlSchemaTypePtr)
8406 xmlSchemaParseElement(ctxt, schema, child, 0);
8407 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008408 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008409 } else if (IS_SCHEMA(child, "any")) {
8410 subtype = xmlSchemaParseAny(ctxt, schema, child);
8411 } else if (IS_SCHEMA(child, "choice")) {
8412 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8413 } else if (IS_SCHEMA(child, "sequence")) {
8414 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8415 }
8416 if (subtype != NULL) {
8417 if (last == NULL) {
8418 type->subtypes = subtype;
8419 last = subtype;
8420 } else {
8421 last->next = subtype;
8422 last = subtype;
8423 }
8424 last->next = NULL;
8425 }
8426 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008427 }
8428 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008429 xmlSchemaPContentErr(ctxt,
8430 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
8431 NULL, type, node, child, NULL,
8432 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008433 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008434 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008435
8436 return (type);
8437}
8438
8439/**
8440 * xmlSchemaParseRestriction:
8441 * @ctxt: a schema validation context
8442 * @schema: the schema being built
8443 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00008444 *
8445 * parse a XML schema Restriction definition
8446 * *WARNING* this interface is highly subject to change
8447 *
8448 * Returns the type definition or NULL in case of error
8449 */
8450static xmlSchemaTypePtr
8451xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008452 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008453{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008454 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00008455 xmlNodePtr child = NULL;
8456 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008457 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00008458 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008459
8460 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8461 return (NULL);
8462
8463 oldcontainer = ctxt->container;
8464
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008465 snprintf((char *) name, 30, "#restr%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008466 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008467 if (type == NULL)
8468 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008469 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008470 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00008471 /*
8472 * Check for illegal attributes.
8473 */
8474 attr = node->properties;
8475 while (attr != NULL) {
8476 if (attr->ns == NULL) {
8477 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8478 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
8479 xmlSchemaPIllegalAttrErr(ctxt,
8480 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8481 NULL, type, attr);
8482 }
8483 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8484 xmlSchemaPIllegalAttrErr(ctxt,
8485 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8486 NULL, type, attr);
8487 }
8488 attr = attr->next;
8489 }
8490 /*
8491 * Extract and validate attributes.
8492 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008493 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008494 /*
8495 * Attribute "base".
8496 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008497 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00008498 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00008499 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8500 /* TODO: Think about the error code. */
8501 xmlSchemaPMissingAttrErr(ctxt,
8502 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
8503 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008504 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008505 /*
8506 * And now for the children...
8507 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008508 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008509 child = node->children;
8510 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008511 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8512 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008513 }
8514 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008515 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8516 if (IS_SCHEMA(child, "all")) {
8517 subtype = (xmlSchemaTypePtr)
8518 xmlSchemaParseAll(ctxt, schema, child);
8519 child = child->next;
8520 type->subtypes = subtype;
8521 } else if (IS_SCHEMA(child, "choice")) {
8522 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8523 child = child->next;
8524 type->subtypes = subtype;
8525 } else if (IS_SCHEMA(child, "sequence")) {
8526 subtype = (xmlSchemaTypePtr)
8527 xmlSchemaParseSequence(ctxt, schema, child);
8528 child = child->next;
8529 type->subtypes = subtype;
8530 } else if (IS_SCHEMA(child, "group")) {
8531 subtype = (xmlSchemaTypePtr)
8532 xmlSchemaParseGroup(ctxt, schema, child, 0);
8533 child = child->next;
8534 type->subtypes = subtype;
8535 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008536 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
8537 if (IS_SCHEMA(child, "simpleType")) {
8538 if (type->base != NULL) {
8539 /*
8540 * src-restriction-base-or-simpleType
8541 * Either the base [attribute] or the simpleType [child] of the
8542 * <restriction> element must be present, but not both.
8543 */
8544 xmlSchemaPContentErr(ctxt,
8545 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
8546 NULL, NULL, type->node, child,
8547 "The attribute 'base' and the <simpleType> child are "
8548 "mutually exclusive", NULL);
8549 } else {
8550 subtype = (xmlSchemaTypePtr)
8551 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8552 type->baseType = subtype;
8553 }
8554 child = child->next;
8555 }
8556 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008557 if (IS_SCHEMA(child, "simpleType")) {
8558 subtype = (xmlSchemaTypePtr)
8559 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008560 type->subtypes = subtype;
8561 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00008562 }
8563 }
8564 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
8565 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
8566 xmlSchemaFacetPtr facet, lastfacet = NULL;
8567
Daniel Veillard01fa6152004-06-29 17:04:39 +00008568 /*
8569 * Add the facets to the parent simpleType/complexType.
8570 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008571 /*
8572 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
8573 * Simple Type Definition Schema Representation Constraint:
8574 * *Single Facet Value*
8575 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008576 while ((IS_SCHEMA(child, "minInclusive")) ||
8577 (IS_SCHEMA(child, "minExclusive")) ||
8578 (IS_SCHEMA(child, "maxInclusive")) ||
8579 (IS_SCHEMA(child, "maxExclusive")) ||
8580 (IS_SCHEMA(child, "totalDigits")) ||
8581 (IS_SCHEMA(child, "fractionDigits")) ||
8582 (IS_SCHEMA(child, "pattern")) ||
8583 (IS_SCHEMA(child, "enumeration")) ||
8584 (IS_SCHEMA(child, "whiteSpace")) ||
8585 (IS_SCHEMA(child, "length")) ||
8586 (IS_SCHEMA(child, "maxLength")) ||
8587 (IS_SCHEMA(child, "minLength"))) {
8588 facet = xmlSchemaParseFacet(ctxt, schema, child);
8589 if (facet != NULL) {
8590 if (lastfacet == NULL)
8591 ctxt->ctxtType->facets = facet;
8592 else
8593 lastfacet->next = facet;
8594 lastfacet = facet;
8595 lastfacet->next = NULL;
8596 }
8597 child = child->next;
8598 }
8599 /*
8600 * Create links for derivation and validation.
8601 */
8602 if (lastfacet != NULL) {
8603 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
8604
8605 facet = ctxt->ctxtType->facets;
8606 do {
8607 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
8608 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008609 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008610 xmlFree(facetLink);
8611 return (NULL);
8612 }
8613 facetLink->facet = facet;
8614 facetLink->next = NULL;
8615 if (lastFacetLink == NULL)
8616 ctxt->ctxtType->facetSet = facetLink;
8617 else
8618 lastFacetLink->next = facetLink;
8619 lastFacetLink = facetLink;
8620 facet = facet->next;
8621 } while (facet != NULL);
8622 }
8623 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008624 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
8625 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8626 if (IS_SCHEMA(child, "anyAttribute")) {
8627 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8628 child = child->next;
8629 }
8630 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008631 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008632 /* TODO: Think about the error code. */
8633 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8634 xmlSchemaPContentErr(ctxt,
8635 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8636 NULL, type, node, child, NULL,
8637 "annotation?, (group | all | choice | sequence)?, "
8638 "((attribute | attributeGroup)*, anyAttribute?))");
8639 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
8640 xmlSchemaPContentErr(ctxt,
8641 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8642 NULL, type, node, child, NULL,
8643 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8644 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8645 "length | minLength | maxLength | enumeration | whiteSpace | "
8646 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
8647 } else {
8648 /* Simple type */
8649 xmlSchemaPContentErr(ctxt,
8650 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8651 NULL, type, node, child, NULL,
8652 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8653 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8654 "length | minLength | maxLength | enumeration | whiteSpace | "
8655 "pattern)*))");
8656 }
8657 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008658 ctxt->container = oldcontainer;
8659 return (type);
8660}
8661
8662/**
8663 * xmlSchemaParseExtension:
8664 * @ctxt: a schema validation context
8665 * @schema: the schema being built
8666 * @node: a subtree containing XML Schema informations
8667 *
8668 * parse a XML schema Extension definition
8669 * *WARNING* this interface is highly subject to change
8670 *
8671 * Returns the type definition or NULL in case of error
8672 */
8673static xmlSchemaTypePtr
8674xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008675 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008676{
8677 xmlSchemaTypePtr type, subtype;
8678 xmlNodePtr child = NULL;
8679 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008680 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008681
8682 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8683 return (NULL);
8684
8685 oldcontainer = ctxt->container;
8686
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008687 snprintf((char *) name, 30, "#ext%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008688 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008689 if (type == NULL)
8690 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008691 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008692 type->node = node;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008693
8694 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8695
Daniel Veillard4255d502002-04-16 15:50:10 +00008696 ctxt->container = name;
8697
8698 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
8699 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008700 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008701 "<extension>: The attribute \"base\" is missing.\n",
8702 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008703 }
8704 child = node->children;
8705 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008706 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8707 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008708 }
8709 subtype = NULL;
8710
8711 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008712 subtype = xmlSchemaParseAll(ctxt, schema, child);
8713 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008714 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008715 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8716 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008717 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008718 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8719 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008720 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008721 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008722 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008723 }
8724 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008725 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008726 if ((ctxt->ctxtType != NULL) &&
8727 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8728 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8729 if (IS_SCHEMA(child, "anyAttribute")) {
8730 ctxt->ctxtType->attributeWildcard =
8731 xmlSchemaParseAnyAttribute(ctxt, schema, child);
8732 child = child->next;
8733 }
8734 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008735 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008736 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008737 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
8738 "<extension> has unexpected content.\n", type->name,
8739 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008740 }
8741 ctxt->container = oldcontainer;
8742 return (type);
8743}
8744
8745/**
8746 * xmlSchemaParseSimpleContent:
8747 * @ctxt: a schema validation context
8748 * @schema: the schema being built
8749 * @node: a subtree containing XML Schema informations
8750 *
8751 * parse a XML schema SimpleContent definition
8752 * *WARNING* this interface is highly subject to change
8753 *
8754 * Returns the type definition or NULL in case of error
8755 */
8756static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008757xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
8758 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008759{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008760 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008761 xmlNodePtr child = NULL;
8762 xmlChar name[30];
8763
8764 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8765 return (NULL);
8766
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008767 snprintf((char *) name, 30, "#SC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008768 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008769 if (type == NULL)
8770 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008771 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00008772 type->node = node;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008773
8774 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00008775
8776 child = node->children;
8777 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008778 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8779 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008780 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008781 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008782 ctxt->parentItem = type;
8783 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008784 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008785 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008786 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008787 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008788 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008789 subtype = (xmlSchemaTypePtr)
8790 xmlSchemaParseExtension(ctxt, schema, child);
8791 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008792 }
8793 type->subtypes = subtype;
8794 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008795 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008796 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
8797 "<simpleContent> has unexpected content.\n",
8798 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008799 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008800 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008801 return (type);
8802}
8803
8804/**
8805 * xmlSchemaParseComplexContent:
8806 * @ctxt: a schema validation context
8807 * @schema: the schema being built
8808 * @node: a subtree containing XML Schema informations
8809 *
8810 * parse a XML schema ComplexContent definition
8811 * *WARNING* this interface is highly subject to change
8812 *
8813 * Returns the type definition or NULL in case of error
8814 */
8815static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008816xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
8817 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008818{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008819 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008820 xmlNodePtr child = NULL;
8821 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008822 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008823
8824 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8825 return (NULL);
8826
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008827 snprintf((char *) name, 30, "#CC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008828 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008829 if (type == NULL)
8830 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008831 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008832 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008833 /*
8834 * Check for illegal attributes.
8835 */
8836 attr = node->properties;
8837 while (attr != NULL) {
8838 if (attr->ns == NULL) {
8839 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8840 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
8841 {
8842 xmlSchemaPIllegalAttrErr(ctxt,
8843 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8844 NULL, NULL, attr);
8845 }
8846 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8847 xmlSchemaPIllegalAttrErr(ctxt,
8848 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8849 NULL, NULL, attr);
8850 }
8851 attr = attr->next;
8852 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008853
8854 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8855
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008856 /*
8857 * Handle attribute 'mixed'.
8858 */
8859 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
8860 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
8861 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
8862 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008863 child = node->children;
8864 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008865 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8866 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008867 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008868 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008869 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008870 subtype = NULL;
8871 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008872 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008873 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008874 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008875 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008876 subtype = (xmlSchemaTypePtr)
8877 xmlSchemaParseExtension(ctxt, schema, child);
8878 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008879 }
8880 type->subtypes = subtype;
8881 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008882 xmlSchemaPContentErr(ctxt,
8883 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8884 NULL, NULL, node, child,
8885 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008886 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008887 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008888 return (type);
8889}
8890
8891/**
8892 * xmlSchemaParseComplexType:
8893 * @ctxt: a schema validation context
8894 * @schema: the schema being built
8895 * @node: a subtree containing XML Schema informations
8896 *
8897 * parse a XML schema Complex Type definition
8898 * *WARNING* this interface is highly subject to change
8899 *
8900 * Returns the type definition or NULL in case of error
8901 */
8902static xmlSchemaTypePtr
8903xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008904 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008905{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008906 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008907 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008908 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008909 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008910 xmlAttrPtr attr;
8911 const xmlChar *attrValue;
8912 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00008913 char buf[40];
8914
Daniel Veillard4255d502002-04-16 15:50:10 +00008915
8916 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8917 return (NULL);
8918
Daniel Veillard01fa6152004-06-29 17:04:39 +00008919 ctxtType = ctxt->ctxtType;
8920
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008921 if (topLevel) {
8922 attr = xmlSchemaGetPropNode(node, "name");
8923 if (attr == NULL) {
8924 xmlSchemaPMissingAttrErr(ctxt,
8925 XML_SCHEMAP_S4S_ATTR_MISSING,
8926 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
8927 "name", NULL);
8928 return (NULL);
8929 } else if (xmlSchemaPValAttrNode(ctxt,
8930 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
8931 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8932 return (NULL);
8933 }
8934 }
8935
8936 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008937 /*
8938 * Parse as local complex type definition.
8939 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008940 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008941 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
8942 if (type == NULL)
8943 return (NULL);
8944 name = (const xmlChar *) buf;
8945 type->node = node;
8946 type->type = XML_SCHEMA_TYPE_COMPLEX;
8947 /*
8948 * TODO: We need the target namespace.
8949 */
8950 } else {
8951 /*
8952 * Parse as global complex type definition.
8953 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008954 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008955 if (type == NULL)
8956 return (NULL);
8957 type->node = node;
8958 type->type = XML_SCHEMA_TYPE_COMPLEX;
8959 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8960 /*
8961 * Set defaults.
8962 */
8963 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
8964 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008965 }
8966 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008967 /*
8968 * Handle attributes.
8969 */
8970 attr = node->properties;
8971 while (attr != NULL) {
8972 if (attr->ns == NULL) {
8973 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
8974 /*
8975 * Attribute "id".
8976 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008977 xmlSchemaPValAttrID(ctxt, NULL, type, node,
8978 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008979 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
8980 /*
8981 * Attribute "mixed".
8982 */
8983 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8984 (xmlNodePtr) attr))
8985 type->flags |= XML_SCHEMAS_TYPE_MIXED;
8986 } else if (topLevel) {
8987 /*
8988 * Attributes of global complex type definitions.
8989 */
8990 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
8991 /* Pass. */
8992 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
8993 /*
8994 * Attribute "abstract".
8995 */
8996 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8997 (xmlNodePtr) attr))
8998 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
8999 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
9000 /*
9001 * Attribute "final".
9002 */
9003 attrValue = xmlSchemaGetNodeContent(ctxt,
9004 (xmlNodePtr) attr);
9005 if (xmlSchemaPValAttrBlockFinal(attrValue,
9006 &(type->flags),
9007 -1,
9008 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
9009 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
9010 -1, -1, -1) != 0)
9011 {
9012 xmlSchemaPSimpleTypeErr(ctxt,
9013 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9014 &des, type, (xmlNodePtr) attr,
9015 NULL,
9016 "(#all | List of (extension | restriction))",
9017 attrValue, NULL, NULL, NULL);
9018 }
9019 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
9020 /*
9021 * Attribute "block".
9022 */
9023 attrValue = xmlSchemaGetNodeContent(ctxt,
9024 (xmlNodePtr) attr);
9025 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9026 -1,
9027 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
9028 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
9029 -1, -1, -1) != 0) {
9030 xmlSchemaPSimpleTypeErr(ctxt,
9031 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9032 &des, type, (xmlNodePtr) attr,
9033 NULL,
9034 "(#all | List of (extension | restriction)) ",
9035 attrValue, NULL, NULL, NULL);
9036 }
9037 } else {
9038 xmlSchemaPIllegalAttrErr(ctxt,
9039 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9040 &des, type, attr);
9041 }
9042 } else {
9043 xmlSchemaPIllegalAttrErr(ctxt,
9044 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9045 &des, type, attr);
9046 }
9047 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9048 xmlSchemaPIllegalAttrErr(ctxt,
9049 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9050 &des, type, attr);
9051 }
9052 attr = attr->next;
9053 }
9054 /*
9055 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009056 * This will be only changed if a complex type
9057 * inherits an attribute wildcard from a base type.
9058 */
9059 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009060 /*
9061 * And now for the children...
9062 */
9063 oldcontainer = ctxt->container;
9064 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009065 child = node->children;
9066 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009067 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9068 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009069 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009070 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009071 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009072 /*
9073 * 3.4.3 : 2.2
9074 * Specifying mixed='true' when the <simpleContent>
9075 * alternative is chosen has no effect
9076 */
William M. Bracke7091952004-05-11 15:09:58 +00009077 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
9078 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009079 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
9080 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009081 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009082 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
9083 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009084 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009085 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009086 /*
9087 * Parse model groups.
9088 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009089 if (IS_SCHEMA(child, "all")) {
9090 subtype = xmlSchemaParseAll(ctxt, schema, child);
9091 child = child->next;
9092 } else if (IS_SCHEMA(child, "choice")) {
9093 subtype = xmlSchemaParseChoice(ctxt, schema, child);
9094 child = child->next;
9095 } else if (IS_SCHEMA(child, "sequence")) {
9096 subtype = xmlSchemaParseSequence(ctxt, schema, child);
9097 child = child->next;
9098 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009099 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009100 child = child->next;
9101 }
9102 if (subtype != NULL)
9103 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009104 /*
9105 * Parse attribute decls/refs.
9106 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009107 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009108 /*
9109 * Parse attribute wildcard.
9110 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009111 if (IS_SCHEMA(child, "anyAttribute")) {
9112 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
9113 child = child->next;
9114 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009115 }
9116 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009117 xmlSchemaPContentErr(ctxt,
9118 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9119 &des, type, node, child,
9120 NULL, "(annotation?, (simpleContent | complexContent | "
9121 "((group | all | choice | sequence)?, ((attribute | "
9122 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009123 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009124 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00009125 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009126 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009127 return (type);
9128}
9129
Daniel Veillard4255d502002-04-16 15:50:10 +00009130/**
9131 * xmlSchemaParseSchema:
9132 * @ctxt: a schema validation context
9133 * @node: a subtree containing XML Schema informations
9134 *
9135 * parse a XML schema definition from a node set
9136 * *WARNING* this interface is highly subject to change
9137 *
9138 * Returns the internal XML Schema structure built from the resource or
9139 * NULL in case of error
9140 */
9141static xmlSchemaPtr
9142xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
9143{
9144 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009145 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009146 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009147 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009148
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009149 /*
9150 * This one is called by xmlSchemaParse only and is used if
9151 * the schema to be parsed was specified via the API; i.e. not
9152 * automatically by the validated instance document.
9153 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009154 if ((ctxt == NULL) || (node == NULL))
9155 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009156 nberrors = ctxt->nberrors;
9157 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009158 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009159 xmlSchemaImportPtr import;
9160
Daniel Veillard4255d502002-04-16 15:50:10 +00009161 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009162 if (schema == NULL)
9163 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009164 /*
9165 * Disable build of list of items.
9166 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009167 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9168 if (attr != NULL) {
9169 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9170 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
9171 /*
9172 * TODO: Should we proceed with an invalid target namespace?
9173 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009174 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
9175 } else {
9176 schema->targetNamespace = NULL;
9177 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009178 /*
9179 * Add the current ns name and location to the import table;
9180 * this is needed to have a consistent mechanism, regardless
9181 * if all schemata are constructed dynamically fired by the
9182 * instance or if the schema to be used was specified via
9183 * the API.
9184 */
9185 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
9186 schema->targetNamespace);
9187 if (import == NULL) {
9188 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
9189 NULL, NULL, (xmlNodePtr) ctxt->doc,
9190 "Internal error: xmlSchemaParseSchema, "
9191 "failed to add an import entry", NULL);
9192 xmlSchemaFree(schema);
9193 schema = NULL;
9194 return (NULL);
9195 }
9196 import->schemaLocation = ctxt->URL;
9197 /*
9198 * NOTE: We won't set the doc here, otherwise it will be freed
9199 * if the import struct is freed.
9200 * import->doc = ctxt->doc;
9201 */
9202
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009203 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009204 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
9205 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
9206
William M. Brack2f2a6632004-08-20 23:09:47 +00009207 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009208 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
9209 } else {
9210 xmlDocPtr doc;
9211
9212 doc = node->doc;
9213
9214 if ((doc != NULL) && (doc->URL != NULL)) {
9215 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9216 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009217 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009218 } else {
9219 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9220 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009221 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009222 }
9223 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009224 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009225 if (ctxt->nberrors != 0) {
9226 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009227 xmlSchemaFree(schema);
9228 schema = NULL;
9229 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009230 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009231 if (schema != NULL)
9232 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009233 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00009234#ifdef DEBUG
9235 if (schema == NULL)
9236 xmlGenericError(xmlGenericErrorContext,
9237 "xmlSchemaParse() failed\n");
9238#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009239 return (schema);
9240}
9241
9242/************************************************************************
9243 * *
9244 * Validating using Schemas *
9245 * *
9246 ************************************************************************/
9247
9248/************************************************************************
9249 * *
9250 * Reading/Writing Schemas *
9251 * *
9252 ************************************************************************/
9253
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009254#if 0 /* Will be enabled if it is clear what options are needed. */
9255/**
9256 * xmlSchemaParserCtxtSetOptions:
9257 * @ctxt: a schema parser context
9258 * @options: a combination of xmlSchemaParserOption
9259 *
9260 * Sets the options to be used during the parse.
9261 *
9262 * Returns 0 in case of success, -1 in case of an
9263 * API error.
9264 */
9265static int
9266xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
9267 int options)
9268
9269{
9270 int i;
9271
9272 if (ctxt == NULL)
9273 return (-1);
9274 /*
9275 * WARNING: Change the start value if adding to the
9276 * xmlSchemaParseOption.
9277 */
9278 for (i = 1; i < (int) sizeof(int) * 8; i++) {
9279 if (options & 1<<i) {
9280 return (-1);
9281 }
9282 }
9283 ctxt->options = options;
9284 return (0);
9285}
9286
9287/**
9288 * xmlSchemaValidCtxtGetOptions:
9289 * @ctxt: a schema parser context
9290 *
9291 * Returns the option combination of the parser context.
9292 */
9293static int
9294xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
9295
9296{
9297 if (ctxt == NULL)
9298 return (-1);
9299 else
9300 return (ctxt->options);
9301}
9302
9303 void *curItems; /* used for dynamic addition of schemata */
9304 int nbCurItems; /* used for dynamic addition of schemata */
9305 int sizeCurItems; /* used for dynamic addition of schemata */
9306
9307#endif
9308
Daniel Veillard4255d502002-04-16 15:50:10 +00009309/**
9310 * xmlSchemaNewParserCtxt:
9311 * @URL: the location of the schema
9312 *
9313 * Create an XML Schemas parse context for that file/resource expected
9314 * to contain an XML Schemas file.
9315 *
9316 * Returns the parser context or NULL in case of error
9317 */
9318xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009319xmlSchemaNewParserCtxt(const char *URL)
9320{
Daniel Veillard4255d502002-04-16 15:50:10 +00009321 xmlSchemaParserCtxtPtr ret;
9322
9323 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009324 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009325
9326 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9327 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009328 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009329 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009330 return (NULL);
9331 }
9332 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009333 ret->dict = xmlDictCreate();
9334 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00009335 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009336 return (ret);
9337}
9338
9339/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009340 * xmlSchemaNewParserCtxtUseDict:
9341 * @URL: the location of the schema
9342 * @dict: the dictionary to be used
9343 *
9344 * Create an XML Schemas parse context for that file/resource expected
9345 * to contain an XML Schemas file.
9346 *
9347 * Returns the parser context or NULL in case of error
9348 */
9349static xmlSchemaParserCtxtPtr
9350xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9351{
9352 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009353 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009354 if (URL == NULL)
9355 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009356 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009357
9358 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9359 if (ret == NULL) {
9360 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9361 NULL);
9362 return (NULL);
9363 }
9364 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9365 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009366 xmlDictReference(dict);
9367 if (URL != NULL)
9368 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009369 ret->includes = 0;
9370 return (ret);
9371}
9372
9373
9374/**
Daniel Veillard6045c902002-10-09 21:13:59 +00009375 * xmlSchemaNewMemParserCtxt:
9376 * @buffer: a pointer to a char array containing the schemas
9377 * @size: the size of the array
9378 *
9379 * Create an XML Schemas parse context for that memory buffer expected
9380 * to contain an XML Schemas file.
9381 *
9382 * Returns the parser context or NULL in case of error
9383 */
9384xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009385xmlSchemaNewMemParserCtxt(const char *buffer, int size)
9386{
Daniel Veillard6045c902002-10-09 21:13:59 +00009387 xmlSchemaParserCtxtPtr ret;
9388
9389 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009390 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009391
9392 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9393 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009394 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009395 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009396 return (NULL);
9397 }
9398 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9399 ret->buffer = buffer;
9400 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009401 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00009402 return (ret);
9403}
9404
9405/**
Daniel Veillard9d751502003-10-29 13:21:47 +00009406 * xmlSchemaNewDocParserCtxt:
9407 * @doc: a preparsed document tree
9408 *
9409 * Create an XML Schemas parse context for that document.
9410 * NB. The document may be modified during the parsing process.
9411 *
9412 * Returns the parser context or NULL in case of error
9413 */
9414xmlSchemaParserCtxtPtr
9415xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
9416{
9417 xmlSchemaParserCtxtPtr ret;
9418
9419 if (doc == NULL)
9420 return (NULL);
9421
9422 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9423 if (ret == NULL) {
9424 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9425 NULL);
9426 return (NULL);
9427 }
9428 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9429 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009430 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00009431 /* The application has responsibility for the document */
9432 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00009433
9434 return (ret);
9435}
9436
9437/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009438 * xmlSchemaFreeParserCtxt:
9439 * @ctxt: the schema parser context
9440 *
9441 * Free the resources associated to the schema parser context
9442 */
9443void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009444xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
9445{
Daniel Veillard4255d502002-04-16 15:50:10 +00009446 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009447 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00009448 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009449 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009450 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009451 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009452 xmlFree(ctxt->assemble);
9453 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009454 if (ctxt->vctxt != NULL) {
9455 xmlSchemaFreeValidCtxt(ctxt->vctxt);
9456 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009457 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00009458 xmlFree(ctxt);
9459}
9460
9461/************************************************************************
9462 * *
9463 * Building the content models *
9464 * *
9465 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009466
Daniel Veillard4255d502002-04-16 15:50:10 +00009467/**
9468 * xmlSchemaBuildAContentModel:
9469 * @type: the schema type definition
9470 * @ctxt: the schema parser context
9471 * @name: the element name whose content is being built
9472 *
9473 * Generate the automata sequence needed for that type
9474 */
9475static void
9476xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009477 xmlSchemaParserCtxtPtr ctxt,
9478 const xmlChar * name)
9479{
Daniel Veillard4255d502002-04-16 15:50:10 +00009480 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009481 xmlGenericError(xmlGenericErrorContext,
9482 "Found unexpected type = NULL in %s content model\n",
9483 name);
9484 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009485 }
9486 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009487 case XML_SCHEMA_TYPE_ANY: {
9488 xmlAutomataStatePtr start, end;
9489 xmlSchemaWildcardPtr wild;
9490 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00009491
Daniel Veillardc0826a72004-08-10 14:17:33 +00009492 wild = type->attributeWildcard;
9493
9494 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009495 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009496 "Internal error: xmlSchemaBuildAContentModel, "
9497 "no wildcard on xsd:any.\n", NULL, NULL);
9498 return;
9499 }
9500
9501 start = ctxt->state;
9502 end = xmlAutomataNewState(ctxt->am);
9503
9504 if (type->maxOccurs == 1) {
9505 if (wild->any == 1) {
9506 /*
9507 * We need to add both transitions:
9508 *
9509 * 1. the {"*", "*"} for elements in a namespace.
9510 */
9511 ctxt->state =
9512 xmlAutomataNewTransition2(ctxt->am,
9513 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9514 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9515 /*
9516 * 2. the {"*"} for elements in no namespace.
9517 */
9518 ctxt->state =
9519 xmlAutomataNewTransition2(ctxt->am,
9520 start, NULL, BAD_CAST "*", NULL, type);
9521 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9522
9523 } else if (wild->nsSet != NULL) {
9524 ns = wild->nsSet;
9525 do {
9526 ctxt->state = start;
9527 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9528 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
9529 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9530 ns = ns->next;
9531 } while (ns != NULL);
9532
9533 } else if (wild->negNsSet != NULL) {
9534 xmlAutomataStatePtr deadEnd;
9535
9536 deadEnd = xmlAutomataNewState(ctxt->am);
9537 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9538 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9539 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9540 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9541 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9542 }
9543 } else {
9544 int counter;
9545 xmlAutomataStatePtr hop;
9546 int maxOccurs =
9547 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
9548 int minOccurs =
9549 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9550
9551 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9552 hop = xmlAutomataNewState(ctxt->am);
9553 if (wild->any == 1) {
9554 ctxt->state =
9555 xmlAutomataNewTransition2(ctxt->am,
9556 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9557 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9558 ctxt->state =
9559 xmlAutomataNewTransition2(ctxt->am,
9560 start, NULL, BAD_CAST "*", NULL, type);
9561 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9562 } else if (wild->nsSet != NULL) {
9563 ns = wild->nsSet;
9564 do {
9565 ctxt->state =
9566 xmlAutomataNewTransition2(ctxt->am,
9567 start, NULL, BAD_CAST "*", ns->value, type);
9568 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9569 ns = ns->next;
9570 } while (ns != NULL);
9571
9572 } else if (wild->negNsSet != NULL) {
9573 xmlAutomataStatePtr deadEnd;
9574
9575 deadEnd = xmlAutomataNewState(ctxt->am);
9576 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9577 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9578 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9579 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9580 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9581 }
9582 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
9583 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
9584 }
9585 if (type->minOccurs == 0) {
9586 xmlAutomataNewEpsilon(ctxt->am, start, end);
9587 }
9588 ctxt->state = end;
9589 break;
9590 }
9591 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009592 xmlAutomataStatePtr oldstate;
9593 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00009594
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009595 /*
9596 * IMPORTANT: This puts element declarations
9597 * (and never element decl. references) into the
9598 * automaton. This is crucial and should not be changed,
9599 * since validating functions rely now on it.
9600 */
9601 particle = (xmlSchemaElementPtr) type;
9602 if (particle->ref != NULL) {
9603 if (particle->refDecl == NULL) {
9604 /*
9605 * Skip content model creation if the reference
9606 * did not resolve to a declaration.
9607 */
9608 break;
9609 } else {
9610 /*
9611 * Referenced global element declaration.
9612 */
9613 elemDecl = particle->refDecl;
9614 }
9615 } else {
9616 /*
9617 * Anonymous element declaration.
9618 */
9619 elemDecl = particle;
9620 }
9621
9622 oldstate = ctxt->state;
9623
9624 if (particle->maxOccurs >= UNBOUNDED) {
9625 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009626 xmlAutomataStatePtr tmp;
9627 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009628
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009629 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009630 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009631 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009632 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009633 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00009634 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009635 xmlAutomataNewTransition2(ctxt->am,
9636 ctxt->state, NULL,
9637 elemDecl->name,
9638 elemDecl->targetNamespace,
9639 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009640 tmp = ctxt->state;
9641 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009642 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009643 ctxt->state =
9644 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009645 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00009646
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009647 } else {
9648 ctxt->state =
9649 xmlAutomataNewTransition2(ctxt->am,
9650 ctxt->state, NULL,
9651 elemDecl->name,
9652 elemDecl->targetNamespace,
9653 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009654 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9655 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009656 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009657 /* basically an elem* */
9658 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9659 ctxt->state);
9660 }
9661 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009662 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009663 xmlAutomataStatePtr tmp;
9664 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009665
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009666 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9667 oldstate, NULL);
9668 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009669 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009670 particle->minOccurs - 1,
9671 particle->maxOccurs - 1);
9672 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9673 ctxt->state,
9674 NULL,
9675 elemDecl->name,
9676 elemDecl->targetNamespace,
9677 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009678 tmp = ctxt->state;
9679 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009680 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009681 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009682 NULL, counter);
9683 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009684 /* basically an elem? */
9685 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009686 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009687 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00009688
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009689 } else {
9690 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9691 ctxt->state,
9692 NULL,
9693 elemDecl->name,
9694 elemDecl->targetNamespace,
9695 (xmlSchemaTypePtr) elemDecl);
9696 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009697 /* basically an elem? */
9698 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009699 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009700 }
9701 }
9702 break;
9703 }
9704 case XML_SCHEMA_TYPE_SEQUENCE:{
9705 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009706
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009707 /*
9708 * If max and min occurances are default (1) then
9709 * simply iterate over the subtypes
9710 */
9711 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
9712 subtypes = type->subtypes;
9713 while (subtypes != NULL) {
9714 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9715 subtypes = subtypes->next;
9716 }
9717 } else {
9718 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009719
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009720 if (type->maxOccurs >= UNBOUNDED) {
9721 if (type->minOccurs > 1) {
9722 xmlAutomataStatePtr tmp;
9723 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009724
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009725 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9726 oldstate,
9727 NULL);
9728 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009729
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009730 counter = xmlAutomataNewCounter(ctxt->am,
9731 type->
9732 minOccurs - 1,
9733 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009734
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009735 subtypes = type->subtypes;
9736 while (subtypes != NULL) {
9737 xmlSchemaBuildAContentModel(subtypes, ctxt,
9738 name);
9739 subtypes = subtypes->next;
9740 }
9741 tmp = ctxt->state;
9742 xmlAutomataNewCountedTrans(ctxt->am, tmp,
9743 oldstate, counter);
9744 ctxt->state =
9745 xmlAutomataNewCounterTrans(ctxt->am, tmp,
9746 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009747
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009748 } else {
9749 subtypes = type->subtypes;
9750 while (subtypes != NULL) {
9751 xmlSchemaBuildAContentModel(subtypes, ctxt,
9752 name);
9753 subtypes = subtypes->next;
9754 }
9755 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9756 oldstate);
9757 if (type->minOccurs == 0) {
9758 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9759 ctxt->state);
9760 }
9761 }
9762 } else if ((type->maxOccurs > 1)
9763 || (type->minOccurs > 1)) {
9764 xmlAutomataStatePtr tmp;
9765 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009766
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009767 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9768 oldstate,
9769 NULL);
9770 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00009771
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009772 counter = xmlAutomataNewCounter(ctxt->am,
9773 type->minOccurs -
9774 1,
9775 type->maxOccurs -
9776 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009777
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009778 subtypes = type->subtypes;
9779 while (subtypes != NULL) {
9780 xmlSchemaBuildAContentModel(subtypes, ctxt,
9781 name);
9782 subtypes = subtypes->next;
9783 }
9784 tmp = ctxt->state;
9785 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
9786 counter);
9787 ctxt->state =
9788 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
9789 counter);
9790 if (type->minOccurs == 0) {
9791 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9792 ctxt->state);
9793 }
Daniel Veillardb509f152002-04-17 16:28:10 +00009794
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009795 } else {
9796 subtypes = type->subtypes;
9797 while (subtypes != NULL) {
9798 xmlSchemaBuildAContentModel(subtypes, ctxt,
9799 name);
9800 subtypes = subtypes->next;
9801 }
9802 if (type->minOccurs == 0) {
9803 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9804 ctxt->state);
9805 }
9806 }
9807 }
9808 break;
9809 }
9810 case XML_SCHEMA_TYPE_CHOICE:{
9811 xmlSchemaTypePtr subtypes;
9812 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00009813
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009814 start = ctxt->state;
9815 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00009816
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009817 /*
9818 * iterate over the subtypes and remerge the end with an
9819 * epsilon transition
9820 */
9821 if (type->maxOccurs == 1) {
9822 subtypes = type->subtypes;
9823 while (subtypes != NULL) {
9824 ctxt->state = start;
9825 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9826 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9827 subtypes = subtypes->next;
9828 }
9829 } else {
9830 int counter;
9831 xmlAutomataStatePtr hop;
9832 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9833 UNBOUNDED : type->maxOccurs - 1;
9834 int minOccurs =
9835 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00009836
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009837 /*
9838 * use a counter to keep track of the number of transtions
9839 * which went through the choice.
9840 */
9841 counter =
9842 xmlAutomataNewCounter(ctxt->am, minOccurs,
9843 maxOccurs);
9844 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00009845
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009846 subtypes = type->subtypes;
9847 while (subtypes != NULL) {
9848 ctxt->state = start;
9849 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9850 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9851 subtypes = subtypes->next;
9852 }
9853 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9854 counter);
9855 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9856 counter);
9857 }
9858 if (type->minOccurs == 0) {
9859 xmlAutomataNewEpsilon(ctxt->am, start, end);
9860 }
9861 ctxt->state = end;
9862 break;
9863 }
9864 case XML_SCHEMA_TYPE_ALL:{
9865 xmlAutomataStatePtr start;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009866 xmlSchemaElementPtr elemDecl, particle;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009867 int lax;
9868
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009869 particle = (xmlSchemaElementPtr) type->subtypes;
9870 if (particle == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009871 break;
9872 start = ctxt->state;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009873 while (particle != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009874 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00009875 /*
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009876 * Changed to put the element declaration and
9877 * never the element decl. reference into the
9878 * automaton. This fixes bug 139897 and bug 167754.
William M. Brack9989c7d2004-05-12 14:39:38 +00009879 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009880 if (particle->ref != NULL) {
9881 if (particle->refDecl == NULL) {
9882 /*
9883 * TODO: Note that we break on missing
9884 * sub-components.
9885 */
9886 break;
9887 } else
9888 elemDecl = particle->refDecl;
9889 } else
9890 elemDecl = particle;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009891 /*
9892 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009893 * {particles} of the group must be 0 or 1; this is
9894 * already ensured during the parse of the content of
9895 * <all>.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009896 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009897 if ((particle->minOccurs == 1) &&
9898 (particle->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009899 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
9900 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009901 elemDecl->name,
9902 elemDecl->targetNamespace,
9903 1, 1, elemDecl);
9904 } else if ((particle->minOccurs == 0) &&
9905 (particle->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009906
9907 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
9908 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009909 elemDecl->name,
9910 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009911 0,
9912 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009913 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009914 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009915 particle = (xmlSchemaElementPtr) particle->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009916 }
9917 lax = type->minOccurs == 0;
9918 ctxt->state =
9919 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
9920 lax);
9921 break;
9922 }
9923 case XML_SCHEMA_TYPE_RESTRICTION:
9924 if (type->subtypes != NULL)
9925 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9926 break;
9927 case XML_SCHEMA_TYPE_EXTENSION:
9928 if (type->baseType != NULL) {
9929 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009930
9931 /*
9932 * TODO: Circular definitions will be checked at the
9933 * constraint level. So remove this when the complex type
9934 * constraints are implemented.
9935 */
Daniel Veillardf7627552004-04-22 07:15:40 +00009936 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009937 /* TODO: Change the error code. */
9938 xmlSchemaPCustomErr(ctxt,
9939 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
9940 NULL, type, type->node,
9941 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00009942 return;
9943 }
9944 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009945 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00009946 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009947 subtypes = type->subtypes;
9948 while (subtypes != NULL) {
9949 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9950 subtypes = subtypes->next;
9951 }
9952 } else if (type->subtypes != NULL)
9953 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9954 break;
9955 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00009956 /*
9957 * Handle model group definition references.
9958 * NOTE: type->subtypes is the referenced model grop definition;
9959 * and type->subtypes->subtypes is the model group (i.e. <all> or
9960 * <choice> or <sequence>).
9961 */
9962 if ((type->ref != NULL) && (type->subtypes != NULL) &&
9963 (type->subtypes->subtypes != NULL)) {
9964 xmlSchemaTypePtr modelGr;
9965 xmlAutomataStatePtr start, end;
9966
9967 modelGr = type->subtypes->subtypes;
9968 start = ctxt->state;
9969 end = xmlAutomataNewState(ctxt->am);
9970 if (type->maxOccurs == 1) {
9971 ctxt->state = start;
9972 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9973 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9974 } else {
9975 int counter;
9976 xmlAutomataStatePtr hop;
9977 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9978 UNBOUNDED : type->maxOccurs - 1;
9979 int minOccurs =
9980 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9981
9982 counter =
9983 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9984 hop = xmlAutomataNewState(ctxt->am);
9985 ctxt->state = start;
9986 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9987 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9988 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9989 counter);
9990 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9991 counter);
9992 }
9993 if (type->minOccurs == 0) {
9994 xmlAutomataNewEpsilon(ctxt->am, start, end);
9995 }
9996 ctxt->state = end;
9997 break;
9998 }
9999 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010000 case XML_SCHEMA_TYPE_COMPLEX:
10001 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
10002 if (type->subtypes != NULL)
10003 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10004 break;
William M. Brack2f2a6632004-08-20 23:09:47 +000010005 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
10006 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010007 default:
10008 xmlGenericError(xmlGenericErrorContext,
10009 "Found unexpected type %d in %s content model\n",
10010 type->type, name);
10011 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010012 }
10013}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010014
Daniel Veillard4255d502002-04-16 15:50:10 +000010015/**
10016 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010017 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +000010018 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +000010019 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000010020 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010021 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000010022 */
10023static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010024xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010025 xmlSchemaParserCtxtPtr ctxt,
10026 const xmlChar * name)
10027{
Daniel Veillard4255d502002-04-16 15:50:10 +000010028 xmlAutomataStatePtr start;
10029
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010030 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
10031 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
10032 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
10033 (type->contModel != NULL))
10034 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010035
10036#ifdef DEBUG_CONTENT
10037 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010038 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010039#endif
10040
Daniel Veillard4255d502002-04-16 15:50:10 +000010041 ctxt->am = xmlNewAutomata();
10042 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010043 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010044 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010045 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010046 }
10047 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010048 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000010049 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010050 type->contModel = xmlAutomataCompile(ctxt->am);
10051 if (type->contModel == NULL) {
10052 xmlSchemaPCustomErr(ctxt,
10053 XML_SCHEMAP_INTERNAL,
10054 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010055 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010056 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010057 xmlSchemaPCustomErr(ctxt,
10058 XML_SCHEMAP_NOT_DETERMINISTIC,
10059 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010060 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010061 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000010062 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000010063#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010064 xmlGenericError(xmlGenericErrorContext,
10065 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010066 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000010067#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000010068 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000010069 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000010070 xmlFreeAutomata(ctxt->am);
10071 ctxt->am = NULL;
10072}
10073
10074/**
10075 * xmlSchemaRefFixupCallback:
10076 * @elem: the schema element context
10077 * @ctxt: the schema parser context
10078 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000010079 * Resolves the references of an element declaration
10080 * or particle, which has an element declaration as it's
10081 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000010082 */
10083static void
10084xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010085 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010086 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010087 const xmlChar * context ATTRIBUTE_UNUSED,
10088 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000010089{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010090 if ((ctxt == NULL) || (elem == NULL) ||
10091 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010092 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010093 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000010094 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010095 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +000010096
Daniel Veillardc0826a72004-08-10 14:17:33 +000010097 /*
10098 * TODO: Evaluate, what errors could occur if the declaration is not
10099 * found. It might be possible that the "typefixup" might crash if
10100 * no ref declaration was found.
10101 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010102 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010103 if (elemDecl == NULL) {
10104 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010105 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010106 NULL, (xmlSchemaTypePtr) elem, elem->node,
10107 "ref", elem->ref, elem->refNs,
10108 XML_SCHEMA_TYPE_ELEMENT, NULL);
10109 } else
10110 elem->refDecl = elemDecl;
10111 } else {
10112 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
10113 xmlSchemaTypePtr type;
10114
10115 /* (type definition) ... otherwise the type definition ·resolved·
10116 * to by the ·actual value· of the type [attribute] ...
10117 */
10118 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
10119 elem->namedTypeNs);
10120 if (type == NULL) {
10121 xmlSchemaPResCompAttrErr(ctxt,
10122 XML_SCHEMAP_SRC_RESOLVE,
10123 NULL, (xmlSchemaTypePtr) elem, elem->node,
10124 "type", elem->namedType, elem->namedTypeNs,
10125 XML_SCHEMA_TYPE_BASIC, "type definition");
10126 } else
10127 elem->subtypes = type;
10128 }
10129 if (elem->substGroup != NULL) {
10130 xmlSchemaElementPtr substHead;
10131
10132 /*
10133 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
10134 * substitutionGroup?
10135 */
10136 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010137 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010138 if (substHead == NULL) {
10139 xmlSchemaPResCompAttrErr(ctxt,
10140 XML_SCHEMAP_SRC_RESOLVE,
10141 NULL, (xmlSchemaTypePtr) elem, NULL,
10142 "substitutionGroup", elem->substGroup, elem->substGroupNs,
10143 XML_SCHEMA_TYPE_ELEMENT, NULL);
10144 } else {
10145 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
10146 /*
10147 * (type definition)...otherwise the {type definition} of the
10148 * element declaration ·resolved· to by the ·actual value· of
10149 * the substitutionGroup [attribute], if present
10150 */
10151 if (elem->subtypes == NULL)
10152 elem->subtypes = substHead->subtypes;
10153 }
10154 }
10155 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
10156 (elem->substGroup == NULL))
10157 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10158 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010159}
10160
William M. Bracke7091952004-05-11 15:09:58 +000010161/**
10162 * xmlSchemaParseListRefFixup:
10163 * @type: the schema type definition
10164 * @ctxt: the schema parser context
10165 *
10166 * Fixup of the itemType reference of the list type.
10167 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010168static void
William M. Bracke7091952004-05-11 15:09:58 +000010169xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010170{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010171
Daniel Veillard01fa6152004-06-29 17:04:39 +000010172 if (((type->base == NULL) &&
10173 (type->subtypes == NULL)) ||
10174 ((type->base != NULL) &&
10175 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010176 /*
10177 * src-list-itemType-or-simpleType
10178 * Either the itemType [attribute] or the <simpleType> [child] of
10179 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010180 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010181 /*
10182 * TODO: Move this to the parse function.
10183 */
10184 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010185 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010186 NULL, type, type->node,
10187 "The attribute 'itemType' and the <simpleType> child "
10188 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010189 } else if (type->base!= NULL) {
10190 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
10191 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010192 xmlSchemaPResCompAttrErr(ctxt,
10193 XML_SCHEMAP_SRC_RESOLVE,
10194 NULL, type, type->node,
10195 "itemType", type->base, type->baseNs,
10196 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010197 }
10198 }
10199 if ((type->subtypes != NULL) &&
10200 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
10201 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +000010202}
10203
10204/**
10205 * xmlSchemaParseUnionRefCheck:
10206 * @typeDecl: the schema type definition
10207 * @ctxt: the schema parser context
10208 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000010209 * Checks and builds the memberTypes of the union type.
10210 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000010211 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010212static int
William M. Bracke7091952004-05-11 15:09:58 +000010213xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +000010214 xmlSchemaParserCtxtPtr ctxt)
10215{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010216
Daniel Veillard01fa6152004-06-29 17:04:39 +000010217 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
10218 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000010219
Daniel Veillard01fa6152004-06-29 17:04:39 +000010220 /* 1 If the <union> alternative is chosen, then [Definition:]
10221 * define the explicit members as the type definitions ·resolved·
10222 * to by the items in the ·actual value· of the memberTypes [attribute],
10223 * if any, followed by the type definitions corresponding to the
10224 * <simpleType>s among the [children] of <union>, if any.
10225 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010226
Daniel Veillard01fa6152004-06-29 17:04:39 +000010227 if (type->type != XML_SCHEMA_TYPE_UNION)
10228 return (-1);
10229 if (ctxt->ctxtType == NULL) {
10230 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010231 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010232 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
10233 "available", NULL, NULL);
10234 return (-1);
10235 }
10236 /*
10237 * src-union-memberTypes-or-simpleTypes
10238 * Either the memberTypes [attribute] of the <union> element must
10239 * be non-empty or there must be at least one simpleType [child].
10240 */
10241 if ((type->base == NULL) &&
10242 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010243 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010244 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010245 NULL, NULL, type->node,
10246 "Either the attribute 'memberTypes' must be non-empty "
10247 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010248 }
10249
10250 ctxtType = ctxt->ctxtType;
10251 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010252 xmlAttrPtr attr;
10253 const xmlChar *cur, *end;
10254 xmlChar *tmp;
10255 const xmlChar *localName, *uri;
10256
10257 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010258 cur = type->base;
10259 do {
10260 while (IS_BLANK_CH(*cur))
10261 cur++;
10262 end = cur;
10263 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
10264 end++;
10265 if (end == cur)
10266 break;
10267 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010268 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
10269 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
10270 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010271 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010272 xmlSchemaPResCompAttrErr(ctxt,
10273 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
10274 NULL, NULL, type->node, "memberTypes", localName, uri,
10275 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010276 } else {
10277 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10278 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10279 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10280 if (link == NULL) {
10281 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10282 return (-1);
10283 }
10284 link->type = memberType;
10285 link->next = NULL;
10286 if (lastLink == NULL)
10287 ctxtType->memberTypes = link;
10288 else
10289 lastLink->next = link;
10290 lastLink = link;
10291 }
10292 xmlFree(tmp);
10293 cur = end;
10294 } while (*cur != 0);
10295 }
10296 /*
10297 * Add local simple types,
10298 */
10299 memberType = type->subtypes;
10300 while (memberType != NULL) {
10301 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10302 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10303 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10304 if (link == NULL) {
10305 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10306 return (-1);
10307 }
10308 link->type = memberType;
10309 link->next = NULL;
10310 if (lastLink == NULL)
10311 ctxtType->memberTypes = link;
10312 else
10313 lastLink->next = link;
10314 lastLink = link;
10315 memberType = memberType->next;
10316 }
10317 /*
10318 * The actual value is then formed by replacing any union type
10319 * definition in the ·explicit members· with the members of their
10320 * {member type definitions}, in order.
10321 */
10322 link = ctxtType->memberTypes;
10323 while (link != NULL) {
10324 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10325 subLink = link->type->memberTypes;
10326 if (subLink != NULL) {
10327 link->type = subLink->type;
10328 if (subLink->next != NULL) {
10329 lastLink = link->next;
10330 subLink = subLink->next;
10331 prevLink = link;
10332 while (subLink != NULL) {
10333 newLink = (xmlSchemaTypeLinkPtr)
10334 xmlMalloc(sizeof(xmlSchemaTypeLink));
10335 if (newLink == NULL) {
10336 xmlSchemaPErrMemory(ctxt, "allocating a type link",
10337 NULL);
10338 return (-1);
10339 }
10340 newLink->type = memberType;
10341 prevLink->next = newLink;
10342 prevLink = newLink;
10343 newLink->next = lastLink;
10344
10345 subLink = subLink->next;
10346 }
10347 }
10348 }
10349 }
10350 link = link->next;
10351 }
10352
10353 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000010354}
10355
Daniel Veillard4255d502002-04-16 15:50:10 +000010356/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010357 * xmlSchemaIsDerivedFromBuiltInType:
10358 * @ctxt: the schema parser context
10359 * @type: the type definition
10360 * @valType: the value type
10361 *
10362 *
10363 * Returns 1 if the type has the given value type, or
10364 * is derived from such a type.
10365 */
William M. Brack803812b2004-06-03 02:11:24 +000010366static int
Daniel Veillard3646d642004-06-02 19:19:14 +000010367xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
10368 xmlSchemaTypePtr type, int valType)
10369{
10370 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010371 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000010372 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010373 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000010374 return(1);
10375 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
10376 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
10377 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
10378 ((xmlSchemaAttributePtr) type)->subtypes, valType));
10379 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
10380 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
10381 if (type->baseType != NULL)
10382 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
10383 valType));
10384 } else if ((type->subtypes != NULL) &&
10385 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
10386 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10387 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
10388 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
10389 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
10390 valType));
10391 }
10392
10393 return (0);
10394}
10395
10396/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010397 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000010398 * @type: the simpleType definition
10399 *
10400 * Returns the primitive type of the given type or
10401 * NULL in case of error.
10402 */
10403static xmlSchemaTypePtr
10404xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
10405{
10406 while (type != NULL) {
10407 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
10408 return (type);
10409 type = type->baseType;
10410 }
10411
10412 return (NULL);
10413}
10414
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010415/**
10416 * xmlSchemaGetBuiltInTypeAncestor:
10417 * @type: the simpleType definition
10418 *
10419 * Returns the primitive type of the given type or
10420 * NULL in case of error.
10421 */
10422static xmlSchemaTypePtr
10423xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
10424{
10425 while (type != NULL) {
10426 if (type->type == XML_SCHEMA_TYPE_BASIC)
10427 return (type);
10428 type = type->baseType;
10429 }
10430
10431 return (NULL);
10432}
10433
Daniel Veillard01fa6152004-06-29 17:04:39 +000010434
10435/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010436 * xmlSchemaBuildAttributeUsesOwned:
10437 * @ctxt: the schema parser context
10438 * @type: the complex type definition
10439 * @cur: the attribute declaration list
10440 * @lastUse: the top of the attribute use list
10441 *
10442 * Builds the attribute uses list on the given complex type.
10443 * This one is supposed to be called by
10444 * xmlSchemaBuildAttributeValidation only.
10445 */
10446static int
10447xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
10448 xmlSchemaAttributePtr cur,
10449 xmlSchemaAttributeLinkPtr *uses,
10450 xmlSchemaAttributeLinkPtr *lastUse)
10451{
10452 xmlSchemaAttributeLinkPtr tmp;
10453 while (cur != NULL) {
10454 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10455 /*
10456 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
10457 * to by the ·actual value·s of the ref [attribute] of the
10458 * <attributeGroup> [children], if any."
10459 */
10460 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
10461 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
10462 lastUse) == -1) {
10463 return (-1);
10464 }
10465 } else {
10466 /* W3C: "1 The set of attribute uses corresponding to the
10467 * <attribute> [children], if any."
10468 */
10469 tmp = (xmlSchemaAttributeLinkPtr)
10470 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10471 if (tmp == NULL) {
10472 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
10473 return (-1);
10474 }
10475 tmp->attr = cur;
10476 tmp->next = NULL;
10477 if (*uses == NULL)
10478 *uses = tmp;
10479 else
10480 (*lastUse)->next = tmp;
10481 *lastUse = tmp;
10482 }
10483 cur = cur->next;
10484 }
10485 return (0);
10486}
10487
Daniel Veillard50355f02004-06-08 17:52:16 +000010488/**
10489 * xmlSchemaCloneWildcardNsConstraints:
10490 * @ctxt: the schema parser context
10491 * @dest: the destination wildcard
10492 * @source: the source wildcard
10493 *
10494 * Clones the namespace constraints of source
10495 * and assignes them to dest.
10496 * Returns -1 on internal error, 0 otherwise.
10497 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010498static int
10499xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
10500 xmlSchemaWildcardPtr *dest,
10501 xmlSchemaWildcardPtr source)
10502{
10503 xmlSchemaWildcardNsPtr cur, tmp, last;
10504
10505 if ((source == NULL) || (*dest == NULL))
10506 return(-1);
10507 (*dest)->any = source->any;
10508 cur = source->nsSet;
10509 last = NULL;
10510 while (cur != NULL) {
10511 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10512 if (tmp == NULL)
10513 return(-1);
10514 tmp->value = cur->value;
10515 if (last == NULL)
10516 (*dest)->nsSet = tmp;
10517 else
10518 last->next = tmp;
10519 last = tmp;
10520 cur = cur->next;
10521 }
10522 if ((*dest)->negNsSet != NULL)
10523 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
10524 if (source->negNsSet != NULL) {
10525 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10526 if ((*dest)->negNsSet == NULL)
10527 return(-1);
10528 (*dest)->negNsSet->value = source->negNsSet->value;
10529 } else
10530 (*dest)->negNsSet = NULL;
10531 return(0);
10532}
10533
Daniel Veillard50355f02004-06-08 17:52:16 +000010534/**
10535 * xmlSchemaUnionWildcards:
10536 * @ctxt: the schema parser context
10537 * @completeWild: the first wildcard
10538 * @curWild: the second wildcard
10539 *
10540 * Unions the namespace constraints of the given wildcards.
10541 * @completeWild will hold the resulting union.
10542 * Returns a positive error code on failure, -1 in case of an
10543 * internal error, 0 otherwise.
10544 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010545static int
10546xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
10547 xmlSchemaWildcardPtr completeWild,
10548 xmlSchemaWildcardPtr curWild)
10549{
10550 xmlSchemaWildcardNsPtr cur, curB, tmp;
10551
10552 /*
10553 * 1 If O1 and O2 are the same value, then that value must be the
10554 * value.
10555 */
10556 if ((completeWild->any == curWild->any) &&
10557 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10558 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10559
10560 if ((completeWild->negNsSet == NULL) ||
10561 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10562
10563 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010564 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010565
10566 /*
10567 * Check equality of sets.
10568 */
10569 cur = completeWild->nsSet;
10570 while (cur != NULL) {
10571 found = 0;
10572 curB = curWild->nsSet;
10573 while (curB != NULL) {
10574 if (cur->value == curB->value) {
10575 found = 1;
10576 break;
10577 }
10578 curB = curB->next;
10579 }
10580 if (!found)
10581 break;
10582 cur = cur->next;
10583 }
10584 if (found)
10585 return(0);
10586 } else
10587 return(0);
10588 }
10589 }
10590 /*
10591 * 2 If either O1 or O2 is any, then any must be the value
10592 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010593 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010594 if (completeWild->any == 0) {
10595 completeWild->any = 1;
10596 if (completeWild->nsSet != NULL) {
10597 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10598 completeWild->nsSet = NULL;
10599 }
10600 if (completeWild->negNsSet != NULL) {
10601 xmlFree(completeWild->negNsSet);
10602 completeWild->negNsSet = NULL;
10603 }
10604 }
Daniel Veillard50355f02004-06-08 17:52:16 +000010605 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010606 }
10607 /*
10608 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
10609 * then the union of those sets must be the value.
10610 */
10611 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10612 int found;
10613 xmlSchemaWildcardNsPtr start;
10614
10615 cur = curWild->nsSet;
10616 start = completeWild->nsSet;
10617 while (cur != NULL) {
10618 found = 0;
10619 curB = start;
10620 while (curB != NULL) {
10621 if (cur->value == curB->value) {
10622 found = 1;
10623 break;
10624 }
10625 curB = curB->next;
10626 }
10627 if (!found) {
10628 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10629 if (tmp == NULL)
10630 return (-1);
10631 tmp->value = cur->value;
10632 tmp->next = completeWild->nsSet;
10633 completeWild->nsSet = tmp;
10634 }
10635 cur = cur->next;
10636 }
10637
10638 return(0);
10639 }
10640 /*
10641 * 4 If the two are negations of different values (namespace names
10642 * or ·absent·), then a pair of not and ·absent· must be the value.
10643 */
10644 if ((completeWild->negNsSet != NULL) &&
10645 (curWild->negNsSet != NULL) &&
10646 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
10647 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000010648
10649 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010650 }
10651 /*
10652 * 5.
10653 */
10654 if (((completeWild->negNsSet != NULL) &&
10655 (completeWild->negNsSet->value != NULL) &&
10656 (curWild->nsSet != NULL)) ||
10657 ((curWild->negNsSet != NULL) &&
10658 (curWild->negNsSet->value != NULL) &&
10659 (completeWild->nsSet != NULL))) {
10660
10661 int nsFound, absentFound = 0;
10662
10663 if (completeWild->nsSet != NULL) {
10664 cur = completeWild->nsSet;
10665 curB = curWild->negNsSet;
10666 } else {
10667 cur = curWild->nsSet;
10668 curB = completeWild->negNsSet;
10669 }
10670 nsFound = 0;
10671 while (cur != NULL) {
10672 if (cur->value == NULL)
10673 absentFound = 1;
10674 else if (cur->value == curB->value)
10675 nsFound = 1;
10676 if (nsFound && absentFound)
10677 break;
10678 cur = cur->next;
10679 }
10680
10681 if (nsFound && absentFound) {
10682 /*
10683 * 5.1 If the set S includes both the negated namespace
10684 * name and ·absent·, then any must be the value.
10685 */
10686 completeWild->any = 1;
10687 if (completeWild->nsSet != NULL) {
10688 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10689 completeWild->nsSet = NULL;
10690 }
10691 if (completeWild->negNsSet != NULL) {
10692 xmlFree(completeWild->negNsSet);
10693 completeWild->negNsSet = NULL;
10694 }
10695 } else if (nsFound && (!absentFound)) {
10696 /*
10697 * 5.2 If the set S includes the negated namespace name
10698 * but not ·absent·, then a pair of not and ·absent· must
10699 * be the value.
10700 */
10701 if (completeWild->nsSet != NULL) {
10702 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10703 completeWild->nsSet = NULL;
10704 }
10705 if (completeWild->negNsSet == NULL) {
10706 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10707 if (completeWild->negNsSet == NULL)
10708 return (-1);
10709 }
10710 completeWild->negNsSet->value = NULL;
10711 } else if ((!nsFound) && absentFound) {
10712 /*
10713 * 5.3 If the set S includes ·absent· but not the negated
10714 * namespace name, then the union is not expressible.
10715 */
10716 xmlSchemaPErr(ctxt, completeWild->node,
10717 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010718 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010719 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010720 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010721 } else if ((!nsFound) && (!absentFound)) {
10722 /*
10723 * 5.4 If the set S does not include either the negated namespace
10724 * name or ·absent·, then whichever of O1 or O2 is a pair of not
10725 * and a namespace name must be the value.
10726 */
10727 if (completeWild->negNsSet == NULL) {
10728 if (completeWild->nsSet != NULL) {
10729 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10730 completeWild->nsSet = NULL;
10731 }
10732 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10733 if (completeWild->negNsSet == NULL)
10734 return (-1);
10735 completeWild->negNsSet->value = curWild->negNsSet->value;
10736 }
10737 }
10738 return (0);
10739 }
10740 /*
10741 * 6.
10742 */
10743 if (((completeWild->negNsSet != NULL) &&
10744 (completeWild->negNsSet->value == NULL) &&
10745 (curWild->nsSet != NULL)) ||
10746 ((curWild->negNsSet != NULL) &&
10747 (curWild->negNsSet->value == NULL) &&
10748 (completeWild->nsSet != NULL))) {
10749
10750 if (completeWild->nsSet != NULL) {
10751 cur = completeWild->nsSet;
10752 } else {
10753 cur = curWild->nsSet;
10754 }
10755 while (cur != NULL) {
10756 if (cur->value == NULL) {
10757 /*
10758 * 6.1 If the set S includes ·absent·, then any must be the
10759 * value.
10760 */
10761 completeWild->any = 1;
10762 if (completeWild->nsSet != NULL) {
10763 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10764 completeWild->nsSet = NULL;
10765 }
10766 if (completeWild->negNsSet != NULL) {
10767 xmlFree(completeWild->negNsSet);
10768 completeWild->negNsSet = NULL;
10769 }
10770 return (0);
10771 }
10772 cur = cur->next;
10773 }
10774 if (completeWild->negNsSet == NULL) {
10775 /*
10776 * 6.2 If the set S does not include ·absent·, then a pair of not
10777 * and ·absent· must be the value.
10778 */
10779 if (completeWild->nsSet != NULL) {
10780 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10781 completeWild->nsSet = NULL;
10782 }
10783 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10784 if (completeWild->negNsSet == NULL)
10785 return (-1);
10786 completeWild->negNsSet->value = NULL;
10787 }
10788 return (0);
10789 }
10790 return (0);
10791
10792}
10793
Daniel Veillard50355f02004-06-08 17:52:16 +000010794/**
10795 * xmlSchemaIntersectWildcards:
10796 * @ctxt: the schema parser context
10797 * @completeWild: the first wildcard
10798 * @curWild: the second wildcard
10799 *
10800 * Intersects the namespace constraints of the given wildcards.
10801 * @completeWild will hold the resulting intersection.
10802 * Returns a positive error code on failure, -1 in case of an
10803 * internal error, 0 otherwise.
10804 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010805static int
10806xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
10807 xmlSchemaWildcardPtr completeWild,
10808 xmlSchemaWildcardPtr curWild)
10809{
William M. Brack803812b2004-06-03 02:11:24 +000010810 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010811
10812 /*
10813 * 1 If O1 and O2 are the same value, then that value must be the
10814 * value.
10815 */
10816 if ((completeWild->any == curWild->any) &&
10817 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10818 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10819
10820 if ((completeWild->negNsSet == NULL) ||
10821 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10822
10823 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010824 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010825
10826 /*
10827 * Check equality of sets.
10828 */
10829 cur = completeWild->nsSet;
10830 while (cur != NULL) {
10831 found = 0;
10832 curB = curWild->nsSet;
10833 while (curB != NULL) {
10834 if (cur->value == curB->value) {
10835 found = 1;
10836 break;
10837 }
10838 curB = curB->next;
10839 }
10840 if (!found)
10841 break;
10842 cur = cur->next;
10843 }
10844 if (found)
10845 return(0);
10846 } else
10847 return(0);
10848 }
10849 }
10850 /*
10851 * 2 If either O1 or O2 is any, then the other must be the value.
10852 */
10853 if ((completeWild->any != curWild->any) && (completeWild->any)) {
10854 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10855 return(-1);
10856 return(0);
10857 }
10858 /*
10859 * 3 If either O1 or O2 is a pair of not and a value (a namespace
10860 * name or ·absent·) and the other is a set of (namespace names or
10861 * ·absent·), then that set, minus the negated value if it was in
10862 * the set, minus ·absent· if it was in the set, must be the value.
10863 */
10864 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
10865 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
10866 const xmlChar *neg;
10867
10868 if (completeWild->nsSet == NULL) {
10869 neg = completeWild->negNsSet->value;
10870 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10871 return(-1);
10872 } else
10873 neg = curWild->negNsSet->value;
10874 /*
10875 * Remove absent and negated.
10876 */
10877 prev = NULL;
10878 cur = completeWild->nsSet;
10879 while (cur != NULL) {
10880 if (cur->value == NULL) {
10881 if (prev == NULL)
10882 completeWild->nsSet = cur->next;
10883 else
10884 prev->next = cur->next;
10885 xmlFree(cur);
10886 break;
10887 }
10888 prev = cur;
10889 cur = cur->next;
10890 }
10891 if (neg != NULL) {
10892 prev = NULL;
10893 cur = completeWild->nsSet;
10894 while (cur != NULL) {
10895 if (cur->value == neg) {
10896 if (prev == NULL)
10897 completeWild->nsSet = cur->next;
10898 else
10899 prev->next = cur->next;
10900 xmlFree(cur);
10901 break;
10902 }
10903 prev = cur;
10904 cur = cur->next;
10905 }
10906 }
10907
10908 return(0);
10909 }
10910 /*
10911 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
10912 * then the intersection of those sets must be the value.
10913 */
10914 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10915 int found;
10916
10917 cur = completeWild->nsSet;
10918 prev = NULL;
10919 while (cur != NULL) {
10920 found = 0;
10921 curB = curWild->nsSet;
10922 while (curB != NULL) {
10923 if (cur->value == curB->value) {
10924 found = 1;
10925 break;
10926 }
10927 curB = curB->next;
10928 }
10929 if (!found) {
10930 if (prev == NULL)
10931 completeWild->nsSet = cur->next;
10932 else
10933 prev->next = cur->next;
10934 tmp = cur->next;
10935 xmlFree(cur);
10936 cur = tmp;
10937 continue;
10938 }
10939 prev = cur;
10940 cur = cur->next;
10941 }
10942
10943 return(0);
10944 }
10945 /* 5 If the two are negations of different namespace names,
10946 * then the intersection is not expressible
10947 */
10948 if ((completeWild->negNsSet != NULL) &&
10949 (curWild->negNsSet != NULL) &&
10950 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
10951 (completeWild->negNsSet->value != NULL) &&
10952 (curWild->negNsSet->value != NULL)) {
10953
10954 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010955 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010956 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010957 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010958 }
10959 /*
10960 * 6 If the one is a negation of a namespace name and the other
10961 * is a negation of ·absent·, then the one which is the negation
10962 * of a namespace name must be the value.
10963 */
10964 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
10965 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
10966 (completeWild->negNsSet->value == NULL)) {
10967 completeWild->negNsSet->value = curWild->negNsSet->value;
10968 }
10969 return(0);
10970}
10971
Daniel Veillard50355f02004-06-08 17:52:16 +000010972/**
10973 * xmlSchemaIsWildcardNsConstraintSubset:
10974 * @ctxt: the schema parser context
10975 * @wildA: the first wildcard
10976 * @wildB: the second wildcard
10977 *
10978 * Returns 1 if the namespace constraint of @wildA is an intensional
10979 * subset of @wildB, 0 otherwise.
10980 */
10981static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000010982xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
10983 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000010984{
Daniel Veillard3646d642004-06-02 19:19:14 +000010985
Daniel Veillard50355f02004-06-08 17:52:16 +000010986 /*
10987 * Schema Component Constraint: Wildcard Subset
10988 */
10989 /*
10990 * 1 super must be any.
10991 */
10992 if (wildB->any)
10993 return (1);
10994 /*
10995 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
10996 * 2.2 super must be a pair of not and the same value.
10997 */
10998 if ((wildA->negNsSet != NULL) &&
10999 (wildB->negNsSet != NULL) &&
11000 (wildA->negNsSet->value == wildA->negNsSet->value))
11001 return (1);
11002 /*
11003 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
11004 */
11005 if (wildA->nsSet != NULL) {
11006 /*
11007 * 3.2.1 super must be the same set or a superset thereof.
11008 */
11009 if (wildB->nsSet != NULL) {
11010 xmlSchemaWildcardNsPtr cur, curB;
11011 int found = 0;
11012
11013 cur = wildA->nsSet;
11014 while (cur != NULL) {
11015 found = 0;
11016 curB = wildB->nsSet;
11017 while (curB != NULL) {
11018 if (cur->value == curB->value) {
11019 found = 1;
11020 break;
11021 }
11022 curB = curB->next;
11023 }
11024 if (!found)
11025 return (0);
11026 cur = cur->next;
11027 }
11028 if (found)
11029 return (1);
11030 } else if (wildB->negNsSet != NULL) {
11031 xmlSchemaWildcardNsPtr cur;
11032 /*
11033 * 3.2.2 super must be a pair of not and a namespace name or
11034 * ·absent· and that value must not be in sub's set.
11035 */
11036 cur = wildA->nsSet;
11037 while (cur != NULL) {
11038 if (cur->value == wildB->negNsSet->value)
11039 return (0);
11040 cur = cur->next;
11041 }
11042 return (1);
11043 }
11044 }
11045 return (0);
11046}
11047
11048/**
11049 * xmlSchemaBuildCompleteAttributeWildcard:
11050 * @ctxt: the schema parser context
11051 * @attrs: the attribute list
11052 * @completeWild: the resulting complete wildcard
11053 *
11054 * Returns -1 in case of an internal error, 0 otherwise.
11055 */
11056static int
11057xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
11058 xmlSchemaAttributePtr attrs,
11059 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000011060{
11061 while (attrs != NULL) {
11062 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
11063 xmlSchemaAttributeGroupPtr group;
11064
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011065 group = (xmlSchemaAttributeGroupPtr) attrs;
11066 /*
11067 * Handle attribute group references.
11068 */
11069 if (group->ref != NULL) {
11070 if (group->refItem == NULL) {
11071 /*
11072 * TODO: Should we raise a warning here?
11073 */
11074 /*
11075 * The referenced attribute group definition could not
11076 * be resolved beforehand, so skip.
11077 */
11078 attrs = attrs->next;
11079 continue;
11080 } else
11081 group = group->refItem;
11082 }
11083 /*
11084 * For every attribute group definition, an intersected wildcard
11085 * will be created (assumed that a wildcard exists on the
11086 * particular attr. gr. def. or on any contained attr. gr. def
11087 * at all).
11088 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
11089 * that the intersection will be performed only once.
11090 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011091 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
11092 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000011093 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11094 group->attributes, &group->attributeWildcard) == -1)
11095 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011096 }
11097 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
11098 }
11099 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000011100 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011101 /*
11102 * Copy the first encountered wildcard as context, except for the annotation.
11103 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011104 *completeWild = xmlSchemaAddWildcard(ctxt);
11105 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
11106 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
11107 completeWild, group->attributeWildcard) == -1)
11108 return (-1);
11109 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000011110 /*
11111 * Although the complete wildcard might not correspond to any
11112 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011113 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000011114 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011115 (*completeWild)->node = group->attributeWildcard->node;
11116
11117 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
11118 xmlSchemaFreeWildcard(*completeWild);
11119 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011120 }
11121 }
11122 }
11123 attrs = attrs->next;
11124 }
11125
Daniel Veillard50355f02004-06-08 17:52:16 +000011126 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011127}
11128
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011129static int
11130xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
11131 int *fixed,
11132 const xmlChar **value,
11133 xmlSchemaValPtr *val)
11134{
11135 *fixed = 0;
11136 *value = NULL;
11137 if (val != 0)
11138 *val = NULL;
11139
11140 if (item->defValue == NULL)
11141 item = item->refDecl;
11142
11143 if (item == NULL)
11144 return (0);
11145
11146 if (item->defValue != NULL) {
11147 *value = item->defValue;
11148 if (val != 0)
11149 *val = item->defVal;
11150 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
11151 *fixed = 1;
11152 return (1);
11153 }
11154 return (0);
11155}
Daniel Veillard3646d642004-06-02 19:19:14 +000011156/**
11157 * xmlSchemaMatchesWildcardNs:
11158 * @wild: the wildcard
11159 * @ns: the namespace
11160 *
11161 *
11162 * Returns 1 if the given namespace matches the wildcard,
11163 * 0 otherwise.
11164 */
11165static int
11166xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
11167{
11168 if (wild == NULL)
11169 return(0);
11170
11171 if (wild->any)
11172 return(1);
11173 else if (wild->nsSet != NULL) {
11174 xmlSchemaWildcardNsPtr cur;
11175
11176 cur = wild->nsSet;
11177 while (cur != NULL) {
11178 if (xmlStrEqual(cur->value, ns))
11179 return(1);
11180 cur = cur->next;
11181 }
11182 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
11183 (!xmlStrEqual(wild->negNsSet->value, ns)))
11184 return(1);
11185
11186 return(0);
11187}
11188
11189/**
11190 * xmlSchemaBuildAttributeValidation:
11191 * @ctxt: the schema parser context
11192 * @type: the complex type definition
11193 *
11194 *
11195 * Builds the wildcard and the attribute uses on the given complex type.
11196 * Returns -1 if an internal error occurs, 0 otherwise.
11197 */
11198static int
11199xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
11200{
11201 xmlSchemaTypePtr baseType = NULL;
11202 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000011203 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000011204 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011205 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000011206 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011207 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011208 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011209
Daniel Veillard01fa6152004-06-29 17:04:39 +000011210 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011211 /*
11212 * Complex Type Definition with complex content Schema Component.
11213 *
11214 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011215 * TODO: Add checks for absent referenced attribute declarations and
11216 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000011217 */
11218 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011219 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011220 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000011221 "attribute uses already builded.\n",
11222 NULL, NULL);
11223 return (-1);
11224 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011225 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011226 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011227 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011228 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011229 type->name, NULL);
11230 return (-1);
11231 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011232 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011233 if (baseType == anyType)
11234 baseIsAnyType = 1;
11235 /*
11236 * Inherit the attribute uses of the base type.
11237 */
11238 /*
11239 * NOTE: It is allowed to "extend" the anyType complex type.
11240 */
11241 if (!baseIsAnyType) {
11242 if (baseType != NULL) {
11243 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
11244 tmp = (xmlSchemaAttributeLinkPtr)
11245 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11246 if (tmp == NULL) {
11247 xmlSchemaPErrMemory(ctxt,
11248 "building attribute uses of complexType", NULL);
11249 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011250 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011251 tmp->attr = cur->attr;
11252 tmp->next = NULL;
11253 if (type->attributeUses == NULL) {
11254 type->attributeUses = tmp;
11255 } else
11256 lastBaseUse->next = tmp;
11257 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011258 }
11259 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011260 }
11261 if ((type->subtypes != NULL) &&
11262 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11263 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011264 /*
11265 * type --> (<simpleContent>|<complexContent>)
11266 * --> (<restriction>|<extension>) --> attributes
11267 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011268 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011269 } else {
11270 /* Short hand form of the complexType. */
11271 attrs = type->attributes;
11272 }
11273 /*
11274 * Handle attribute wildcards.
11275 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011276 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11277 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011278 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011279 * NOTE: During the parse time, the wildcard is created on the complexType
11280 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011281 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011282 if (err == -1) {
11283 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
11284 "Internal error: xmlSchemaBuildAttributeValidation: "
11285 "failed to build an intersected attribute wildcard.\n",
11286 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011287 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011288 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011289
11290 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
11291 ((baseIsAnyType) ||
11292 ((baseType != NULL) &&
11293 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11294 (baseType->attributeWildcard != NULL)))) {
11295 if (type->attributeWildcard != NULL) {
11296 /*
11297 * Union the complete wildcard with the base wildcard.
11298 */
11299 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
11300 baseType->attributeWildcard) == -1)
11301 return (-1);
11302 } else {
11303 /*
11304 * Just inherit the wildcard.
11305 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011306 /*
11307 * NOTE: This is the only case where an attribute
11308 * wildcard is shared.
11309 */
11310 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
11311 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011312 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000011313 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011314 }
11315
11316 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11317 if (type->attributeWildcard != NULL) {
11318 /*
11319 * Derivation Valid (Restriction, Complex)
11320 * 4.1 The {base type definition} must also have one.
11321 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011322 if (baseType->attributeWildcard == NULL) {
11323 xmlSchemaPCustomErr(ctxt,
11324 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
11325 NULL, type, NULL,
11326 "The type has an attribute wildcard, "
11327 "but the base type %s does not have one",
11328 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11329 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011330 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011331 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011332 type->attributeWildcard, baseType->attributeWildcard) == 0) {
11333 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011334 xmlSchemaPCustomErr(ctxt,
11335 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
11336 NULL, type, NULL,
11337 "The attribute wildcard is not a valid "
11338 "subset of the wildcard in the base type %s",
11339 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11340 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011341 return (1);
11342 }
11343 /* 4.3 Unless the {base type definition} is the ·ur-type
11344 * definition·, the complex type definition's {attribute
11345 * wildcard}'s {process contents} must be identical to or
11346 * stronger than the {base type definition}'s {attribute
11347 * wildcard}'s {process contents}, where strict is stronger
11348 * than lax is stronger than skip.
11349 */
11350 if ((type->baseType != anyType) &&
11351 (type->attributeWildcard->processContents <
11352 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011353 xmlSchemaPCustomErr(ctxt,
11354 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
11355 NULL, type, NULL,
11356 "The 'process contents' of the attribute wildcard is weaker than "
11357 "the one in the base type %s",
11358 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11359 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011360 return (1);
11361 }
11362 }
11363 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11364 /*
11365 * Derivation Valid (Extension)
11366 * At this point the type and the base have both, either
11367 * no wildcard or a wildcard.
11368 */
11369 if ((baseType->attributeWildcard != NULL) &&
11370 (baseType->attributeWildcard != type->attributeWildcard)) {
11371 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011372 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011373 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011374 xmlSchemaPCustomErr(ctxt,
11375 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
11376 NULL, type, NULL,
11377 "The attribute wildcard is not a valid "
11378 "superset of the one in the base type %s",
11379 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11380 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011381 return (1);
11382 }
11383 }
11384 }
11385
Daniel Veillard3646d642004-06-02 19:19:14 +000011386 /*
11387 * Gather attribute uses defined by this type.
11388 */
11389 if (attrs != NULL) {
11390 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
11391 &uses, &lastUse) == -1) {
11392 return (-1);
11393 }
11394 }
11395 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
11396 * "Two distinct attribute declarations in the {attribute uses} must
11397 * not have identical {name}s and {target namespace}s."
11398 *
11399 * For "extension" this is done further down.
11400 */
11401 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
11402 cur = uses;
11403 while (cur != NULL) {
11404 tmp = cur->next;
11405 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011406 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11407 xmlSchemaGetAttrName(tmp->attr))) &&
11408 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11409 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
11410
11411 xmlSchemaPAttrUseErr(ctxt,
11412 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11413 NULL, type, NULL, cur->attr,
11414 "Duplicate attribute use %s specified",
11415 xmlSchemaFormatNsUriLocal(&str,
11416 xmlSchemaGetAttrTargetNsURI(tmp->attr),
11417 xmlSchemaGetAttrName(tmp->attr))
11418 );
11419 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011420 break;
11421 }
11422 tmp = tmp->next;
11423 }
11424 cur = cur->next;
11425 }
11426 }
11427 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11428 /*
11429 * Derive by restriction.
11430 */
11431 if (baseIsAnyType) {
11432 type->attributeUses = uses;
11433 } else {
11434 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011435 const xmlChar *bEffValue;
11436 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000011437
11438 cur = uses;
11439 while (cur != NULL) {
11440 found = 0;
11441 base = type->attributeUses;
11442 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011443 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11444 xmlSchemaGetAttrName(base->attr)) &&
11445 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
11446 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011447
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011448 found = 1;
11449
Daniel Veillard3646d642004-06-02 19:19:14 +000011450 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
11451 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11452 /*
11453 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000011454 */
11455 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011456 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011457 NULL, type, NULL, cur->attr,
11458 "The 'optional' use is inconsistent with a matching "
11459 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011460 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
11461 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11462 /*
11463 * derivation-ok-restriction 3
11464 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011465 xmlSchemaPCustomErr(ctxt,
11466 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
11467 NULL, type, NULL,
11468 "A matching attribute use for the 'required' "
11469 "attribute use %s of the base type is missing",
11470 xmlSchemaFormatNsUriLocal(&str,
11471 xmlSchemaGetAttrTargetNsURI(base->attr),
11472 xmlSchemaGetAttrName(base->attr)));
11473 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011474 } else {
11475 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011476 * 2.1.3 [Definition:] Let the effective value
11477 * constraint of an attribute use be its {value
11478 * constraint}, if present, otherwise its {attribute
11479 * declaration}'s {value constraint} .
11480 */
11481 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11482 &bEffValue, 0);
11483 /*
11484 * 2.1.3 ... one of the following must be true
11485 *
11486 * 2.1.3.1 B's ·effective value constraint· is
11487 * ·absent· or default.
11488 */
11489 if ((bEffValue != NULL) &&
11490 (effFixed == 1)) {
11491 const xmlChar *rEffValue = NULL;
11492
11493 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11494 &rEffValue, 0);
11495 /*
11496 * 2.1.3.2 R's ·effective value constraint· is
11497 * fixed with the same string as B's.
11498 */
11499 if ((effFixed == 0) ||
11500 (! xmlStrEqual(rEffValue, bEffValue))) {
11501 xmlSchemaPAttrUseErr(ctxt,
11502 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
11503 NULL, type, NULL, cur->attr,
11504 "The effective value constraint of the "
11505 "attribute use is inconsistent with "
11506 "its correspondent of the base type",
11507 NULL);
11508 }
11509 }
11510 /*
11511 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
11512 */
11513 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011514 * Override the attribute use.
11515 */
11516 base->attr = cur->attr;
11517 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011518
Daniel Veillard3646d642004-06-02 19:19:14 +000011519 break;
11520 }
11521 base = base->next;
11522 }
11523
11524 if (!found) {
11525 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11526 /*
11527 * derivation-ok-restriction 2.2
11528 */
11529 if ((type->attributeWildcard != NULL) &&
11530 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
11531 cur->attr->targetNamespace))
11532 found = 1;
11533
11534 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011535 xmlSchemaPAttrUseErr(ctxt,
11536 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
11537 NULL, type, NULL, cur->attr,
11538 "Neither a matching attribute use, "
11539 "nor a matching wildcard in the base type does exist",
11540 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011541 } else {
11542 /*
11543 * Add the attribute use.
11544 *
11545 * Note that this may lead to funny derivation error reports, if
11546 * multiple equal attribute uses exist; but this is not
11547 * allowed anyway, and it will be reported beforehand.
11548 */
11549 tmp = cur;
11550 if (prev != NULL)
11551 prev->next = cur->next;
11552 else
11553 uses = cur->next;
11554 cur = cur->next;
11555 if (type->attributeUses == NULL) {
11556 type->attributeUses = tmp;
11557 } else
11558 lastBaseUse->next = tmp;
11559 lastBaseUse = tmp;
11560
11561 continue;
11562 }
11563 }
11564 }
11565 prev = cur;
11566 cur = cur->next;
11567 }
11568 if (uses != NULL)
11569 xmlSchemaFreeAttributeUseList(uses);
11570 }
11571 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11572 /*
11573 * The spec allows only appending, and not other kinds of extensions.
11574 *
11575 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
11576 */
11577 if (uses != NULL) {
11578 if (type->attributeUses == NULL) {
11579 type->attributeUses = uses;
11580 } else
11581 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011582 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011583 } else {
11584 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000011585 * Derive implicitely from the ur-type.
11586 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011587 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011588 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011589 /*
11590 * 3.4.6 -> Complex Type Definition Properties Correct
11591 */
11592 if (type->attributeUses != NULL) {
11593 cur = type->attributeUses;
11594 prev = NULL;
11595 while (cur != NULL) {
11596 /*
11597 * 4. Two distinct attribute declarations in the {attribute uses} must
11598 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000011599 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011600 * Note that this was already done for "restriction" and types derived from
11601 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000011602 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011603 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11604 tmp = cur->next;
11605 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011606 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11607 xmlSchemaGetAttrName(tmp->attr))) &&
11608 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11609 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011610
Daniel Veillardc0826a72004-08-10 14:17:33 +000011611 xmlSchemaPAttrUseErr(ctxt,
11612 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11613 NULL, type, NULL, tmp->attr,
11614 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011615 break;
11616 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011617 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011618 }
11619 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011620 /*
11621 * 5. Two distinct attribute declarations in the {attribute uses} must
11622 * not have {type definition}s which are or are derived from ID.
11623 */
11624 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000011625 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011626 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011627 xmlSchemaPAttrUseErr(ctxt,
11628 XML_SCHEMAP_CT_PROPS_CORRECT_5,
11629 NULL, type, NULL, cur->attr,
11630 "There must not exist more than one attribute use, "
11631 "declared of type 'ID' or derived from it",
11632 NULL);
11633 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000011634 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011635 id = cur;
11636 }
11637 /*
11638 * Remove "prohibited" attribute uses. The reason this is done at this late
11639 * stage is to be able to catch dublicate attribute uses. So we had to keep
11640 * prohibited uses in the list as well.
11641 */
11642 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11643 tmp = cur;
11644 if (prev == NULL)
11645 type->attributeUses = cur->next;
11646 else
11647 prev->next = cur->next;
11648 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011649 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000011650 } else {
11651 prev = cur;
11652 cur = cur->next;
11653 }
11654 }
11655 }
11656 /*
11657 * TODO: This check should be removed if we are 100% sure of
11658 * the base type attribute uses already being built.
11659 */
11660 if ((baseType != NULL) && (!baseIsAnyType) &&
11661 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11662 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011663 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011664 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011665 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011666 baseType->name, NULL);
11667 }
11668 return (0);
11669}
11670
11671/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000011672 * xmlSchemaTypeFinalContains:
11673 * @schema: the schema
11674 * @type: the type definition
11675 * @final: the final
11676 *
11677 * Evaluates if a type definition contains the given "final".
11678 * This does take "finalDefault" into account as well.
11679 *
11680 * Returns 1 if the type does containt the given "final",
11681 * 0 otherwise.
11682 */
11683static int
11684xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
11685{
11686 int tfinal = final, tflags = type->flags;
11687
11688 if (type == NULL)
11689 return (0);
11690 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
11691 switch (final) {
11692 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
11693 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
11694 break;
11695 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
11696 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
11697 break;
11698 case XML_SCHEMAS_TYPE_FINAL_LIST:
11699 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
11700 break;
11701 case XML_SCHEMAS_TYPE_FINAL_UNION:
11702 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
11703 break;
11704 }
11705 tflags = schema->flags;
11706 }
11707 if (tflags & tfinal)
11708 return (1);
11709 else
11710 return (0);
11711
11712}
11713
11714/**
11715 * xmlSchemaGetUnionSimpleTypeMemberTypes:
11716 * @type: the Union Simple Type
11717 *
11718 * Returns a list of member types of @type if existing,
11719 * returns NULL otherwise.
11720 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011721static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000011722xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
11723{
11724 while (type != NULL) {
11725 if (type->memberTypes != NULL)
11726 return (type->memberTypes);
11727 else
11728 type = type->baseType;
11729 }
11730 return (NULL);
11731}
11732
11733/**
11734 * xmlSchemaGetListSimpleTypeItemType:
11735 * @type: the simple type definition
11736 *
11737 * Returns the item type definition of the list simple type.
11738 */
11739static xmlSchemaTypePtr
11740xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
11741{
11742 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
11743 return (NULL);
11744 /*
11745 * Note: In libxml2, the built-in types do not reflect
11746 * the datatype hierarchy (yet?) - we have to treat them
11747 * in a special way.
11748 */
11749 if (type->type == XML_SCHEMA_TYPE_BASIC)
11750 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
11751 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
11752 /* 1 If the <list> alternative is chosen, then the type
11753 * definition ·resolved· to by the ·actual value· of the
11754 * itemType [attribute] of <list>, if present, otherwise
11755 * the type definition corresponding to the <simpleType>
11756 * among the [children] of <list>.
11757 */
11758 return (type->subtypes->subtypes);
11759 else {
11760 /* 2 If the <restriction> option is chosen, then the
11761 * {item type definition} of the {base type definition}.
11762 */
11763 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
11764 }
11765}
11766
11767/**
11768 * xmlSchemaCheckCOSSTDerivedOK:
11769 * @type: the derived simple type definition
11770 * @baseType: the base type definition
11771 *
11772 * Checks wheter @type can be validly
11773 * derived from @baseType.
11774 *
11775 * Returns 0 on success, an positive error code otherwise.
11776 */
11777static int
11778xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
11779 xmlSchemaTypePtr type,
11780 xmlSchemaTypePtr baseType,
11781 int subset)
11782{
11783 /*
11784 * Schema Component Constraint: Type Derivation OK (Simple)
11785 *
11786 *
11787 * 1 They are the same type definition.
11788 * TODO: The identy check might have to be more complex than this.
11789 */
11790 if (type == baseType)
11791 return (0);
11792 /*
11793 * 2.1 restriction is not in the subset, or in the {final}
11794 * of its own {base type definition};
11795 */
11796 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
11797 (xmlSchemaTypeFinalContains(schema,
11798 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
11799 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
11800 }
11801 /* 2.2 */
11802 if (type->baseType == baseType) {
11803 /*
11804 * 2.2.1 D's ·base type definition· is B.
11805 */
11806 return (0);
11807 }
11808 /*
11809 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
11810 * and is validly derived from B given the subset, as defined by this
11811 * constraint.
11812 */
11813 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
11814 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
11815 return (0);
11816 }
11817 /*
11818 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
11819 * definition·.
11820 */
11821 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
11822 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
11823 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
11824 return (0);
11825 }
11826 /*
11827 * 2.2.4 B's {variety} is union and D is validly derived from a type
11828 * definition in B's {member type definitions} given the subset, as
11829 * defined by this constraint.
11830 *
11831 * NOTE: This seems not to involve built-in types, since there is no
11832 * built-in Union Simple Type.
11833 */
11834 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11835 xmlSchemaTypeLinkPtr cur;
11836
11837 cur = baseType->memberTypes;
11838 while (cur != NULL) {
11839 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
11840 cur->type, subset) == 0)
11841 return (0);
11842 cur = cur->next;
11843 }
11844 }
11845
11846 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
11847}
11848
11849
11850/**
11851 * xmlSchemaCheckSTPropsCorrect:
11852 * @ctxt: the schema parser context
11853 * @type: the simple type definition
11854 *
11855 * Checks st-props-correct.
11856 *
11857 * Returns 0 if the properties are correct,
11858 * if not, a positive error code and -1 on internal
11859 * errors.
11860 */
11861static int
11862xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
11863 xmlSchemaTypePtr type)
11864{
11865 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
11866 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011867 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011868
Daniel Veillardc0826a72004-08-10 14:17:33 +000011869 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011870 /*
11871 * Schema Component Constraint: Simple Type Definition Properties Correct
11872 *
11873 * NOTE: This is somehow redundant, since we actually built a simple type
11874 * to have all the needed information; this acts as an self test.
11875 */
11876 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11877 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11878 /*
11879 * TODO: 1 The values of the properties of a simple type definition must be as
11880 * described in the property tableau in Datatype definition, modulo the
11881 * impact of Missing Sub-components (§5.3).
11882 */
11883 /* Base type: If the datatype has been ·derived· by ·restriction·
11884 * then the Simple Type Definition component from which it is ·derived·,
11885 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
11886 */
11887 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011888 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011889 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011890 NULL, type, NULL,
11891 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011892 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11893 }
11894 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
11895 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
11896 (baseType == anyType))) {
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 base type %s is not a simple type",
11901 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11902 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011903 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11904 }
11905 if ((baseType != anySimpleType) &&
11906 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011907 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011908 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011909 NULL, type, NULL,
11910 "A type, derived by list or union, must have"
11911 "the simple ur-type definition as base type, not %s",
11912 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11913 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011914 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11915 }
11916 /*
11917 * Variety: One of {atomic, list, union}.
11918 */
11919 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11920 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
11921 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011922 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011923 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011924 NULL, type, NULL,
11925 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011926 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11927 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011928 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011929
11930 /*
11931 * 2 All simple type definitions must be derived ultimately from the ·simple
11932 * ur-type definition (so· circular definitions are disallowed). That is, it
11933 * must be possible to reach a built-in primitive datatype or the ·simple
11934 * ur-type definition· by repeatedly following the {base type definition}.
11935 */
11936 baseType = type->baseType;
11937 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
11938 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11939 xmlSchemaTypeFixup(baseType, ctxt, NULL);
11940 if (baseType == anySimpleType)
11941 break;
11942 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011943 xmlSchemaPCustomErr(ctxt,
11944 XML_SCHEMAP_ST_PROPS_CORRECT_2,
11945 NULL, type, NULL,
11946 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011947 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
11948 }
11949 baseType = baseType->baseType;
11950 }
11951 /*
11952 * 3 The {final} of the {base type definition} must not contain restriction.
11953 */
11954 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
11955 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011956 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011957 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011958 NULL, type, NULL,
11959 "The 'final' of its base type %s must not contain "
11960 "'restriction'",
11961 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11962 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011963 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
11964 }
11965 return (0);
11966}
11967
11968/**
11969 * xmlSchemaCheckDerivationValidSimpleRestriction:
11970 * @ctxt: the schema parser context
11971 * @type: the simple type definition
11972 *
11973 * Checks if the given @type (simpleType) is derived
11974 * validly by restriction.
11975 *
11976 * Returns -1 on internal errors, 0 if the type is validly derived,
11977 * a positive error code otherwise.
11978 */
11979static int
11980xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011981 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011982{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011983 xmlChar *str = NULL;
11984
11985 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011986
11987 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
11988 xmlSchemaPErr(ctxt, type->node,
11989 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011990 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
11991 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011992 type->name, NULL);
11993 return (-1);
11994 }
11995
11996 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
11997 xmlSchemaTypePtr primitive;
11998 /*
11999 * 1.1 The {base type definition} must be an atomic simple
12000 * type definition or a built-in primitive datatype.
12001 */
12002 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012003 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012004 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012005 NULL, type, NULL,
12006 "The base type %s is not an atomic simple type",
12007 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12008 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012009 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
12010 }
12011 /* 1.2 The {final} of the {base type definition} must not contain
12012 * restriction.
12013 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012014 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012015 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12016 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012017 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012018 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012019 NULL, type, NULL,
12020 "The final of its base type %s must not contain 'restriction'",
12021 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12022 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012023 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
12024 }
12025
12026 /*
12027 * 1.3.1 DF must be an allowed constraining facet for the {primitive
12028 * type definition}, as specified in the appropriate subsection of 3.2
12029 * Primitive datatypes.
12030 */
12031 if (type->facets != NULL) {
12032 xmlSchemaFacetPtr facet;
12033 int ok = 1;
12034
12035 primitive = xmlSchemaGetPrimitiveType(type);
12036 if (primitive == NULL) {
12037 xmlSchemaPErr(ctxt, type->node,
12038 XML_ERR_INTERNAL_ERROR,
12039 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012040 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012041 type->name, NULL);
12042 return (-1);
12043 }
12044 facet = type->facets;
12045 do {
12046 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012047 ok = 0;
12048 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012049 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012050 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012051 }
12052 facet = facet->next;
12053 } while (facet != NULL);
12054 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000012055 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012056 }
12057 /*
12058 * TODO: 1.3.2 (facet derivation)
12059 */
12060 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12061 xmlSchemaTypePtr itemType = NULL;
12062
12063 itemType = xmlSchemaGetListSimpleTypeItemType(type);
12064 if (itemType == NULL) {
12065 xmlSchemaPErr(ctxt, type->node,
12066 XML_ERR_INTERNAL_ERROR,
12067 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012068 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012069 type->name, NULL);
12070 return (-1);
12071 }
12072 /*
12073 * 2.1 The {item type definition} must have a {variety} of atomic or
12074 * union (in which case all the {member type definitions}
12075 * must be atomic).
12076 */
12077 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12078 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012079 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012080 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012081 NULL, type, NULL,
12082 "The item type %s must have a variety of atomic or union",
12083 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
12084 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012085 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
12086 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12087 xmlSchemaTypeLinkPtr member;
12088
12089 member = itemType->memberTypes;
12090 while (member != NULL) {
12091 if ((member->type->flags &
12092 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012093 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012094 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012095 NULL, type, NULL,
12096 "The item type is a union type, but the "
12097 "member type %s of this item type is not atomic",
12098 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12099 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012100 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
12101 }
12102 member = member->next;
12103 }
12104 }
12105
12106 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12107 xmlSchemaFacetPtr facet;
12108 /*
12109 * This is the case if we have: <simpleType><list ..
12110 */
12111 /*
12112 * 2.3.1
12113 * 2.3.1.1 The {final} of the {item type definition} must not
12114 * contain list.
12115 */
12116 if (xmlSchemaTypeFinalContains(ctxt->schema,
12117 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012118 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012119 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012120 NULL, type, NULL,
12121 "The final of its item type %s must not contain 'list'",
12122 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
12123 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012124 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
12125 }
12126 /*
12127 * 2.3.1.2 The {facets} must only contain the whiteSpace
12128 * facet component.
12129 */
12130 if (type->facets != NULL) {
12131 facet = type->facets;
12132 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012133 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
12134 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012135 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012136 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012137 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
12138 }
12139 facet = facet->next;
12140 } while (facet != NULL);
12141 }
12142 /*
12143 * TODO: Datatypes states:
12144 * A ·list· datatype can be ·derived· from an ·atomic· datatype
12145 * whose ·lexical space· allows space (such as string or anyURI)or
12146 * a ·union· datatype any of whose {member type definitions}'s
12147 * ·lexical space· allows space.
12148 */
12149 } else {
12150 /*
12151 * This is the case if we have: <simpleType><restriction ...
12152 */
12153 /*
12154 * 2.3.2
12155 * 2.3.2.1 The {base type definition} must have a {variety} of list.
12156 */
12157 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012158 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012159 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012160 NULL, type, NULL,
12161 "The base type %s must be a list type",
12162 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12163 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012164 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
12165 }
12166 /*
12167 * 2.3.2.2 The {final} of the {base type definition} must not
12168 * contain restriction.
12169 */
12170 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12171 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012172 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012173 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012174 NULL, type, NULL,
12175 "The final of the base type %s must not contain 'restriction'",
12176 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12177 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012178 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
12179 }
12180 /*
12181 * 2.3.2.3 The {item type definition} must be validly derived
12182 * from the {base type definition}'s {item type definition} given
12183 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
12184 */
12185 {
12186 xmlSchemaTypePtr baseItemType;
12187
12188 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
12189 if (baseItemType == NULL) {
12190 xmlSchemaPErr(ctxt, type->node,
12191 XML_ERR_INTERNAL_ERROR,
12192 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012193 "List simple type '%s': Failed to "
12194 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012195 type->name, type->baseType->name);
12196 return (-1);
12197 }
12198 if ((itemType != baseItemType) &&
12199 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
12200 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012201 xmlChar *strBIT = NULL, *strBT = NULL;
12202 xmlSchemaPCustomErrExt(ctxt,
12203 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
12204 NULL, type, NULL,
12205 "The item type %s is not validly derived from the "
12206 "item type %s of the base type %s",
12207 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
12208 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
12209 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12210
12211 FREE_AND_NULL(str)
12212 FREE_AND_NULL(strBIT)
12213 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012214 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
12215 }
12216 }
12217
12218 if (type->facets != NULL) {
12219 xmlSchemaFacetPtr facet;
12220 int ok = 1;
12221 /*
12222 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
12223 * and enumeration facet components are allowed among the {facets}.
12224 */
12225 facet = type->facets;
12226 do {
12227 switch (facet->type) {
12228 case XML_SCHEMA_FACET_LENGTH:
12229 case XML_SCHEMA_FACET_MINLENGTH:
12230 case XML_SCHEMA_FACET_MAXLENGTH:
12231 case XML_SCHEMA_FACET_WHITESPACE:
12232 /*
12233 * TODO: 2.5.1.2 List datatypes
12234 * The value of ·whiteSpace· is fixed to the value collapse.
12235 */
12236 case XML_SCHEMA_FACET_PATTERN:
12237 case XML_SCHEMA_FACET_ENUMERATION:
12238 break;
12239 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012240 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012241 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012242 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012243 /*
12244 * We could return, but it's nicer to report all
12245 * invalid facets.
12246 */
12247 ok = 0;
12248 }
12249 }
12250 facet = facet->next;
12251 } while (facet != NULL);
12252 if (ok == 0)
12253 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
12254 /*
12255 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
12256 * is a facet of the same kind in the {facets} of the {base type
12257 * definition} (call this BF),then the DF's {value} must be a valid
12258 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
12259 */
12260 }
12261
12262
12263 }
12264 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12265 /*
12266 * 3.1 The {member type definitions} must all have {variety} of
12267 * atomic or list.
12268 */
12269 xmlSchemaTypeLinkPtr member;
12270
12271 member = type->memberTypes;
12272 while (member != NULL) {
12273 if (((member->type->flags &
12274 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12275 ((member->type->flags &
12276 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012277 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012278 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012279 NULL, type, NULL,
12280 "The member type %s is neither an atomic, nor a list type",
12281 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12282 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012283 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
12284 }
12285 member = member->next;
12286 }
12287 /*
12288 * 3.3.1 If the {base type definition} is the ·simple ur-type
12289 * definition·
12290 */
12291 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12292 /*
12293 * 3.3.1.1 All of the {member type definitions} must have a
12294 * {final} which does not contain union.
12295 */
12296 member = type->memberTypes;
12297 while (member != NULL) {
12298 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
12299 XML_SCHEMAS_TYPE_FINAL_UNION)) {
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_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012302 NULL, type, NULL,
12303 "The final of member type %s contains 'union'",
12304 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12305 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012306 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
12307 }
12308 member = member->next;
12309 }
12310 /*
12311 * 3.3.1.2 The {facets} must be empty.
12312 */
12313 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012314 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012315 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012316 NULL, type, NULL,
12317 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012318 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
12319 }
12320 } else {
12321 /*
12322 * 3.3.2.1 The {base type definition} must have a {variety} of union.
12323 */
12324 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012325 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012326 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012327 NULL, type, NULL,
12328 "The base type %s is not a union type",
12329 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12330 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012331 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
12332 }
12333 /*
12334 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
12335 */
12336 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12337 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012338 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012339 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012340 NULL, type, NULL,
12341 "The final of its base type %s must not contain 'restriction'",
12342 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12343 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012344 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
12345 }
12346 /*
12347 * 3.3.2.3 The {member type definitions}, in order, must be validly
12348 * derived from the corresponding type definitions in the {base
12349 * type definition}'s {member type definitions} given the empty set,
12350 * as defined in Type Derivation OK (Simple) (§3.14.6).
12351 */
12352 {
12353 xmlSchemaTypeLinkPtr baseMember;
12354
12355 /*
12356 * OPTIMIZE: if the type is restricting, it has no local defined
12357 * member types and inherits the member types of the base type;
12358 * thus a check for equality can be skipped.
12359 */
12360 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012361 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000012362 * union simple type can have other member types as the member
12363 * types of it's base type. This check seems not necessary with
12364 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012365 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012366 */
12367 if (type->memberTypes != NULL) {
12368 member = type->memberTypes;
12369 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
12370 if ((member == NULL) && (baseMember != NULL)) {
12371 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012372 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012373 "Internal error: "
12374 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012375 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012376 "of member types in the base type\n",
12377 type->name, NULL);
12378 }
12379 while (member != NULL) {
12380 if (baseMember == NULL) {
12381 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012382 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012383 "Internal error: "
12384 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012385 "(3.3.2.3), union simple type '%s', unequal number "
12386 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012387 type->name, NULL);
12388 }
12389 if ((member->type != baseMember->type) &&
12390 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
12391 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012392 xmlChar *strBMT = NULL, *strBT = NULL;
12393
12394 xmlSchemaPCustomErrExt(ctxt,
12395 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
12396 NULL, type, NULL,
12397 "The member type %s is not validly derived from its "
12398 "corresponding member type %s of the base type %s",
12399 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
12400 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
12401 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12402 FREE_AND_NULL(str)
12403 FREE_AND_NULL(strBMT)
12404 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012405 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
12406 }
12407 member = member->next;
12408 baseMember = baseMember->next;
12409 }
12410 }
12411 }
12412 /*
12413 * 3.3.2.4 Only pattern and enumeration facet components are
12414 * allowed among the {facets}.
12415 */
12416 if (type->facets != NULL) {
12417 xmlSchemaFacetPtr facet;
12418 int ok = 1;
12419
12420 facet = type->facets;
12421 do {
12422 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
12423 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012424 xmlSchemaPIllegalFacetListUnionErr(ctxt,
12425 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
12426 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012427 ok = 0;
12428 }
12429 facet = facet->next;
12430 } while (facet != NULL);
12431 if (ok == 0)
12432 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
12433
12434 }
12435 /*
12436 * TODO: 3.3.2.5 (facet derivation)
12437 */
12438 }
12439 }
12440
12441 return (0);
12442}
12443
12444/**
12445 * xmlSchemaCheckSRCSimpleType:
12446 * @ctxt: the schema parser context
12447 * @type: the simple type definition
12448 *
12449 * Checks crc-simple-type constraints.
12450 *
12451 * Returns 0 if the constraints are satisfied,
12452 * if not a positive error code and -1 on internal
12453 * errors.
12454 */
12455static int
12456xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
12457 xmlSchemaTypePtr type)
12458{
12459 /*
12460 * NOTE: src-simple-type 2-4 are redundant, since the checks
12461 * were are done for the corresponding <restriction>, <list> and <union>
12462 * elements, but W3C wants a <simpleType> error as well, so it gets one.
12463 * Maby this can be skipped in the future, if we get sure it's not needed.
12464 */
12465 if (type->subtypes == NULL) {
12466 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012467 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012468 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012469 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012470 type->name, NULL);
12471 return (-1);
12472 }
12473 /*
12474 * src-simple-type.1 The corresponding simple type definition, if any,
12475 * must satisfy the conditions set out in Constraints on Simple Type
12476 * Definition Schema Components (§3.14.6).
12477 */
12478 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
12479 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
12480 /*
12481 * TODO: Removed this, since it got annoying to get an
12482 * extra error report, if anything failed until now.
12483 * Enable this if needed.
12484 */
12485 /*
12486 xmlSchemaPErr(ctxt, type->node,
12487 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012488 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012489 "on simple type definitions.\n",
12490 type->name, NULL);
12491 */
12492 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
12493 }
12494
12495 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
12496 /*
12497 * src-simple-type.2 If the <restriction> alternative is chosen,
12498 * either it must have a base [attribute] or a <simpleType> among its
12499 * [children], but not both.
12500 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012501 /*
12502 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
12503 * NOTE: This was removed, since this will be already handled
12504 * in the parse function for <restriction>.
12505 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012506 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
12507 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
12508 * an itemType [attribute] or a <simpleType> among its [children],
12509 * but not both.
12510 * NOTE: baseType is set to the local simple type definiton,
12511 * if existent, at parse time. This is a hack and not nice.
12512 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012513 /*
12514 * TODO: Remove this, and add the check to the parse function of <list>.
12515 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012516 if (((type->subtypes->base == NULL) &&
12517 (type->baseType == NULL)) ||
12518 ((type->subtypes->base != NULL) &&
12519 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012520 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012521 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012522 NULL, type, NULL,
12523 "Either the attribute 'itemType' or the <simpleType> child "
12524 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012525 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
12526 }
12527
12528
12529 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
12530 xmlSchemaTypeLinkPtr member;
12531 xmlSchemaTypePtr ancestor, anySimpleType;
12532
12533 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12534
12535 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
12536 * the <union> alternative is chosen, there must not be any entries
12537 * in the memberTypes [attribute] at any depth which resolve to the
12538 * component corresponding to the <simpleType>.
12539 */
12540 member = type->memberTypes;
12541 while (member != NULL) {
12542 ancestor = member->type;
12543 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
12544 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12545 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
12546 if (ancestor == anySimpleType)
12547 break;
12548 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012549 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012550 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012551 NULL, type, NULL,
12552 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012553 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
12554 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12555 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012556 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000012557 * type as item type, which in turn has a list ST as member
12558 * type, we will assume this here as well, since this check
12559 * was not yet performed.
12560 */
12561
12562 }
12563 ancestor = ancestor->baseType;
12564 }
12565 member = member->next;
12566 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012567 }
12568
12569 return (0);
12570}
12571
William M. Brack2f2a6632004-08-20 23:09:47 +000012572#if 0 /* Not yet used code for CT schema validation */
12573static int
12574xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
12575 const xmlChar * value,
12576 xmlSchemaTypePtr type,
12577 int fireErrors)
12578{
12579 int ret;
12580 /*
12581 * 3.14.4 Simple Type Definition Validation Rules
12582 * Validation Rule: String Valid
12583 */
12584 /*
12585 * 1 It is schema-valid with respect to that definition as defined
12586 * by Datatype Valid in [XML Schemas: Datatypes].
12587 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012588 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
12589 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000012590 return (ret);
12591 /*
12592 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
12593 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
12594 * the string must be a ·declared entity name·.
12595 */
12596 /*
12597 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
12598 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
12599 * then every whitespace-delimited substring of the string must be a ·declared
12600 * entity name·.
12601 */
12602 /*
12603 * 2.3 otherwise no further condition applies.
12604 */
12605
12606 return (0);
12607}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012608#endif
12609
William M. Brack2f2a6632004-08-20 23:09:47 +000012610
12611static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012612xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
12613{
12614 if (vctxt->pctxt == NULL) {
12615 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
12616 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
12617 if (vctxt->pctxt == NULL) {
12618 xmlSchemaVErr(vctxt, NULL,
12619 XML_SCHEMAV_INTERNAL,
12620 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12621 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000012622 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012623 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012624 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012625 /* TODO: Pass user data. */
12626 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
12627 }
12628 return (0);
12629}
12630
12631static int
12632xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
12633{
12634 if (ctxt->vctxt == NULL) {
12635 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
12636 if (ctxt->vctxt == NULL) {
12637 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012638 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012639 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12640 "failed to create a temp. validation context.\n",
12641 NULL, NULL);
12642 return (-1);
12643 }
12644 /* TODO: Pass user data. */
12645 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
12646 }
12647 return (0);
12648}
12649
12650/**
12651 * xmlSchemaCheckCOSValidDefault:
12652 * @ctxt: the schema parser context
12653 * @type: the simple type definition
12654 * @value: the default value
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000012655 * @val: the precomputed value to be returned
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012656 * @node: an optional node (the holder of the value)
12657 *
12658 * Checks the "cos-valid-default" constraints.
12659 *
12660 * Returns 0 if the constraints are satisfied,
12661 * if not, a positive error code and -1 on internal
12662 * errors.
12663 */
12664static int
12665xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
12666 xmlSchemaValidCtxtPtr vctxt,
12667 xmlSchemaTypePtr type,
12668 const xmlChar *value,
12669 xmlNodePtr node)
12670{
12671 int ret = 0;
12672
12673 /*
12674 * cos-valid-default:
12675 * Schema Component Constraint: Element Default Valid (Immediate)
12676 * For a string to be a valid default with respect to a type
12677 * definition the appropriate case among the following must be true:
12678 */
12679 /*
12680 * NOTE: This has to work without a given node (the holder of the
12681 * value), since it should work on the component, i.e. an underlying
12682 * DOM must not be mandatory.
12683 */
12684 if ((pctxt == NULL) || (vctxt == NULL)) {
12685 xmlSchemaPErr(pctxt, node,
12686 XML_SCHEMAP_INTERNAL,
12687 "Internal error: xmlSchemaCheckCOSValidDefault, "
12688 "bad arguments: the parser and/or validation context is "
12689 "missing.\n",
12690 NULL, NULL);
12691 return (-1);
12692 }
12693 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012694 /*
12695 * Complex type.
12696 *
12697 * 2.1 its {content type} must be a simple type definition or mixed.
12698 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012699 /*
12700 * TODO: Adjust this when the content type will be computed
12701 * correctly.
12702 */
12703 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
12704 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
12705 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
12706 xmlSchemaPSimpleTypeErr(pctxt,
12707 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
12708 NULL, NULL, node,
12709 type, NULL, NULL,
12710 "If the type of a constraint value is complex, its content "
12711 "type must be mixed or a simple type",
12712 NULL, NULL);
12713 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
12714 }
12715 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012716 /*
12717 * 2.2.2 If the {content type} is mixed, then the {content type}'s
12718 * particle must be ·emptiable· as defined by Particle Emptiable
12719 * (§3.9.6).
12720 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012721
William M. Brack2f2a6632004-08-20 23:09:47 +000012722 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012723 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000012724 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012725 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000012726 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012727 }
12728 /*
12729 * 1 If the type definition is a simple type definition, then the string
12730 * must be ·valid· with respect to that definition as defined by String
12731 * Valid (§3.14.4).
12732 *
12733 * AND
12734 *
12735 * 2.2.1 If the {content type} is a simple type definition, then the
12736 * string must be ·valid· with respect to that simple type definition
12737 * as defined by String Valid (§3.14.4).
12738 */
12739 vctxt->node = node;
12740 vctxt->cur = NULL;
12741 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
12742 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
12743 if (ret < 0) {
12744 xmlSchemaPErr(pctxt, node,
12745 /* NOTNICE: error code: This function will be used during
12746 * schema construction and xsi:type validation.
12747 */
12748 XML_SCHEMAP_INTERNAL,
12749 "Internal error: xmlSchemaCheckCOSValidDefault, "
12750 "while validating a value constaint value.\n",
12751 NULL, NULL);
12752
12753 }
12754 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000012755}
12756
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012757#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000012758/**
12759 * xmlSchemaGetSTContentOfCT:
12760 * @ctxt: the schema parser context
12761 * @type: the complex type definition
12762 *
12763 *
12764 * Returns the corresponding simple type for the content of
12765 * the complex type.
12766 */
12767static xmlSchemaTypePtr
12768xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
12769 xmlSchemaTypePtr type)
12770{
12771 xmlSchemaTypePtr orig = type, anyType;
12772
12773 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12774 while ((type != NULL) && (type != anyType) &&
12775 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
12776 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
12777 return(type);
12778 type = type->baseType;
12779 }
12780 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012781 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012782 NULL, orig, NULL,
12783 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
12784 "no simple type for the content of complex type '%s' could be "
12785 "computed", orig->name);
12786 return (NULL);
12787}
12788
12789
William M. Brack2f2a6632004-08-20 23:09:47 +000012790
William M. Brack2f2a6632004-08-20 23:09:47 +000012791
12792/**
12793 * xmlSchemaCheckCOSCTExtends:
12794 * @ctxt: the schema parser context
12795 * @type: the complex type definition
12796 *
12797 * Schema Component Constraint: Derivation Valid (Extension)
12798 *
12799 * Returns 0 if the constraints are satisfied, a positive
12800 * error code if not and -1 if an internal error occured.
12801 */
12802static int
12803xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
12804 xmlSchemaTypePtr type)
12805{
12806 xmlSchemaTypePtr base;
12807 /*
12808 * 1 If the {base type definition} is a complex type definition,
12809 * then all of the following must be true:
12810 */
12811 base = type->baseType;
12812 if (base == NULL) {
12813 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012814 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012815 NULL, type, NULL,
12816 "Internal error: xmlSchemaCheckCOSCTExtends, "
12817 "the complex type '%s' has no base type", type->name);
12818 return (-1);
12819 }
12820 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
12821 /*
12822 * 1.1 The {final} of the {base type definition} must not
12823 * contain extension.
12824 */
12825 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
12826 xmlSchemaPCustomErr(ctxt,
12827 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
12828 NULL, type, NULL,
12829 "The 'final' of the base type definition "
12830 "contains extension", NULL);
12831 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
12832 }
12833 /*
12834 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
12835 * of the complex type definition itself, that is, for every attribute
12836 * use in the {attribute uses} of the {base type definition}, there
12837 * must be an attribute use in the {attribute uses} of the complex
12838 * type definition itself whose {attribute declaration} has the same
12839 * {name}, {target namespace} and {type definition} as its attribute
12840 * declaration
12841 *
12842 * NOTE: This will be already satisfied by the way the attribute uses
12843 * are extended in xmlSchemaBuildAttributeValidation; thus this check
12844 * is not needed.
12845 */
12846
12847 /*
12848 * 1.3 If it has an {attribute wildcard}, the complex type definition
12849 * must also have one, and the base type definition's {attribute
12850 * wildcard}'s {namespace constraint} must be a subset of the complex
12851 * type definition's {attribute wildcard}'s {namespace constraint},
12852 * as defined by Wildcard Subset (§3.10.6).
12853 *
12854 * This is already checked in xmlSchemaBuildAttributeValidation; thus
12855 * this check is not needed.
12856 */
12857
12858 /*
12859 * 1.4 One of the following must be true:
12860 *
12861 * 1.4.1 The {content type} of the {base type definition} and the
12862 * {content type} of the complex type definition itself must be the same
12863 * simple type definition
12864 */
12865
12866
12867
12868 } else {
12869 /*
12870 * 2 If the {base type definition} is a simple type definition,
12871 * then all of the following must be true:
12872 */
12873 /*
12874 * 2.1 The {content type} must be the same simple type definition.
12875 */
12876 /*
12877 * 2.2 The {final} of the {base type definition} must not contain
12878 * extension
12879 */
12880 }
12881
12882}
12883
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012884static int
12885xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
12886 xmlSchemaTypePtr type)
12887{
12888 xmlSchemaTypePtr base, content;
12889 int OK = 0;
12890
12891 /*
12892 * TODO: Adjust the error codes here, as I used
12893 * XML_SCHEMAP_SRC_CT_1 only yet.
12894 */
12895 /*
12896 * Schema Representation Constraint:
12897 * Complex Type Definition Representation OK
12898 */
12899 base = type->baseType;
12900 if (base == NULL) {
12901 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
12902 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
12903 type->name);
12904 return (-1);
12905 }
12906
12907 if (type->subtypes != NULL) {
12908 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
12909 if IS_COMPLEX_TYPE(base) {
12910 /*
12911 * 1 If the <complexContent> alternative is chosen, the type definition
12912 * ·resolved· to by the ·actual value· of the base [attribute]
12913 * must be a complex type definition;
12914 */
12915 xmlSchemaPCustomErr(ctxt,
12916 XML_SCHEMAP_SRC_CT_1,
12917 NULL, type, NULL,
12918 "The base type is not a complex type", NULL);
12919 return (XML_SCHEMAP_SRC_CT_1);
12920 }
12921 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
12922
12923 if IS_SIMPLE_TYPE(base) {
12924 if (type->flags &
12925 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12926 /*
12927 * 2.1.3 only if the <extension> alternative is also
12928 * chosen, a simple type definition.
12929 */
12930 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
12931 xmlSchemaPCustomErr(ctxt,
12932 XML_SCHEMAP_SRC_CT_1,
12933 NULL, type, NULL,
12934 "A complex type (simple content) cannot restrict "
12935 "an other simple type",
12936 NULL);
12937 return (XML_SCHEMAP_SRC_CT_1);
12938 }
12939 OK = 1;
12940
12941 } else { /* if IS_SIMPLE_TYPE(base) */
12942 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
12943 /*
12944 * 2.1.2 only if the <restriction> alternative is also
12945 * chosen, a complex type definition whose {content type}
12946 * is mixed and a particle emptyable.
12947 */
12948 /*
12949 * FIXME TODO: Check for *empiable particle* is missing.
12950 */
12951 if ((type->flags &
12952 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
12953 xmlSchemaPCustomErr(ctxt,
12954 XML_SCHEMAP_SRC_CT_1,
12955 NULL, type, NULL,
12956 "A complex type (simple content) cannot "
12957 "extend an other complex type which has a "
12958 "content type of: 'mixed' and emptiable particle",
12959 NULL);
12960 return (XML_SCHEMAP_SRC_CT_1);
12961 }
12962 /*
12963 * NOTE: This will be fired as well, if the base type
12964 * is *'anyType'*.
12965 * NOTE: type->subtypes->subtypes will be the
12966 * <restriction> item.
12967 */
12968 if (type->subtypes->subtypes == NULL) {
12969 /* Yes, this is paranoid programming. */
12970 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12971 NULL, type, NULL,
12972 "Internal error: xmlSchemaCheckSRCCT, "
12973 "'%s', <simpleContent> has no <restriction>",
12974 type->name);
12975 return (-1);
12976 }
12977 /*
12978 * 2.2 If clause 2.1.2 above is satisfied, then there
12979 * must be a <simpleType> among the [children] of
12980 * <restriction>.
12981 */
12982 if (type->subtypes->subtypes->type !=
12983 XML_SCHEMA_TYPE_SIMPLE) {
12984 /* TODO: Change error code to ..._SRC_CT_2_2. */
12985 xmlSchemaPCustomErr(ctxt,
12986 XML_SCHEMAP_SRC_CT_1,
12987 NULL, type, NULL,
12988 "A <simpleType> is expected among the children "
12989 "of <restriction>", NULL);
12990 return (XML_SCHEMAP_SRC_CT_1);
12991 }
12992 OK = 1;
12993 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
12994 /*
12995 * 2.1.1 a complex type definition whose {content type} is a
12996 * simple type definition;
12997 */
12998 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
12999 xmlSchemaPCustomErr(ctxt,
13000 XML_SCHEMAP_SRC_CT_1,
13001 NULL, type, NULL,
13002 "A complex type (simple content) cannot "
13003 "be derived from the complex type '%s'",
13004 base->name);
13005 return (XML_SCHEMAP_SRC_CT_1);
13006 }
13007 content = base->contentTypeDef;
13008 if (content == NULL) {
13009 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13010 NULL, type, NULL,
13011 "Internal error: xmlSchemaCheckSRCCT, "
13012 "'%s', base type has no content type",
13013 type->name);
13014 return (-1);
13015 }
13016 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
13017 xmlSchemaPCustomErr(ctxt,
13018 XML_SCHEMAP_SRC_CT_1,
13019 NULL, type, NULL,
13020 "A complex type (simple content) cannot "
13021 "be derived from the complex type '%s'",
13022 base->name);
13023 return (XML_SCHEMAP_SRC_CT_1);
13024 }
13025 }
13026 }
13027 }
13028 }
13029 /*
13030 * TODO: 3 The corresponding complex type definition component must
13031 * satisfy the conditions set out in Constraints on Complex Type
13032 * Definition Schema Components (§3.4.6);
13033 *
13034 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
13035 * above for {attribute wildcard} is satisfied, the intensional
13036 * intersection must be expressible, as defined in Attribute Wildcard
13037 * Intersection (§3.10.6).
13038 */
13039
13040}
William M. Brack2f2a6632004-08-20 23:09:47 +000013041#endif
13042
Daniel Veillard01fa6152004-06-29 17:04:39 +000013043/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013044 * xmlSchemaGroupDefFixup:
13045 * @typeDecl: the schema model group definition
13046 * @ctxt: the schema parser context
13047 *
13048 * Fixes model group definitions.
13049 */
13050static void
13051xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
13052 xmlSchemaParserCtxtPtr ctxt,
13053 const xmlChar * name ATTRIBUTE_UNUSED)
13054{
13055 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
13056 if ((group->ref != NULL) && (group->subtypes == NULL)) {
13057 xmlSchemaTypePtr groupDef;
13058 /*
13059 * Resolve the reference.
13060 */
13061 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
13062 group->refNs);
13063 if (groupDef == NULL) {
13064 xmlSchemaPResCompAttrErr(ctxt,
13065 XML_SCHEMAP_SRC_RESOLVE,
13066 NULL, group, NULL,
13067 "ref", group->ref, group->refNs,
13068 XML_SCHEMA_TYPE_GROUP, NULL);
13069 return;
13070 }
13071 group->subtypes = groupDef;
13072 }
13073}
13074
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013075#if 0 /* Enable when the content type will be computed. */
13076static int
13077xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
13078 xmlSchemaTypePtr type)
13079{
13080 xmlSchemaTypePtr base, res = NULL;
13081
13082 base = type->baseType;
13083 if (base == NULL) {
13084 xmlSchemaPCustomErr(ctxt,
13085 XML_SCHEMAP_INTERNAL,
13086 NULL, type, NULL,
13087 "Internal error: xmlSchemaGetContentType, "
13088 "the complex type '%s' has no base type", type->name);
13089 return (-1);
13090 }
13091 if (IS_ANYTYPE(base) || (type->subtypes->type ==
13092 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
13093 xmlSchemaTypePtr start;
13094 /*
13095 * Effective 'mixed'.
13096 */
13097 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
13098 type->contentType = XML_SCHEMA_CONTENT_MIXED;
13099 /*
13100 * Effective content.
13101 */
13102 if (IS_ANYTYPE(base))
13103 start = type;
13104 else
13105 start = type->subtypes;
13106
13107 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
13108 xmlSchemaTypePtr baseContentItem;
13109
13110 /*
13111 * Complex type with simple content.
13112 */
13113 if IS_COMPLEX_TYPE(base) {
13114 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
13115 /*
13116 * Summary: a complex type (simple content) can *restrict*
13117 * a complex type with the following content type:
13118 * 1. 'mixed' and an emptiable particle
13119 * 2. simple type
13120 */
13121 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
13122 /*
13123 * 2 if the {content type} of the base type is mixed and a
13124 * particle which is ·emptiable·,
13125 * [...]
13126 * then starting from the simple type definition
13127 * corresponding to the <simpleType> among the [children]
13128 * of <restriction> (**which must be present**)
13129 *
13130 * FIXME TODO: Handle "emptiable particle".
13131 */
13132 res = type->subtypes->subtypes;
13133 if (res == NULL) {
13134 xmlSchemaPCustomErr(ctxt,
13135 XML_SCHEMAP_INTERNAL,
13136 NULL, type, NULL,
13137 "Internal error: xmlSchemaGetContentType, "
13138 "CT '%s' (restricting): <simpleContent> has no "
13139 "<restriction>",
13140 type->name);
13141 return (-1);
13142 }
13143
13144 res->subtypes;
13145 if (res == NULL) {
13146 xmlSchemaPCustomErr(ctxt,
13147 XML_SCHEMAP_INTERNAL,
13148 NULL, type, NULL,
13149 "Internal error: xmlSchemaGetContentType, "
13150 "CT '%s' (restricting): <restriction> has no "
13151 "mandatory <simpleType>",
13152 type->name);
13153 return (-1);
13154 }
13155 } else {
13156 baseContentItem = base->contentTypeDef;
13157 if (baseContentItem == NULL) {
13158 xmlSchemaPCustomErr(ctxt,
13159 XML_SCHEMAP_INTERNAL,
13160 NULL, type, NULL,
13161 "Internal error: xmlSchemaGetContentType, "
13162 "CT '%s' (restricting), the base type has no "
13163 "content type", type->name);
13164 return (-1);
13165 }
13166 if IS_SIMPLE_TYPE(baseContentItem) {
13167 /*
13168 * 1 If the base type is a complex type whose own
13169 * {content type} is a simple type and the <restriction>
13170 * alternative is chosen
13171 */
13172 /* type->subtypes->subtypes will be the restriction item.*/
13173 res = type->subtypes->subtypes;
13174 if (res == NULL) {
13175 xmlSchemaPCustomErr(ctxt,
13176 XML_SCHEMAP_INTERNAL,
13177 NULL, type, NULL,
13178 "Internal error: xmlSchemaGetContentType, "
13179 "CT '%s' (restricting): <simpleType> has no "
13180 "<restriction>", type->name);
13181 return (-1);
13182 }
13183 /*
13184 * 1.1 the simple type definition corresponding to the
13185 * <simpleType> among the [children] of <restriction>if
13186 * there is one;
13187 */
13188 res = res->subtypes;
13189 if (res == NULL) {
13190 /*
13191 * 1.2 otherwise the {content type}
13192 * of the base type .
13193 */
13194 res = baseContentItem;
13195 }
13196 }
13197 }
13198 /*
13199 * SPECIAL TODO: If *restricting* the spec wants us to
13200 * create an *additional* simple type which restricts the
13201 * located simple type; we won't do this yet, and look how
13202 * far we get with it.
13203 */
13204 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
13205 /*
13206 * Summary: a complex type (simple content) can *extend*
13207 * only a complex base with a simple type as content.
13208 */
13209 /*
13210 * 3 If the type definition ·resolved· to by the ·actual
13211 * value· of the base [attribute] is a complex type
13212 * definition (whose own {content type} *must be* a simple
13213 * type definition, see below) and the *<extension>*
13214 * alternative is chosen, then the {content type} of that
13215 * complex type definition;
13216 */
13217 res = base->contentTypeDef;
13218 if (res == NULL) {
13219 xmlSchemaPCustomErr(ctxt,
13220 XML_SCHEMAP_INTERNAL,
13221 NULL, type, NULL,
13222 "Internal error: xmlSchemaGetContentType, "
13223 "CT '%s' (extending), the base type has no content "
13224 "type", type->name);
13225 return (-1);
13226 }
13227 if (! IS_SIMPLE_TYPE(res)) {
13228 xmlSchemaPCustomErr(ctxt,
13229 XML_SCHEMAP_INTERNAL,
13230 NULL, type, NULL,
13231 "Internal error: xmlSchemaGetContentType, "
13232 "CT '%s' (extending), the content type of the "
13233 "base is not a simple type", type->name);
13234 return (-1);
13235 }
13236 }
13237 } else /* if IS_COMPLEX_TYPE(base) */
13238 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
13239 /*
13240 * 4 otherwise (the type definition ·resolved· to by the
13241 * ·actual value· of the base [attribute] is a simple type
13242 * definition and the <extension> alternative is chosen),
13243 * then that simple type definition.
13244 */
13245 res = base;
13246 }
13247 type->contentTypeDef = res;
13248 if (res == NULL) {
13249 xmlSchemaPCustomErr(ctxt,
13250 XML_SCHEMAP_INTERNAL,
13251 NULL, type, NULL,
13252 "Internal error: xmlSchemaGetContentType, "
13253 "'%s', the content type could not be determined",
13254 type->name);
13255 return (-1);
13256 }
13257
13258 }
13259
13260}
13261#endif
13262
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013263/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013264 * xmlSchemaTypeFixup:
13265 * @typeDecl: the schema type definition
13266 * @ctxt: the schema parser context
13267 *
13268 * Fixes the content model of the type.
13269 */
13270static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013271xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013272 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013273{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013274 xmlSchemaTypePtr ctxtType;
13275
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013276 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013277 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013278 /*
13279 * Do not allow the following types to be typefixed, prior to
13280 * the corresponding simple/complex types.
13281 */
13282 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013283 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013284 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13285 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13286 case XML_SCHEMA_TYPE_UNION:
13287 case XML_SCHEMA_TYPE_RESTRICTION:
13288 case XML_SCHEMA_TYPE_EXTENSION:
13289 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013290 default:
13291 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013292 }
13293 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013294 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013295 name = item->name;
13296 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
13297 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013298 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013299 if (item->subtypes != NULL) {
13300 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013301 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013302 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013303 NULL);
13304 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013305 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013306 XML_SCHEMA_CONTENT_SIMPLE;
13307 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013308 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013309 break;
13310 }
13311 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013312 xmlSchemaTypePtr base = NULL;
13313
13314 ctxt->ctxtType->flags |=
13315 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013316 if (item->baseType != NULL)
13317 base = item->baseType;
13318 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013319 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013320 xmlSchemaGetType(ctxt->schema, item->base,
13321 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013322 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013323 xmlSchemaPResCompAttrErr(ctxt,
13324 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000013325 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013326 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
13327 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013328 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013329 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000013330 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013331 xmlSchemaTypeFixup(base, ctxt, NULL);
13332 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013333 }
13334 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013335 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
13336 /*
13337 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000013338 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013339 /*
13340 * Content type.
13341 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013342 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013343 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013344 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13345 else if ((item->subtypes->subtypes == NULL) &&
13346 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013347 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013348 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013349 XML_SCHEMA_TYPE_SEQUENCE)))
13350 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013351 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13352 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013353 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013354 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013355 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013356 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013357 else {
13358 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013359 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013360 XML_SCHEMA_CONTENT_ELEMENTS;
13361 }
13362 } else {
13363 /*
13364 * SimpleType restriction.
13365 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013366 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013367 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013368 break;
13369 }
13370 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013371 xmlSchemaTypePtr base = NULL;
13372 xmlSchemaContentType explicitContentType;
13373
13374 /*
13375 * An extension does exist on a complexType only.
13376 */
13377 ctxt->ctxtType->flags |=
13378 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013379 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013380 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013381 xmlSchemaPCustomErr(ctxt,
13382 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013383 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013384 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000013385 return;
13386 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013387 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013388 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013389 xmlSchemaGetType(ctxt->schema, item->base,
13390 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013391 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013392 xmlSchemaPResCompAttrErr(ctxt,
13393 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013394 NULL, item, item->node,
13395 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013396 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013397 } else if (base->contentType ==
13398 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013399 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013400 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013401 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013402 }
13403 /*
13404 * The type definition ·resolved· to by the ·actual
13405 * value· of the base [attribute]
13406 */
13407 ctxt->ctxtType->baseType = base;
13408 /*
13409 * TODO: This one is still needed for computation of
13410 * the content model by xmlSchemaBuildAContentModel.
13411 * Try to get rid of it.
13412 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013413 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013414 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013415 if ((item->subtypes != NULL) &&
13416 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
13417 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013418
13419 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013420 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013421 /* 1.1.1 */
13422 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013423 else if ((item->subtypes->subtypes == NULL) &&
13424 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013425 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013426 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013427 XML_SCHEMA_TYPE_SEQUENCE)))
13428 /* 1.1.2 */
13429 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013430 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013431 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013432 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013433 /* 1.1.3 */
13434 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
13435 if (base != NULL) {
13436 /* It will be reported later, if the base is missing. */
13437 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
13438 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013439 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013440 } else if (base->contentType ==
13441 XML_SCHEMA_CONTENT_EMPTY) {
13442 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013443 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013444 XML_SCHEMA_CONTENT_ELEMENTS;
13445 } else {
13446 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013447 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013448 XML_SCHEMA_CONTENT_ELEMENTS;
13449 }
13450 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013451 break;
13452 }
13453 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013454 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013455 ctxt->ctxtType = item;
13456 /*
13457 * Start with an empty content-type type.
13458 */
13459 if (item->subtypes == NULL)
13460 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13461
13462 if ((item->subtypes == NULL) ||
13463 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013464 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013465 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013466 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
13467 /*
13468 * This case is understood as shorthand for complex
13469 * content restricting the ur-type definition, and
13470 * the details of the mappings should be modified as
13471 * necessary.
13472 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013473 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13474 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013475 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013476 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013477 * Assume that we inherit the content-type type
13478 * from 'anyType', which is 'mixed' and a particle
13479 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013480 */
13481 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013482 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013483 /*
13484 * Fixup the sub components.
13485 */
13486 if ((item->subtypes != NULL) &&
13487 (item->subtypes->contentType ==
13488 XML_SCHEMA_CONTENT_UNKNOWN)) {
13489 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013490 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013491 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13492 item->contentType = XML_SCHEMA_CONTENT_MIXED;
13493 } else if (item->subtypes != NULL) {
13494 /*
13495 * Use the content-type type of the model groups
13496 * defined, if 'mixed' is not set. If 'mixed' is set
13497 * it will expand the content-type by allowing character
13498 * content to appear.
13499 */
13500 item->contentType =
13501 item->subtypes->contentType;
13502 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013503
13504 /*
13505 * Some optimization for validation:
13506 * If there are no facets beside the "whitespace" facet,
13507 * then a value needs not to checked against against a
13508 * facet, thus no computed value is needed.
13509 * TODO URGENT: This is just a workaround, we need to
13510 * introduce the correct usage of contentType to store the
13511 * facets in!
13512 */
Daniel Veillardd3210bc2005-01-28 17:56:39 +000013513 if ((item->baseType != NULL) &&
13514 (item->baseType->flags &
13515 XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013516 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13517 else {
13518 xmlSchemaFacetLinkPtr cur;
13519
13520 for (cur = item->facetSet; cur != NULL;
13521 cur = cur->next) {
13522 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13523 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13524 break;
13525 }
13526 }
13527 }
13528
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013529 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013530 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013531 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013532 break;
13533 }
13534 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013535 if (item->subtypes == NULL) {
13536 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13537 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
13538 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000013539 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013540 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013541 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13542 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013543 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000013544 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013545 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013546 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013547 if (item->subtypes != NULL)
13548 item->contentType =
13549 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013550 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013551 /*
13552 * Removed due to implementation of the build of attribute uses.
13553 */
13554 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013555 if (item->attributes == NULL)
13556 item->attributes =
13557 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000013558 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013559 }
13560 break;
13561 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013562 case XML_SCHEMA_TYPE_SIMPLE:
13563 /*
13564 * Simple Type Definition Schema Component
13565 *
13566 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013567 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013568 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13569 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013570 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013571 ctxt->ctxtType = item;
13572 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013573 }
13574 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013575 if ((item->baseType != NULL) &&
13576 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013577 XML_SCHEMA_CONTENT_UNKNOWN)) {
13578 /* OPTIMIZE: Actually this one will never by hit, since
13579 * the base type is already type-fixed in <restriction>.
13580 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013581 ctxt->ctxtType = item;
13582 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013583 }
13584 /* Base type:
13585 * 2 If the <list> or <union> alternative is chosen,
13586 * then the ·simple ur-type definition·.
13587 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013588 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013589 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013590 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13591 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13592 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013593 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013594 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13595 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
13596 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013597 XML_SCHEMA_TYPE_RESTRICTION) {
13598 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
13599
13600 /*
13601 * Variety
13602 * If the <restriction> alternative is chosen, then the
13603 * {variety} of the {base type definition}.
13604 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013605 if (item->baseType != NULL) {
13606 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013607 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013608 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
13609 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013610 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013611 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13612 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013613 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013614 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013615 /*
13616 * Schema Component Constraint: Simple Type Restriction
13617 * (Facets)
13618 * NOTE: Satisfaction of 1 and 2 arise from the fixup
13619 * applied beforehand.
13620 *
13621 * 3 The {facets} of R are the union of S and the {facets}
13622 * of B, eliminating duplicates. To eliminate duplicates,
13623 * when a facet of the same kind occurs in both S and the
13624 * {facets} of B, the one in the {facets} of B is not
13625 * included, with the exception of enumeration and pattern
13626 * facets, for which multiple occurrences with distinct values
13627 * are allowed.
13628 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013629 if (item->baseType->facetSet != NULL) {
13630 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013631 if (last != NULL)
13632 while (last->next != NULL)
13633 last = last->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013634 cur = item->baseType->facetSet;
13635 for (; cur != NULL; cur = cur->next) {
13636 /*
13637 * Base patterns won't be add here:
13638 * they are ORed in a type and
13639 * ANDed in derived types. This will
13640 * happed at validation level by
13641 * walking the base axis of the type.
13642 */
13643 if (cur->facet->type ==
13644 XML_SCHEMA_FACET_PATTERN)
13645 continue;
13646 facet = NULL;
13647 if ((item->facetSet != NULL) &&
13648 /* REMOVED: a check for
13649 * XML_SCHEMA_FACET_PATTERN was already
13650 * performed above.
13651
13652 * (cur->facet->type !=
13653 * XML_SCHEMA_FACET_PATTERN) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000013654 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013655 (cur->facet->type !=
13656 XML_SCHEMA_FACET_ENUMERATION)) {
13657 facet = item->facetSet;
13658 do {
13659 if (cur->facet->type ==
13660 facet->facet->type)
13661 break;
13662 facet = facet->next;
13663 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013664 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013665 if (facet == NULL) {
13666 facet = (xmlSchemaFacetLinkPtr)
13667 xmlMalloc(sizeof(xmlSchemaFacetLink));
13668 if (facet == NULL) {
13669 xmlSchemaPErrMemory(ctxt,
13670 "fixing simpleType", NULL);
13671 return;
13672 }
13673 /*
13674 * The facets are not copied but referenced
13675 * via the facet link.
13676 */
13677 facet->facet = cur->facet;
13678 facet->next = NULL;
13679 if (last == NULL)
13680 item->facetSet = facet;
13681 else
13682 last->next = facet;
13683 last = facet;
13684 }
13685 }
13686 }
13687 /*
13688 * Some optimization for validation:
13689 * If there are no facets beside the "whitespace" facet,
13690 * then a value needs not to checked against against a
13691 * facet, thus no computed value is needed.
13692 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000013693 if (item->baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013694 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13695 else {
13696 for (cur = item->facetSet; cur != NULL;
13697 cur = cur->next) {
13698 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13699 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13700 break;
13701 }
13702 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013703 }
13704 }
13705 }
13706 /*
13707 * Check constraints.
13708 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013709 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013710 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013711 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013712 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013713 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013714 case XML_SCHEMA_TYPE_ALL:
13715 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013716 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013717 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013718 case XML_SCHEMA_TYPE_GROUP:
13719 /*
13720 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
13721 */
13722 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013723 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013724 xmlSchemaParseListRefFixup(item, ctxt);
13725 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013726 break;
13727 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013728 xmlSchemaParseUnionRefCheck(item, ctxt);
13729 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013730 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013731 case XML_SCHEMA_TYPE_BASIC:
13732 case XML_SCHEMA_TYPE_ANY:
13733 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013734 case XML_SCHEMA_TYPE_UR:
13735 case XML_SCHEMA_TYPE_ELEMENT:
13736 case XML_SCHEMA_TYPE_ATTRIBUTE:
13737 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000013738 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013739 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013740 case XML_SCHEMA_FACET_MININCLUSIVE:
13741 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13742 case XML_SCHEMA_FACET_MAXINCLUSIVE:
13743 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13744 case XML_SCHEMA_FACET_TOTALDIGITS:
13745 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13746 case XML_SCHEMA_FACET_PATTERN:
13747 case XML_SCHEMA_FACET_ENUMERATION:
13748 case XML_SCHEMA_FACET_WHITESPACE:
13749 case XML_SCHEMA_FACET_LENGTH:
13750 case XML_SCHEMA_FACET_MAXLENGTH:
13751 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013752 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13753 if (item->subtypes != NULL)
13754 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013755 break;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000013756 case XML_SCHEMA_TYPE_IDC_UNIQUE:
13757 case XML_SCHEMA_TYPE_IDC_KEY:
13758 case XML_SCHEMA_TYPE_IDC_KEYREF:
13759 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013760 }
13761 }
Daniel Veillard8651f532002-04-17 09:06:27 +000013762#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013763 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013764 xmlGenericError(xmlGenericErrorContext,
13765 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013766 item->node->doc->URL,
13767 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013768 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013769 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013770 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013771 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013772 case XML_SCHEMA_CONTENT_SIMPLE:
13773 xmlGenericError(xmlGenericErrorContext, "simple\n");
13774 break;
13775 case XML_SCHEMA_CONTENT_ELEMENTS:
13776 xmlGenericError(xmlGenericErrorContext, "elements\n");
13777 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013778 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013779 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
13780 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013781 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013782 xmlGenericError(xmlGenericErrorContext, "empty\n");
13783 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013784 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013785 xmlGenericError(xmlGenericErrorContext, "mixed\n");
13786 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013787 /* Removed, since not used. */
13788 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000013789 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013790 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
13791 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013792 */
Daniel Veillard8651f532002-04-17 09:06:27 +000013793 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013794 xmlGenericError(xmlGenericErrorContext, "basic\n");
13795 break;
13796 default:
13797 xmlGenericError(xmlGenericErrorContext,
13798 "not registered !!!\n");
13799 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013800 }
13801#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013802}
13803
13804/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013805 * xmlSchemaCheckFacet:
13806 * @facet: the facet
13807 * @typeDecl: the schema type definition
13808 * @ctxt: the schema parser context or NULL
13809 * @name: name of the type
13810 *
13811 * Checks the default values types, especially for facets
13812 *
13813 * Returns 0 if okay or -1 in cae of error
13814 */
13815int
13816xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013817 xmlSchemaTypePtr typeDecl,
13818 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013819{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013820 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013821 int ret = 0, reuseValCtxt = 0;
13822
Daniel Veillardce682bc2004-11-05 17:22:25 +000013823 if ((facet == NULL) || (typeDecl == NULL))
13824 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013825 /*
13826 * TODO: will the parser context be given if used from
13827 * the relaxNG module?
13828 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013829
13830 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013831 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013832 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013833 }
13834 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013835 case XML_SCHEMA_FACET_MININCLUSIVE:
13836 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13837 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013838 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13839 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013840 /*
13841 * Okay we need to validate the value
13842 * at that point.
13843 */
13844 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013845 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013846
13847 /* 4.3.5.5 Constraints on enumeration Schema Components
13848 * Schema Component Constraint: enumeration valid restriction
13849 * It is an ·error· if any member of {value} is not in the
13850 * ·value space· of {base type definition}.
13851 *
13852 * minInclusive, maxInclusive, minExclusive, maxExclusive:
13853 * The value ·must· be in the
13854 * ·value space· of the ·base type·.
13855 */
13856 /*
13857 * This function is intended to deliver a compiled value
13858 * on the facet. In XML Schemas the type holding a facet,
13859 * cannot be a built-in type. Thus to ensure that other API
13860 * calls (relaxng) do work, if the given type is a built-in
13861 * type, we will assume that the given built-in type *is
13862 * already* the base type.
13863 */
13864 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
13865 base = typeDecl->baseType;
13866 if (base == NULL) {
13867 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013868 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013869 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013870 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013871 typeDecl->name, NULL);
13872 return (-1);
13873 }
13874 } else
13875 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013876 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013877 * This avoids perseverative creation of the
13878 * validation context if a parser context is
13879 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013880 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013881 if (ctxt != NULL) {
13882 reuseValCtxt = 1;
13883 if (ctxt->vctxt == NULL) {
13884 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13885 return (-1);
13886 }
13887 vctxt = ctxt->vctxt;
13888 } else {
13889 vctxt = xmlSchemaNewValidCtxt(NULL);
13890 if (vctxt == NULL) {
13891 xmlSchemaPErr(ctxt, typeDecl->node,
13892 XML_SCHEMAP_INTERNAL,
13893 "Internal error: xmlSchemaCheckFacet, "
13894 "creating a new validation context.\n",
13895 NULL, NULL);
13896 return (-1);
13897 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013898 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013899
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013900 vctxt->node = facet->node;
13901 vctxt->cur = NULL;
13902 /*
13903 * NOTE: This call does not check the content nodes,
13904 * since they are not available:
13905 * facet->node is just the node holding the facet
13906 * definition, *not* the attribute holding the *value*
13907 * of the facet.
13908 */
13909 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
13910 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013911 facet->val = vctxt->value;
13912 vctxt->value = NULL;
13913 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013914 /* error code */
13915 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013916 xmlSchemaPErrExt(ctxt, facet->node,
13917 XML_SCHEMAP_INVALID_FACET,
13918 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013919 "Type definition '%s': The value '%s' of the "
13920 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013921 name, facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000013922 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000013923 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013924 }
13925 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013926 } else if (ret < 0) {
13927 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013928 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013929 NULL, NULL, NULL,
13930 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013931 "failed to validate the value '%s' name of the "
13932 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013933 facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000013934 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013935 base->name, NULL, NULL);
13936 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013937 }
13938 if (reuseValCtxt == 0)
13939 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013940 break;
13941 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013942 case XML_SCHEMA_FACET_PATTERN:
13943 facet->regexp = xmlRegexpCompile(facet->value);
13944 if (facet->regexp == NULL) {
13945 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013946 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013947 "Type definition '%s': The value '%s' of the "
13948 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013949 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013950 ret = -1;
13951 }
13952 break;
13953 case XML_SCHEMA_FACET_TOTALDIGITS:
13954 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13955 case XML_SCHEMA_FACET_LENGTH:
13956 case XML_SCHEMA_FACET_MAXLENGTH:
13957 case XML_SCHEMA_FACET_MINLENGTH:{
13958 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013959
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013960 tmp =
13961 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
13962 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013963 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013964 if (tmp != 0) {
13965 /* error code */
13966 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013967 xmlSchemaPErrExt(ctxt, facet->node,
13968 XML_SCHEMAP_INVALID_FACET_VALUE,
13969 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013970 "Type definition '%s': The value '%s' of the "
13971 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013972 name, facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000013973 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000013974 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013975 }
13976 ret = -1;
13977 }
13978 break;
13979 }
13980 case XML_SCHEMA_FACET_WHITESPACE:{
13981 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
13982 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
13983 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
13984 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
13985 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
13986 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
13987 } else {
13988 if (ctxt != NULL) {
13989 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013990 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013991 "Type definition '%s': The value '%s' of the "
13992 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013993 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013994 }
13995 ret = -1;
13996 }
13997 }
13998 default:
13999 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014000 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014001 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014002}
14003
14004/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014005 * xmlSchemaCheckDefaults:
14006 * @typeDecl: the schema type definition
14007 * @ctxt: the schema parser context
14008 *
14009 * Checks the default values types, especially for facets
14010 */
14011static void
14012xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014013 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000014014{
Daniel Veillard4255d502002-04-16 15:50:10 +000014015 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014016 name = typeDecl->name;
14017 /*
14018 * NOTE: It is intended to use the facets list, instead
14019 * of facetSet.
14020 */
14021 if (typeDecl->facets != NULL) {
14022 xmlSchemaFacetPtr facet = typeDecl->facets;
14023
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014024 /*
14025 * Temporarily assign the "schema" to the validation context
14026 * of the parser context. This is needed for NOTATION validation.
14027 */
14028 if (ctxt->vctxt == NULL) {
14029 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14030 return;
14031 }
14032 ctxt->vctxt->schema = ctxt->schema;
14033
Daniel Veillard01fa6152004-06-29 17:04:39 +000014034 while (facet != NULL) {
14035 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
14036 facet = facet->next;
14037 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014038
14039 ctxt->vctxt->schema = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014040 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014041}
14042
14043/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014044 * xmlSchemaGetCircModelGrDefRef:
14045 * @ctxtGr: the searched model group
14046 * @list: the list of model groups to be processed
14047 *
14048 * This one is intended to be used by
14049 * xmlSchemaCheckGroupDefCircular only.
14050 *
14051 * Returns the circular model group definition reference, otherwise NULL.
14052 */
14053static xmlSchemaTypePtr
14054xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
14055 xmlSchemaTypePtr gr)
14056{
14057 xmlSchemaTypePtr circ = NULL;
14058 int marked;
14059 /*
14060 * We will search for an model group reference which
14061 * references the context model group definition.
14062 */
14063 while (gr != NULL) {
14064 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
14065 (gr->type == XML_SCHEMA_TYPE_ALL) ||
14066 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
14067 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
14068 (gr->subtypes != NULL)) {
14069 marked = 0;
14070 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
14071 (gr->ref != NULL)) {
14072 if (gr->subtypes == ctxtGrDef)
14073 return (gr);
14074 else if (gr->subtypes->flags &
14075 XML_SCHEMAS_TYPE_MARKED) {
14076 gr = gr->next;
14077 continue;
14078 } else {
14079 /*
14080 * Mark to avoid infinite recursion on
14081 * circular references not yet examined.
14082 */
14083 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
14084 marked = 1;
14085 }
14086 if (gr->subtypes->subtypes != NULL)
14087 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
14088 gr->subtypes->subtypes);
14089 /*
14090 * Unmark the visited model group definition.
14091 */
14092 if (marked)
14093 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
14094 if (circ != NULL)
14095 return (circ);
14096 } else {
14097 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
14098 (xmlSchemaTypePtr) gr->subtypes);
14099 if (circ != NULL)
14100 return (circ);
14101 }
14102
14103 }
14104 gr = gr->next;
14105 }
14106 return (NULL);
14107}
14108
14109/**
14110 * xmlSchemaCheckGroupDefCircular:
14111 * attrGr: the model group definition
14112 * @ctxt: the parser context
14113 * @name: the name
14114 *
14115 * Checks for circular references to model group definitions.
14116 */
14117static void
14118xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
14119 xmlSchemaParserCtxtPtr ctxt,
14120 const xmlChar * name ATTRIBUTE_UNUSED)
14121{
14122 /*
14123 * Schema Component Constraint: Model Group Correct
14124 * 2 Circular groups are disallowed. That is, within the {particles}
14125 * of a group there must not be at any depth a particle whose {term}
14126 * is the group itself.
14127 */
14128 /*
14129 * NOTE: "gr->subtypes" holds the referenced group.
14130 */
14131 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
14132 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
14133 (modelGrDef->subtypes == NULL))
14134 return;
14135 else {
14136 xmlSchemaTypePtr circ;
14137
14138 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
14139 if (circ != NULL) {
14140 /*
14141 * TODO: Report the referenced attr group as QName.
14142 */
14143 xmlSchemaPCustomErr(ctxt,
14144 XML_SCHEMAP_MG_PROPS_CORRECT_2,
14145 NULL, NULL, circ->node,
14146 "Circular reference to the model group definition '%s' "
14147 "defined", modelGrDef->name);
14148 /*
14149 * NOTE: We will cut the reference to avoid further
14150 * confusion of the processor.
14151 * TODO: SPEC: Does the spec define how to process here?
14152 */
14153 circ->subtypes = NULL;
14154 }
14155 }
14156}
14157
14158
14159/**
14160 * xmlSchemaGetCircAttrGrRef:
14161 * @ctxtGr: the searched attribute group
14162 * @attr: the current attribute list to be processed
14163 *
14164 * This one is intended to be used by
14165 * xmlSchemaCheckSRCAttributeGroupCircular only.
14166 *
14167 * Returns the circular attribute grou reference, otherwise NULL.
14168 */
14169static xmlSchemaAttributeGroupPtr
14170xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
14171 xmlSchemaAttributePtr attr)
14172{
14173 xmlSchemaAttributeGroupPtr circ = NULL, gr;
14174 int marked;
14175 /*
14176 * We will search for an attribute group reference which
14177 * references the context attribute group.
14178 */
14179 while (attr != NULL) {
14180 marked = 0;
14181 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
14182 gr = (xmlSchemaAttributeGroupPtr) attr;
14183 if (gr->refItem != NULL) {
14184 if (gr->refItem == ctxtGr)
14185 return (gr);
14186 else if (gr->refItem->flags &
14187 XML_SCHEMAS_ATTRGROUP_MARKED) {
14188 attr = attr->next;
14189 continue;
14190 } else {
14191 /*
14192 * Mark as visited to avoid infinite recursion on
14193 * circular references not yet examined.
14194 */
14195 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
14196 marked = 1;
14197 }
14198 }
14199 if (gr->attributes != NULL)
14200 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
14201 /*
14202 * Unmark the visited group's attributes.
14203 */
14204 if (marked)
14205 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
14206 if (circ != NULL)
14207 return (circ);
14208 }
14209 attr = attr->next;
14210 }
14211 return (NULL);
14212}
14213
14214/**
14215 * xmlSchemaCheckSRCAttributeGroupCircular:
14216 * attrGr: the attribute group definition
14217 * @ctxt: the parser context
14218 * @name: the name
14219 *
14220 * Checks for circular references of attribute groups.
14221 */
14222static void
14223xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
14224 xmlSchemaParserCtxtPtr ctxt,
14225 const xmlChar * name ATTRIBUTE_UNUSED)
14226{
14227 /*
14228 * Schema Representation Constraint:
14229 * Attribute Group Definition Representation OK
14230 * 3 Circular group reference is disallowed outside <redefine>.
14231 * That is, unless this element information item's parent is
14232 * <redefine>, then among the [children], if any, there must
14233 * not be an <attributeGroup> with ref [attribute] which resolves
14234 * to the component corresponding to this <attributeGroup>. Indirect
14235 * circularity is also ruled out. That is, when QName resolution
14236 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
14237 * any <attributeGroup>s with a ref [attribute] among the [children],
14238 * it must not be the case that a ·QName· is encountered at any depth
14239 * which resolves to the component corresponding to this <attributeGroup>.
14240 */
14241 /*
14242 * Only global components can be referenced.
14243 */
14244 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
14245 (attrGr->attributes == NULL))
14246 return;
14247 else {
14248 xmlSchemaAttributeGroupPtr circ;
14249
14250 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
14251 if (circ != NULL) {
14252 /*
14253 * TODO: Report the referenced attr group as QName.
14254 */
14255 xmlSchemaPCustomErr(ctxt,
14256 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
14257 NULL, NULL, circ->node,
14258 "Circular reference to the attribute group '%s' "
14259 "defined", attrGr->name);
14260 /*
14261 * NOTE: We will cut the reference to avoid further
14262 * confusion of the processor.
14263 * BADSPEC: The spec should define how to process in this case.
14264 */
14265 circ->attributes = NULL;
14266 circ->refItem = NULL;
14267 }
14268 }
14269}
14270
14271/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000014272 * xmlSchemaAttrGrpFixup:
14273 * @attrgrpDecl: the schema attribute definition
14274 * @ctxt: the schema parser context
14275 * @name: the attribute name
14276 *
14277 * Fixes finish doing the computations on the attributes definitions
14278 */
14279static void
Daniel Veillard3646d642004-06-02 19:19:14 +000014280xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014281 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000014282{
14283 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000014284 name = attrgrp->name;
14285 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014286 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000014287 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014288 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000014289
Daniel Veillardc0826a72004-08-10 14:17:33 +000014290 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
14291 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014292 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014293 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014294 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014295 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
14296 "ref", attrgrp->ref, attrgrp->refNs,
14297 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014298 return;
14299 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014300 attrgrp->refItem = ref;
14301 /*
14302 * Check for self reference!
14303 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014304 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000014305 attrgrp->attributes = ref->attributes;
14306 attrgrp->attributeWildcard = ref->attributeWildcard;
14307 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000014308}
14309
14310/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014311 * xmlSchemaAttrCheckValConstr:
14312 * @item: an schema attribute declaration/use
14313 * @ctxt: a schema parser context
14314 * @name: the name of the attribute
14315 *
14316 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000014317 *
14318 * Fixes finish doing the computations on the attributes definitions
14319 */
14320static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014321xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
14322 xmlSchemaParserCtxtPtr ctxt,
14323 const xmlChar * name ATTRIBUTE_UNUSED)
14324{
14325
14326 /*
14327 * a-props-correct
14328 * Schema Component Constraint: Attribute Declaration Properties Correct
14329 *
14330 * 2 if there is a {value constraint}, the canonical lexical
14331 * representation of its value must be ·valid· with respect
14332 * to the {type definition} as defined in String Valid (§3.14.4).
14333 */
14334
14335 if (item->defValue != NULL) {
14336 int ret;
14337 xmlNodePtr node;
14338 xmlSchemaTypePtr type;
14339
14340 if (item->subtypes == NULL) {
14341 xmlSchemaPErr(ctxt, item->node,
14342 XML_SCHEMAP_INTERNAL,
14343 "Internal error: xmlSchemaCheckAttrValConstr, "
14344 "type is missing... skipping validation of "
14345 "value constraint", NULL, NULL);
14346 return;
14347 }
14348
14349 /*
14350 * TODO: Try to avoid creating a new context.
14351 * TODO: This all is not very performant.
14352 */
14353 type = item->subtypes;
14354 /*
14355 * Ensure there's validation context.
14356 */
14357 if (ctxt->vctxt == NULL) {
14358 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
14359 xmlSchemaPErr(ctxt, item->node,
14360 XML_SCHEMAP_INTERNAL,
14361 "Internal error: xmlSchemaCheckAttrValConstr, "
14362 "creating a new validation context.\n",
14363 NULL, NULL);
14364 return;
14365 }
14366 }
14367
14368 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
14369 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
14370 else
14371 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
14372 ctxt->vctxt->node = node;
14373 ctxt->vctxt->cur = NULL;
14374 /*
14375 * NOTE: This call does not check the content nodes,
14376 * since they are not available:
14377 * facet->node is just the node holding the facet
14378 * definition, *not* the attribute holding the *value*
14379 * of the facet.
14380 */
14381 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
14382 item->defValue, 0, 1, 1, 0);
14383 if (ret == 0) {
14384 /*
14385 * Store the computed value.
14386 */
14387 item->defVal = ctxt->vctxt->value;
14388 ctxt->vctxt->value = NULL;
14389 } else if (ret > 0) {
14390 if (ctxt != NULL) {
14391 xmlSchemaPSimpleTypeErr(ctxt,
14392 XML_SCHEMAP_A_PROPS_CORRECT_2,
14393 NULL, NULL, node,
14394 type, NULL, item->defValue,
14395 NULL, NULL, NULL);
14396 }
14397 } else if (ret < 0) {
14398 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14399 NULL, NULL, node,
14400 "Internal error: xmlSchemaAttrCheckValConstr, "
14401 "failed to validate the value constraint of the "
14402 "attribute decl/use against the type '%s'",
14403 type->name);
14404 }
14405 }
14406}
14407
14408#if 0 /* Not used yet. */
14409static int
14410xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
14411 xmlSchemaElementPtr edecl)
14412{
14413 /*
14414 * TODO: 1 The values of the properties of an element declaration must be as
14415 * described in the property tableau in The Element Declaration Schema
14416 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
14417 */
14418 /*
14419 * 2 If there is a {value constraint}, the canonical lexical
14420 * representation of its value must be ·valid· with respect to the {type
14421 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14422 *
14423 * NOTE: This is done in xmlSchemaCheckElemValConstr.
14424 */
14425 /*
14426 * 3 If there is a non-·absent· {substitution group affiliation},
14427 * then {scope} must be global.
14428 *
14429 * NOTE: This is done in xmlSchemaParseElement.
14430 * TODO: Move it to this layer here.
14431 */
14432 /*
14433 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
14434 * of the element declaration must be validly derived from the {type
14435 * definition} of the {substitution group affiliation}, given the value
14436 * of the {substitution group exclusions} of the {substitution group
14437 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
14438 * (if the {type definition} is complex) or as defined in
14439 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
14440 * simple).
14441 */
14442 /*
14443 * TODO: 5 If the {type definition} or {type definition}'s {content type}
14444 * is or is derived from ID then there must not be a {value constraint}.
14445 * Note: The use of ID as a type definition for elements goes beyond
14446 * XML 1.0, and should be avoided if backwards compatibility is desired
14447 */
14448 /*
14449 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
14450 * be possible to return to an element declaration by repeatedly following
14451 * the {substitution group affiliation} property.
14452 */
14453}
14454#endif
14455
14456/**
14457 * xmlSchemaCheckElemValConstr:
14458 * @item: an schema element declaration/particle
14459 * @ctxt: a schema parser context
14460 * @name: the name of the attribute
14461 *
14462 * Validates the value constraints of an element declaration.
14463 *
14464 * Fixes finish doing the computations on the element declarations.
14465 */
14466static void
14467xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
14468 xmlSchemaParserCtxtPtr ctxt,
14469 const xmlChar * name ATTRIBUTE_UNUSED)
14470{
14471 if (decl->value != NULL) {
14472 int ret;
14473 xmlNodePtr node = NULL;
14474 xmlSchemaTypePtr type;
14475
14476 /*
14477 * 2 If there is a {value constraint}, the canonical lexical
14478 * representation of its value must be ·valid· with respect to the {type
14479 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14480 */
14481 if (decl->subtypes == NULL) {
14482 xmlSchemaPErr(ctxt, decl->node,
14483 XML_SCHEMAP_INTERNAL,
14484 "Internal error: xmlSchemaCheckElemValConstr, "
14485 "type is missing... skipping validation of "
14486 "the value constraint", NULL, NULL);
14487 return;
14488 }
14489 /*
14490 * Ensure there's a validation context.
14491 */
14492 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14493 return;
14494
14495 type = decl->subtypes;
14496
14497 if (decl->node != NULL) {
14498 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
14499 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
14500 else
14501 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
14502 }
14503 ctxt->vctxt->node = node;
14504 ctxt->vctxt->cur = NULL;
14505 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
14506 node);
14507 if (ret == 0) {
14508 /*
14509 * Consume the computed value.
14510 */
14511 decl->defVal = ctxt->vctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014512 ctxt->vctxt->value = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014513 } else if (ret < 0) {
14514 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14515 NULL, NULL, node,
14516 "Internal error: xmlSchemaElemCheckValConstr, "
14517 "failed to validate the value constraint of the "
14518 "element declaration '%s'",
14519 decl->name);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014520 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014521 }
14522}
14523
14524/**
14525 * xmlSchemaAttrFixup:
14526 * @item: an schema attribute declaration/use.
14527 * @ctxt: a schema parser context
14528 * @name: the name of the attribute
14529 *
14530 * Fixes finish doing the computations on attribute declarations/uses.
14531 */
14532static void
14533xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
14534 xmlSchemaParserCtxtPtr ctxt,
14535 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000014536{
Daniel Veillardc0826a72004-08-10 14:17:33 +000014537 /*
14538 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014539 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000014540 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014541 /*
14542 * The simple type definition corresponding to the <simpleType> element
14543 * information item in the [children], if present, otherwise the simple
14544 * type definition ·resolved· to by the ·actual value· of the type
14545 * [attribute], if present, otherwise the ·simple ur-type definition·.
14546 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014547 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014548 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014549 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
14550 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014551 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014552 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014553 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000014554
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014555 type = xmlSchemaGetType(ctxt->schema, item->typeName,
14556 item->typeNs);
14557 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014558 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014559 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014560 NULL, (xmlSchemaTypePtr) item, item->node,
14561 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014562 XML_SCHEMA_TYPE_SIMPLE, NULL);
14563 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014564 item->subtypes = type;
14565
14566 } else if (item->ref != NULL) {
14567 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000014568
Daniel Veillardc0826a72004-08-10 14:17:33 +000014569 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014570 * We have an attribute use here; assign the referenced
14571 * attribute declaration.
14572 */
14573 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014574 * TODO: Evaluate, what errors could occur if the declaration is not
14575 * found. It might be possible that the "typefixup" might crash if
14576 * no ref declaration was found.
14577 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014578 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
14579 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014580 xmlSchemaPResCompAttrErr(ctxt,
14581 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014582 NULL, (xmlSchemaTypePtr) item, item->node,
14583 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014584 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014585 return;
14586 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014587 item->refDecl = decl;
14588 xmlSchemaAttrFixup(decl, ctxt, NULL);
14589
14590 item->subtypes = decl->subtypes;
14591 /*
14592 * Attribute Use Correct
14593 * au-props-correct.2: If the {attribute declaration} has a fixed
14594 * {value constraint}, then if the attribute use itself has a
14595 * {value constraint}, it must also be fixed and its value must match
14596 * that of the {attribute declaration}'s {value constraint}.
14597 */
14598 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
14599 (item->defValue != NULL)) {
14600 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
14601 (!xmlStrEqual(item->defValue, decl->defValue))) {
14602 xmlSchemaPCustomErr(ctxt,
14603 XML_SCHEMAP_AU_PROPS_CORRECT_2,
14604 NULL, NULL, item->node,
14605 "The value constraint must be fixed "
14606 "and match the referenced attribute "
14607 "declarations's value constraint '%s'",
14608 decl->defValue);
14609 }
14610 /*
14611 * FUTURE: One should change the values of the attr. use
14612 * if ever validation should be attempted even if the
14613 * schema itself was not fully valid.
14614 */
14615 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014616 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014617 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14618 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014619}
14620
14621/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014622 * xmlSchemaResolveIDCKeyRef:
14623 * @idc: the identity-constraint definition
14624 * @ctxt: the schema parser context
14625 * @name: the attribute name
14626 *
14627 * Resolve keyRef references to key/unique IDCs.
14628 */
14629static void
14630xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
14631 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000014632 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014633{
14634 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
14635 return;
14636 if (idc->ref->name != NULL) {
14637 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
14638 ctxt->schema->idcDef,
14639 idc->ref->name,
14640 idc->ref->targetNamespace);
14641 if (idc->ref->item == NULL) {
14642 /*
14643 * TODO: It is actually not an error to fail to resolve.
14644 */
14645 xmlSchemaPResCompAttrErr(ctxt,
14646 XML_SCHEMAP_SRC_RESOLVE,
14647 NULL, (xmlSchemaTypePtr) idc, idc->node,
14648 "refer", idc->ref->name,
14649 idc->ref->targetNamespace,
14650 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
14651 return;
14652 }
14653 }
14654}
14655
14656/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014657 * xmlSchemaParse:
14658 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014659 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014660 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000014661 * XML Shema struture which can be used to validate instances.
14662 * *WARNING* this interface is highly subject to change
14663 *
14664 * Returns the internal XML Schema structure built from the resource or
14665 * NULL in case of error
14666 */
14667xmlSchemaPtr
14668xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
14669{
14670 xmlSchemaPtr ret = NULL;
14671 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014672 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014673 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014674
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014675 /*
14676 * This one is used if the schema to be parsed was specified via
14677 * the API; i.e. not automatically by the validated instance document.
14678 */
14679
Daniel Veillard4255d502002-04-16 15:50:10 +000014680 xmlSchemaInitTypes();
14681
Daniel Veillard6045c902002-10-09 21:13:59 +000014682 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000014683 return (NULL);
14684
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014685 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014686 ctxt->counter = 0;
14687 ctxt->container = NULL;
14688
14689 /*
14690 * First step is to parse the input document into an DOM/Infoset
14691 */
Daniel Veillard6045c902002-10-09 21:13:59 +000014692 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014693 doc = xmlReadFile((const char *) ctxt->URL, NULL,
14694 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014695 if (doc == NULL) {
14696 xmlSchemaPErr(ctxt, NULL,
14697 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014698 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014699 ctxt->URL, NULL);
14700 return (NULL);
14701 }
Daniel Veillard6045c902002-10-09 21:13:59 +000014702 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014703 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
14704 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014705 if (doc == NULL) {
14706 xmlSchemaPErr(ctxt, NULL,
14707 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014708 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014709 NULL, NULL);
14710 return (NULL);
14711 }
14712 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000014713 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000014714 } else if (ctxt->doc != NULL) {
14715 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014716 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000014717 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014718 xmlSchemaPErr(ctxt, NULL,
14719 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014720 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014721 NULL, NULL);
14722 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014723 }
14724
14725 /*
14726 * Then extract the root and Schema parse it
14727 */
14728 root = xmlDocGetRootElement(doc);
14729 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014730 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
14731 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014732 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000014733 if (!preserve) {
14734 xmlFreeDoc(doc);
14735 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014736 return (NULL);
14737 }
14738
14739 /*
14740 * Remove all the blank text nodes
14741 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014742 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000014743
14744 /*
14745 * Then do the parsing for good
14746 */
14747 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000014748 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000014749 if (!preserve) {
14750 xmlFreeDoc(doc);
14751 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014752 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000014753 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014754 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014755 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000014756 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014757 ctxt->ctxtType = NULL;
14758 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000014759 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000014760 * Then fixup all attributes declarations
14761 */
14762 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
14763
14764 /*
14765 * Then fixup all attributes group declarations
14766 */
14767 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
14768 ctxt);
14769
14770 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014771 * Resolve identity-constraint keyRefs.
14772 */
14773 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
14774
14775 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014776 * Check attribute groups for circular references.
14777 */
14778 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
14779 xmlSchemaCheckAttributeGroupCircular, ctxt);
14780
14781 /*
14782 * Then fixup all model group definitions.
14783 */
14784 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014785
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014786 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000014787 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000014788 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014789 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014790
14791 /*
14792 * Then fix references of element declaration; apply constraints.
14793 */
14794 xmlHashScanFull(ret->elemDecl,
14795 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014796
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014797 /*
14798 * Check model groups defnitions for circular references.
14799 */
14800 xmlHashScan(ret->groupDecl, (xmlHashScanner)
14801 xmlSchemaCheckGroupDefCircular, ctxt);
14802
Daniel Veillard4255d502002-04-16 15:50:10 +000014803 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014804 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000014805 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014806 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014807 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014808
14809 /*
14810 * Then check the defaults part of the type like facets values
14811 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014812 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000014813
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014814 /*
14815 * Validate the value constraint of attribute declarations/uses.
14816 */
14817 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
14818
14819 /*
14820 * Validate the value constraint of element declarations.
14821 */
14822 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
14823
Daniel Veillardc0826a72004-08-10 14:17:33 +000014824
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014825 if (ctxt->nberrors != 0) {
14826 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014827 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014828 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014829 return (ret);
14830}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014831
Daniel Veillard4255d502002-04-16 15:50:10 +000014832/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000014833 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000014834 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000014835 * @err: the error callback
14836 * @warn: the warning callback
14837 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000014838 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014839 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014840 */
14841void
14842xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014843 xmlSchemaValidityErrorFunc err,
14844 xmlSchemaValidityWarningFunc warn, void *ctx)
14845{
Daniel Veillard4255d502002-04-16 15:50:10 +000014846 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014847 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000014848 ctxt->error = err;
14849 ctxt->warning = warn;
14850 ctxt->userData = ctx;
14851}
14852
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014853/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000014854 * xmlSchemaGetParserErrors:
14855 * @ctxt: a XMl-Schema parser context
14856 * @err: the error callback result
14857 * @warn: the warning callback result
14858 * @ctx: contextual data for the callbacks result
14859 *
14860 * Get the callback information used to handle errors for a parser context
14861 *
14862 * Returns -1 in case of failure, 0 otherwise
14863 */
14864int
14865xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
14866 xmlSchemaValidityErrorFunc * err,
14867 xmlSchemaValidityWarningFunc * warn, void **ctx)
14868{
14869 if (ctxt == NULL)
14870 return(-1);
14871 if (err != NULL)
14872 *err = ctxt->error;
14873 if (warn != NULL)
14874 *warn = ctxt->warning;
14875 if (ctx != NULL)
14876 *ctx = ctxt->userData;
14877 return(0);
14878}
14879
14880/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014881 * xmlSchemaFacetTypeToString:
14882 * @type: the facet type
14883 *
14884 * Convert the xmlSchemaTypeType to a char string.
14885 *
14886 * Returns the char string representation of the facet type if the
14887 * type is a facet and an "Internal Error" string otherwise.
14888 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014889static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014890xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
14891{
14892 switch (type) {
14893 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014894 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014895 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014896 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014897 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014898 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014899 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014900 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014901 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014902 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014903 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014904 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014905 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014906 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014907 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014908 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014909 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014910 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014911 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014912 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014913 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014914 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014915 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014916 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014917 default:
14918 break;
14919 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014920 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014921}
14922
Daniel Veillardc0826a72004-08-10 14:17:33 +000014923static int
14924xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
14925{
14926 xmlSchemaTypePtr anc;
14927
14928 /*
14929 * The normalization type can be changed only for types which are derived
14930 * from xsd:string.
14931 */
14932 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000014933 if (type->builtInType == XML_SCHEMAS_STRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014934 return(XML_SCHEMAS_FACET_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000014935 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014936 return(XML_SCHEMAS_FACET_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014937 else {
14938 /*
14939 * For all ·atomic· datatypes other than string (and types ·derived·
14940 * by ·restriction· from it) the value of whiteSpace is fixed to
14941 * collapse
14942 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014943 return(XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014944 }
14945 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14946 /*
14947 * For list types the facet "whiteSpace" is fixed to "collapse".
14948 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014949 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014950 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014951 return (XML_SCHEMAS_FACET_UNKNOWN);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014952 } else if (type->facetSet != NULL) {
14953 xmlSchemaTypePtr anyST;
14954 xmlSchemaFacetLinkPtr lin;
14955
14956 /*
14957 * Atomic types.
14958 */
14959 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14960 anc = type->baseType;
14961 do {
14962 /*
14963 * For all ·atomic· datatypes other than string (and types ·derived·
14964 * by ·restriction· from it) the value of whiteSpace is fixed to
14965 * collapse
14966 */
14967 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
14968 (anc->builtInType == XML_SCHEMAS_STRING)) {
14969
14970 lin = type->facetSet;
14971 do {
14972 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014973 return(lin->facet->whitespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014974 break;
14975 }
14976 lin = lin->next;
14977 } while (lin != NULL);
14978 break;
14979 }
14980 anc = anc->baseType;
14981 } while (anc != anyST);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000014982 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014983 }
14984 return (-1);
14985}
14986
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014987/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000014988 * xmlSchemaValidateFacetsInternal:
14989 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000014990 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000014991 * @facets: the list of facets to check
14992 * @value: the lexical repr of the value to validate
14993 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000014994 * @fireErrors: if 0, only internal errors will be fired;
14995 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000014996 *
14997 * Check a value against all facet conditions
14998 *
14999 * Returns 0 if the element is schemas valid, a positive error code
15000 * number otherwise and -1 in case of internal or API error.
15001 */
15002static int
15003xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015004 xmlSchemaTypePtr type,
15005 const xmlChar * value,
15006 unsigned long length,
15007 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000015008{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015009 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015010 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015011 xmlSchemaTypePtr biType; /* The build-in type. */
15012 xmlSchemaTypePtr tmpType;
15013 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000015014 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015015 xmlSchemaFacetPtr facet;
15016 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015017
Daniel Veillardc0826a72004-08-10 14:17:33 +000015018#ifdef DEBUG_UNION_VALIDATION
15019 printf("Facets of type: '%s'\n", (const char *) type->name);
15020 printf(" fireErrors: %d\n", fireErrors);
15021#endif
15022
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015023 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015024 /*
15025 * NOTE: Do not jump away, if the facetSet of the given type is
15026 * empty: until now, "pattern" facets of the *base types* need to
15027 * be checked as well.
15028 */
15029 biType = type->baseType;
15030 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
15031 biType = biType->baseType;
15032 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015033 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015034 "Internal error: xmlSchemaValidateFacetsInternal, "
15035 "the base type axis of the given type '%s' does not resolve to "
15036 "a built-in type.\n",
15037 type->name, NULL);
15038 return (-1);
15039 }
15040
15041 if (type->facetSet != NULL) {
15042 facetLink = type->facetSet;
15043 while (facetLink != NULL) {
15044 facet = facetLink->facet;
15045 /*
15046 * Skip the pattern "whiteSpace": it is used to
15047 * format the character content beforehand.
15048 */
15049 switch (facet->type) {
15050 case XML_SCHEMA_FACET_WHITESPACE:
15051 case XML_SCHEMA_FACET_PATTERN:
15052 case XML_SCHEMA_FACET_ENUMERATION:
15053 break;
15054 case XML_SCHEMA_FACET_LENGTH:
15055 case XML_SCHEMA_FACET_MINLENGTH:
15056 case XML_SCHEMA_FACET_MAXLENGTH:
15057 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15058 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
15059 value, length, 0);
15060 len = length;
15061 } else
15062 ret = xmlSchemaValidateLengthFacet(biType, facet,
15063 value, ctxt->value, &len);
15064 break;
15065 default:
15066 ret = xmlSchemaValidateFacet(biType, facet, value,
15067 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015068 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015069 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015070 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015071 "Internal error: xmlSchemaValidateFacetsInternal, "
15072 "validating facet of type '%s'.\n",
15073 type->name, NULL);
15074 break;
15075 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015076 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015077 type, facet, NULL, NULL, NULL, NULL);
15078 }
15079
15080 facetLink = facetLink->next;
15081 }
15082 if (ret >= 0) {
15083 /*
15084 * Process enumerations.
15085 */
15086 retFacet = 0;
15087 facetLink = type->facetSet;
15088 while (facetLink != NULL) {
15089 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
15090 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
15091 value, ctxt->value);
15092 if (retFacet <= 0)
15093 break;
15094 }
15095 facetLink = facetLink->next;
15096 }
15097 if (retFacet > 0) {
15098 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
15099 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015100 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015101 value, 0, type, NULL, NULL, NULL, NULL, NULL);
15102 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015103 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015104 "Internal error: xmlSchemaValidateFacetsInternal, "
15105 "validating facet of type '%s'.\n",
15106 BAD_CAST "enumeration", NULL);
15107 ret = -1;
15108 }
15109 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015110 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015111 if (ret >= 0) {
15112 /*
15113 * Process patters. Pattern facets are ORed at type level
15114 * and ANDed if derived. Walk the base type axis.
15115 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015116 tmpType = type;
15117 facet = NULL;
15118 do {
15119 retFacet = 0;
15120 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015121 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015122 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
15123 continue;
15124 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
15125 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015126 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015127 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015128 else if (retFacet < 0) {
15129 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
15130 "Internal error: xmlSchemaValidateFacetsInternal, "
15131 "validating 'pattern' facet '%s' of type '%s'.\n",
15132 facetLink->facet->value, tmpType->name);
15133 ret = -1;
15134 break;
15135 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000015136 /* Save the last non-validating facet. */
15137 facet = facetLink->facet;
15138 }
15139 if (retFacet != 0)
15140 break;
15141 tmpType = tmpType->baseType;
15142 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015143 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015144 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
15145 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015146 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015147 NULL, NULL, NULL, NULL);
15148 }
15149 }
15150 }
15151
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015152 return (ret);
15153}
15154
Daniel Veillard4255d502002-04-16 15:50:10 +000015155/************************************************************************
15156 * *
15157 * Simple type validation *
15158 * *
15159 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000015160
Daniel Veillard4255d502002-04-16 15:50:10 +000015161
15162/************************************************************************
15163 * *
15164 * DOM Validation code *
15165 * *
15166 ************************************************************************/
15167
Daniel Veillard4255d502002-04-16 15:50:10 +000015168static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015169 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000015170 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015171static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015172 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000015173 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015174 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000015175
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015176static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015177static int xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015178
15179#ifdef ELEM_INFO_ENABLED
15180/**
15181 * xmlSchemaGetFreshElemInfo:
15182 * @vctxt: the schema validation context
15183 *
15184 * Creates/reuses and initializes the element info item for
15185 * the currect tree depth.
15186 *
15187 * Returns the element info item or NULL on API or internal errors.
15188 */
15189static xmlSchemaElemInfoPtr
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015190xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt,
15191 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015192{
15193 xmlSchemaElemInfoPtr info = NULL;
15194
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015195 if (depth > vctxt->sizeElemInfos) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015196 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015197 "Internal error: xmlSchemaGetFreshElemInfo, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015198 "an inconsistent depth encountered.\n",
15199 NULL, NULL);
15200 return (NULL);
15201 }
15202 if (vctxt->elemInfos == NULL) {
15203 vctxt->elemInfos = (xmlSchemaElemInfoPtr *)
15204 xmlMalloc(10 * sizeof(xmlSchemaElemInfoPtr));
15205 if (vctxt->elemInfos == NULL) {
15206 xmlSchemaVErrMemory(vctxt,
15207 "allocating the element info array", NULL);
15208 return (NULL);
15209 }
15210 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaElemInfoPtr));
15211 vctxt->sizeElemInfos = 10;
15212 } else if (vctxt->sizeElemInfos == vctxt->depth) {
15213 int i = vctxt->sizeElemInfos;
15214
15215 vctxt->sizeElemInfos *= 2;
15216 vctxt->elemInfos = (xmlSchemaElemInfoPtr *)
15217 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
15218 sizeof(xmlSchemaElemInfoPtr));
15219 if (vctxt->elemInfos == NULL) {
15220 xmlSchemaVErrMemory(vctxt,
15221 "re-allocating the element info array", NULL);
15222 return (NULL);
15223 }
15224 /*
15225 * We need the new memory to be NULLed.
15226 * TODO: Use memset instead?
15227 */
15228 for (; i < vctxt->sizeElemInfos; i++)
15229 vctxt->elemInfos[i] = NULL;
15230 } else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015231 info = vctxt->elemInfos[depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015232
15233 if (info == NULL) {
15234 info = (xmlSchemaElemInfoPtr)
15235 xmlMalloc(sizeof(xmlSchemaElemInfo));
15236 if (info == NULL) {
15237 xmlSchemaVErrMemory(vctxt,
15238 "allocating an element info", NULL);
15239 return (NULL);
15240 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015241 vctxt->elemInfos[depth] = info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015242 }
15243 memset(info, 0, sizeof(xmlSchemaElemInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015244 info->depth = depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015245
15246 return (info);
15247}
15248#endif /* ELEM_INFO_ENABLED */
15249
Daniel Veillard3646d642004-06-02 19:19:14 +000015250
15251/**
15252 * xmlSchemaFreeAttrStates:
15253 * @state: a list of attribute states
15254 *
15255 * Free the given list of attribute states
15256 *
15257 */
15258static void
15259xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
15260{
15261 xmlSchemaAttrStatePtr tmp;
15262 while (state != NULL) {
15263 tmp = state;
15264 state = state->next;
15265 xmlFree(tmp);
15266 }
15267}
15268
Daniel Veillard4255d502002-04-16 15:50:10 +000015269/**
15270 * xmlSchemaRegisterAttributes:
15271 * @ctxt: a schema validation context
15272 * @attrs: a list of attributes
15273 *
15274 * Register the list of attributes as the set to be validated on that element
15275 *
15276 * Returns -1 in case of error, 0 otherwise
15277 */
15278static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015279xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
15280{
Daniel Veillard3646d642004-06-02 19:19:14 +000015281 xmlSchemaAttrStatePtr tmp;
15282
15283 ctxt->attr = NULL;
15284 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015285 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015286 if ((attrs->ns != NULL) &&
15287 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
15288 attrs = attrs->next;
15289 continue;
15290 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015291 tmp = (xmlSchemaAttrStatePtr)
15292 xmlMalloc(sizeof(xmlSchemaAttrState));
15293 if (tmp == NULL) {
15294 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
15295 return (-1);
15296 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015297 tmp->attr = attrs;
15298 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
15299 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015300 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015301 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015302 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000015303 else
15304 ctxt->attrTop->next = tmp;
15305 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015306 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015307 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015308 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000015309}
15310
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015311#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000015312/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015313 * xmlSchemaValidateCheckNodeList
15314 * @nodelist: the list of nodes
15315 *
15316 * Check the node list is only made of text nodes and entities pointing
15317 * to text nodes
15318 *
15319 * Returns 1 if true, 0 if false and -1 in case of error
15320 */
15321static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015322xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
15323{
Daniel Veillard4255d502002-04-16 15:50:10 +000015324 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015325 if (nodelist->type == XML_ENTITY_REF_NODE) {
15326 TODO /* implement recursion in the entity content */
15327 }
15328 if ((nodelist->type != XML_TEXT_NODE) &&
15329 (nodelist->type != XML_COMMENT_NODE) &&
15330 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000015331 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015332 return (0);
15333 }
15334 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015335 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015336 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015337}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015338#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015339
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015340static void
15341xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
15342{
15343 int i, nbItems;
15344 xmlSchemaTypePtr item, *items;
15345
15346
15347 /*
15348 * During the Assemble of the schema ctxt->curItems has
15349 * been filled with the relevant new items. Fix those up.
15350 */
15351 nbItems = ctxt->assemble->nbItems;
15352 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
15353
15354 for (i = 0; i < nbItems; i++) {
15355 item = items[i];
15356 switch (item->type) {
15357 case XML_SCHEMA_TYPE_ATTRIBUTE:
15358 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
15359 break;
15360 case XML_SCHEMA_TYPE_ELEMENT:
15361 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
15362 NULL, NULL, NULL);
15363 break;
15364 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15365 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
15366 ctxt, NULL);
15367 break;
15368 case XML_SCHEMA_TYPE_GROUP:
15369 xmlSchemaGroupDefFixup(item, ctxt, NULL);
15370 default:
15371 break;
15372 }
15373 }
15374 /*
15375 * Circularity checks.
15376 */
15377 for (i = 0; i < nbItems; i++) {
15378 item = items[i];
15379 switch (item->type) {
15380 case XML_SCHEMA_TYPE_GROUP:
15381 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
15382 break;
15383 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15384 xmlSchemaCheckAttributeGroupCircular(
15385 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
15386 break;
15387 default:
15388 break;
15389 }
15390 }
15391 /*
15392 * Fixup for all other item.
15393 * TODO: Hmm, not sure if starting from complex/simple types,
15394 * all subsequent items will be reached.
15395 */
15396 for (i = 0; i < nbItems; i++) {
15397 item = items[i];
15398 switch (item->type) {
15399 case XML_SCHEMA_TYPE_SIMPLE:
15400 case XML_SCHEMA_TYPE_COMPLEX:
15401 xmlSchemaTypeFixup(item, ctxt, NULL);
15402 break;
15403 default:
15404 break;
15405 }
15406 }
15407 /*
15408 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015409 * hold by simple type components only (and
15410 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015411 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015412 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015413 for (i = 0; i < nbItems; i++) {
15414 item = items[i];
15415 switch (item->type) {
15416 case XML_SCHEMA_TYPE_SIMPLE:
15417 case XML_SCHEMA_TYPE_COMPLEX:
15418 xmlSchemaCheckDefaults(item, ctxt, NULL);
15419 break;
15420 default:
15421 break;
15422 }
15423 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015424 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015425 /*
15426 * Build the content model for complex types.
15427 */
15428 for (i = 0; i < nbItems; i++) {
15429 item = items[i];
15430 switch (item->type) {
15431 case XML_SCHEMA_TYPE_COMPLEX:
15432 xmlSchemaBuildContentModel(item, ctxt, NULL);
15433 break;
15434 default:
15435 break;
15436 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015437 }
15438 /*
15439 * Validate value contraint values.
15440 */
15441 for (i = 0; i < nbItems; i++) {
15442 item = items[i];
15443 switch (item->type) {
15444 case XML_SCHEMA_TYPE_ATTRIBUTE:
15445 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
15446 break;
15447 case XML_SCHEMA_TYPE_ELEMENT:
15448 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
15449 break;
15450 default:
15451 break;
15452 }
15453 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015454}
15455
15456/**
15457 * xmlSchemaAssembleByLocation:
15458 * @pctxt: a schema parser context
15459 * @vctxt: a schema validation context
15460 * @schema: the existing schema
15461 * @node: the node that fired the assembling
15462 * @nsName: the namespace name of the new schema
15463 * @location: the location of the schema
15464 *
15465 * Expands an existing schema by an additional schema.
15466 *
15467 * Returns 0 if the new schema is correct, a positive error code
15468 * number otherwise and -1 in case of an internal or API error.
15469 */
15470static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015471xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
15472 xmlSchemaPtr schema,
15473 xmlNodePtr node,
15474 const xmlChar *nsName,
15475 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015476{
15477 const xmlChar *targetNs, *oldtns;
15478 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015479 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015480 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015481 xmlSchemaParserCtxtPtr pctxt;
15482
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015483 /*
15484 * This should be used:
15485 * 1. on <import>(s)
15486 * 2. if requested by the validated instance
15487 * 3. if requested via the API
15488 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015489 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015490 return (-1);
15491 /*
15492 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015493 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015494 if ((vctxt->pctxt == NULL) &&
15495 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
15496 xmlSchemaVErr(vctxt, node,
15497 XML_SCHEMAV_INTERNAL,
15498 "Internal error: xmlSchemaAssembleByLocation, "
15499 "failed to create a temp. parser context.\n",
15500 NULL, NULL);
15501 return (-1);
15502 }
15503 pctxt = vctxt->pctxt;
15504 /*
15505 * Set the counter to produce unique names for anonymous items.
15506 */
15507 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015508 /*
15509 * Acquire the schema document.
15510 */
15511 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
15512 nsName, location, &doc, &targetNs, 0);
15513 if (ret != 0) {
15514 if (doc != NULL)
15515 xmlFreeDoc(doc);
15516 } else if (doc != NULL) {
15517 docElem = xmlDocGetRootElement(doc);
15518 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015519 * Create new assemble info.
15520 */
15521 if (pctxt->assemble == NULL) {
15522 pctxt->assemble = xmlSchemaNewAssemble();
15523 if (pctxt->assemble == NULL) {
15524 xmlSchemaVErrMemory(vctxt,
15525 "Memory error: xmlSchemaAssembleByLocation, "
15526 "allocating assemble info", NULL);
15527 xmlFreeDoc(doc);
15528 return (-1);
15529 }
15530 }
15531 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015532 * Save and reset the context & schema.
15533 */
15534 oldflags = schema->flags;
15535 oldtns = schema->targetNamespace;
15536 olddoc = schema->doc;
15537
15538 xmlSchemaClearSchemaDefaults(schema);
15539 schema->targetNamespace = targetNs;
15540 /* schema->nbCurItems = 0; */
15541 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015542 pctxt->ctxtType = NULL;
15543 pctxt->parentItem = NULL;
15544
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015545 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
15546 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015547 xmlSchemaPostSchemaAssembleFixup(pctxt);
15548 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015549 * Set the counter of items.
15550 */
15551 schema->counter = pctxt->counter;
15552 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015553 * Free the list of assembled components.
15554 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015555 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015556 /*
15557 * Restore the context & schema.
15558 */
15559 schema->flags = oldflags;
15560 schema->targetNamespace = oldtns;
15561 schema->doc = olddoc;
15562 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015563 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015564 return (ret);
15565}
15566
15567/**
15568 * xmlSchemaAssembleByXSIAttr:
15569 * @vctxt: a schema validation context
15570 * @xsiAttr: an xsi attribute
15571 * @noNamespace: whether a schema with no target namespace is exptected
15572 *
15573 * Expands an existing schema by an additional schema using
15574 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
15575 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
15576 * must be set to 1.
15577 *
15578 * Returns 0 if the new schema is correct, a positive error code
15579 * number otherwise and -1 in case of an internal or API error.
15580 */
15581static int
15582xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
15583 xmlAttrPtr xsiAttr,
15584 int noNamespace)
15585{
15586 xmlChar *value;
15587 const xmlChar *cur, *end;
15588 const xmlChar *nsname = NULL, *location;
15589 int count = 0;
15590 int ret = 0;
15591
15592 if (xsiAttr == NULL) {
15593 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
15594 NULL, NULL,
15595 "Internal error: xmlSchemaAssembleByXSIAttr, "
15596 "bad arguments", NULL);
15597 return (-1);
15598 }
15599 /*
15600 * Parse the value; we will assume an even number of values
15601 * to be given (this is how Xerces and XSV work).
15602 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015603 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015604 cur = value;
15605 do {
15606 if (noNamespace != 1) {
15607 /*
15608 * Get the namespace name.
15609 */
15610 while (IS_BLANK_CH(*cur))
15611 cur++;
15612 end = cur;
15613 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15614 end++;
15615 if (end == cur)
15616 break;
15617 count++;
15618 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
15619 cur = end;
15620 }
15621 /*
15622 * Get the URI.
15623 */
15624 while (IS_BLANK_CH(*cur))
15625 cur++;
15626 end = cur;
15627 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15628 end++;
15629 if (end == cur)
15630 break;
15631 count++;
15632 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015633 cur = end;
15634 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015635 xsiAttr->parent, nsname, location);
15636 if (ret == -1) {
15637 xmlSchemaVCustomErr(vctxt,
15638 XML_SCHEMAV_INTERNAL,
15639 (xmlNodePtr) xsiAttr, NULL,
15640 "Internal error: xmlSchemaAssembleByXSIAttr, "
15641 "assembling schemata", NULL);
15642 if (value != NULL)
15643 xmlFree(value);
15644 return (-1);
15645 }
15646 } while (*cur != 0);
15647 if (value != NULL)
15648 xmlFree(value);
15649 return (ret);
15650}
15651
15652/**
15653 * xmlSchemaAssembleByXSIElem:
15654 * @vctxt: a schema validation context
15655 * @elem: an element node possibly holding xsi attributes
15656 * @noNamespace: whether a schema with no target namespace is exptected
15657 *
15658 * Assembles an existing schema by an additional schema using
15659 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
15660 * of the given @elem.
15661 *
15662 * Returns 0 if the new schema is correct, a positive error code
15663 * number otherwise and -1 in case of an internal or API error.
15664 */
15665static int
15666xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
15667 xmlNodePtr elem)
15668{
15669 int ret = 0, retNs = 0;
15670 xmlAttrPtr attr;
15671
15672 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
15673 if (attr != NULL) {
15674 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
15675 if (retNs == -1)
15676 return (-1);
15677 }
15678 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
15679 if (attr != NULL) {
15680 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
15681 if (ret == -1)
15682 return (-1);
15683 }
15684 if (retNs != 0)
15685 return (retNs);
15686 else
15687 return (ret);
15688}
15689
Daniel Veillard4255d502002-04-16 15:50:10 +000015690/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015691 * xmlSchemaValidateCallback:
15692 * @ctxt: a schema validation context
15693 * @name: the name of the element detected (might be NULL)
15694 * @type: the type
15695 *
15696 * A transition has been made in the automata associated to an element
15697 * content model
15698 */
15699static void
15700xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015701 const xmlChar * name ATTRIBUTE_UNUSED,
15702 xmlSchemaTypePtr type, xmlNodePtr node)
15703{
Daniel Veillard4255d502002-04-16 15:50:10 +000015704 xmlSchemaTypePtr oldtype = ctxt->type;
15705 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015706
Daniel Veillard4255d502002-04-16 15:50:10 +000015707#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000015708 xmlGenericError(xmlGenericErrorContext,
15709 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015710 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000015711#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015712 /*
15713 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
15714 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015715 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015716 ctxt->node = node;
15717 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015718
15719#ifdef ELEM_INFO_ENABLED
15720 xmlSchemaBeginElement(ctxt);
15721#endif
15722
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015723 /*
15724 * Assemble new schemata using xsi.
15725 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015726 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015727 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015728
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015729 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15730 if (ret == -1) {
15731 xmlSchemaVCustomErr(ctxt,
15732 XML_SCHEMAV_INTERNAL,
15733 ctxt->node, NULL,
15734 "Internal error: xmlSchemaValidateElement, "
15735 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015736 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015737 }
15738 /*
15739 * NOTE: We won't react on schema parser errors here.
15740 * TODO: But a warning would be nice.
15741 */
15742 }
15743 switch (type->type) {
15744 case XML_SCHEMA_TYPE_ELEMENT: {
15745 /*
15746 * NOTE: The build of the content model
15747 * (xmlSchemaBuildAContentModel) ensures that the element
15748 * declaration (and not a reference to it) will be given.
15749 */
15750 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
15751 /*
15752 * This is paranoid coding ;-)... it should not
15753 * happen here any more.
15754 */
15755 xmlSchemaVCustomErr(ctxt,
15756 XML_SCHEMAV_INTERNAL,
15757 node, NULL,
15758 "Internal error: xmlSchemaValidateCallback, "
15759 "element declaration 'reference' encountered, "
15760 "but an element declaration was expected",
15761 NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015762 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015763 }
15764 xmlSchemaValidateElementByDeclaration(ctxt,
15765 (xmlSchemaElementPtr) type);
15766 break;
15767 }
15768 case XML_SCHEMA_TYPE_ANY:
15769 xmlSchemaValidateElementByWildcard(ctxt, type);
15770 break;
15771 default:
15772 break;
15773 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015774leave:
15775
15776#ifdef ELEM_INFO_ENABLED
15777 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015778#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015779 ctxt->type = oldtype;
15780 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015781}
Daniel Veillard4255d502002-04-16 15:50:10 +000015782
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015783static int
15784xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
15785 const xmlChar *value,
15786 xmlSchemaValPtr *val,
15787 xmlNodePtr node)
15788{
15789 int ret;
15790
15791 ret = xmlValidateQName(value, 1);
15792 if (ret != 0)
15793 return (ret);
15794
15795 {
15796 xmlChar *uri = NULL;
15797 xmlChar *local = NULL;
15798 xmlChar *prefix;
15799
15800 local = xmlSplitQName2(value, &prefix);
15801 if (prefix != NULL) {
15802 xmlNsPtr ns;
15803
15804 /*
15805 * TODO: Make this streamable.
15806 */
15807 if ((node == NULL) || (node->doc == NULL)) {
15808 xmlFree(prefix);
15809 xmlFree(local);
15810 return (3);
15811 }
15812
15813 ns = xmlSearchNs(node->doc, node, prefix);
15814 if (ns == NULL) {
15815 xmlFree(prefix);
15816 xmlFree(local);
15817 return (1);
15818 }
15819 }
15820 if (prefix != NULL) {
15821 if (xmlHashLookup2(vctxt->schema->notaDecl, local, uri) == NULL)
15822 ret = 1;
15823 } else if (xmlHashLookup2(vctxt->schema->notaDecl, value,
15824 NULL) == NULL)
15825 ret = 1;
15826
15827 if ((ret == 0) && (val != NULL)) {
15828 if (prefix != NULL) {
15829 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST local,
15830 BAD_CAST xmlStrdup(uri));
15831 local = NULL;
15832 } else
15833 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST xmlStrdup(value),
15834 NULL);
15835 if (*val == NULL)
15836 ret = -1;
15837 }
15838 if (local != NULL)
15839 xmlFree(local);
15840 }
15841
15842 return (ret);
15843}
15844
Daniel Veillard01fa6152004-06-29 17:04:39 +000015845/**
15846 * xmlSchemaValidateSimpleTypeValue:
15847 * @ctxt: a schema validation context
15848 * @value: the value to be validated
15849 * @fireErrors: shall errors be reported?
15850 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015851 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015852 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000015853 *
15854 * Validates a value by the given type (user derived or built-in).
15855 *
15856 * Returns 0 if the value is valid, a positive error code
15857 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015858 */
15859static int
15860xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015861 xmlSchemaTypePtr type,
15862 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015863 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015864 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015865 int normalize,
15866 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015867{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015868 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015869 int ret = 0;
15870 xmlChar *normValue = NULL;
15871 int wtsp;
15872
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015873 node = ctxt->node;
15874 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015875 wtsp = ctxt->valueWS;
15876 /*
15877 * Normalize the value.
15878 */
15879 if (normalize &&
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015880 (ctxt->valueWS != XML_SCHEMAS_FACET_COLLAPSE)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015881 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
15882
15883 if ((norm != -1) && (norm > ctxt->valueWS)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015884 if (norm == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015885 normValue = xmlSchemaCollapseString(value);
15886 else
15887 normValue = xmlSchemaWhiteSpaceReplace(value);
15888 ctxt->valueWS = norm;
15889 if (normValue != NULL)
15890 value = (const xmlChar *) normValue;
15891 }
15892 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015893 /*
15894 * The nodes of a content must be checked only once,
15895 * this is not working since list types will fire this
15896 * multiple times.
15897 */
15898 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
15899 xmlNodePtr cur = ctxt->cur;
15900
15901 do {
15902 switch (cur->type) {
15903 case XML_TEXT_NODE:
15904 case XML_CDATA_SECTION_NODE:
15905 case XML_PI_NODE:
15906 case XML_COMMENT_NODE:
15907 case XML_XINCLUDE_START:
15908 case XML_XINCLUDE_END:
15909 break;
15910 case XML_ENTITY_REF_NODE:
15911 case XML_ENTITY_NODE:
15912 /* TODO: Scour the entities for illegal nodes. */
15913 TODO break;
15914 case XML_ELEMENT_NODE: {
15915 /* NOTE: Changed to an internal error, since the
15916 * existence of an element node will be already checked in
15917 * xmlSchemaValidateElementBySimpleType and in
15918 * xmlSchemaValidateElementByComplexType.
15919 */
15920 xmlSchemaVCustomErr(ctxt,
15921 XML_SCHEMAV_INTERNAL,
15922 /* XML_SCHEMAS_ERR_INVALIDELEM, */
15923 node, type,
15924 "Element '%s' found in simple type content",
15925 cur->name);
15926 return (XML_SCHEMAV_INTERNAL);
15927 }
15928 case XML_ATTRIBUTE_NODE:
15929 case XML_DOCUMENT_NODE:
15930 case XML_DOCUMENT_TYPE_NODE:
15931 case XML_DOCUMENT_FRAG_NODE:
15932 case XML_NOTATION_NODE:
15933 case XML_HTML_DOCUMENT_NODE:
15934 case XML_DTD_NODE:
15935 case XML_ELEMENT_DECL:
15936 case XML_ATTRIBUTE_DECL:
15937 case XML_ENTITY_DECL:
15938 case XML_NAMESPACE_DECL:
15939#ifdef LIBXML_DOCB_ENABLED
15940 case XML_DOCB_DOCUMENT_NODE:
15941#endif
15942 xmlSchemaVCustomErr(ctxt,
15943 XML_SCHEMAV_INTERNAL,
15944 /* XML_SCHEMAS_ERR_INVALIDELEM, */
15945 node, NULL,
15946 "Node of unexpected type found in simple type content",
15947 NULL);
15948 return (XML_SCHEMAV_INTERNAL);
15949 }
15950 cur = cur->next;
15951 } while (cur != NULL);
15952 }
15953
William M. Brack2f2a6632004-08-20 23:09:47 +000015954 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
15955 xmlSchemaTypePtr base, anyType;
15956
15957 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
15958
15959 base = type->baseType;
15960 while ((base != NULL) &&
15961 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
15962 (base->type != XML_SCHEMA_TYPE_BASIC) &&
15963 (base != anyType)) {
15964 base = base->baseType;
15965 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015966 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015967 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015968 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015969 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15970 "validating complex type '%s'\n",
15971 type->name, NULL);
15972 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
15973 /*
15974 * Check facets.
15975 */
15976 /*
15977 * This is somehow not nice, since if an error occurs
15978 * the reported type will be the complex type; the spec
15979 * wants a simple type to be created on the complex type
15980 * if it has a simple content. For now we have to live with
15981 * it.
15982 */
15983 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15984 value, 0, fireErrors);
15985 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015986 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015987 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15988 "validating facets of complex type '%s'\n",
15989 type->name, NULL);
15990 } else if (ret > 0) {
15991 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000015992 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015993 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000015994 }
15995 }
15996 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015997
15998 if (ctxt->value != NULL) {
15999 xmlSchemaFreeValue(ctxt->value);
16000 ctxt->value = NULL;
16001 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016002 /*
16003 * STREAM-READ-CHILDREN.
16004 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016005 if ((type->builtInType == XML_SCHEMAS_NOTATION) &&
16006 (ctxt->schema != NULL)) {
16007 /*
16008 * NOTATIONs need to be processed here, since they need
16009 * to lookup in the hashtable of NOTATION declarations.
16010 */
16011 ret = xmlSchemaValidateNotation(ctxt, value, &(ctxt->value), node);
16012 } else
16013 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016014 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016015 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
16016 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
16017 else
16018 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016019 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016020 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016021 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016022 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016023 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016024 "validating built-in type '%s'\n", type->name, NULL);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016025 } else if ((ctxt->value == NULL) &&
16026 (type->builtInType == XML_SCHEMAS_STRING) &&
16027 (ctxt->nodeInfo != NULL) &&
16028 (ctxt->nodeInfo->flags & XML_SCHEMA_ELEM_INFO_VALUE_NEEDED)) {
16029#ifdef IDC_VALUE_SUPPORT
16030 xmlChar *valdup;
16031 /*
16032 * Create a precomputed string value for "string" as well if
16033 * requested.
16034 */
16035 valdup = xmlStrdup(value);
16036 ctxt->value = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
16037 BAD_CAST valdup);
16038 if ((valdup != NULL) && (ctxt->value == NULL))
16039 xmlFree(valdup);
16040#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000016041 }
16042 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
16043 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
16044 * a literal in the ·lexical space· of {base type definition}
16045 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016046 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016047 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016048 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016049 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016050 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016051 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016052 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016053 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016054 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016055 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016056 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016057 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016058 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016059 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016060 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16061 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016062 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016063 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016064 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016065 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016066 type->name, NULL);
16067 } else if (ret > 0) {
16068 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016069 /*
16070 Disabled, since the facet validation already reports errors.
16071 if (fireErrors)
16072 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16073 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016074 }
16075 }
16076 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
16077
16078 xmlSchemaTypePtr tmpType;
16079 const xmlChar *cur, *end;
16080 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016081 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016082
16083 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
16084 * of white space separated tokens, each of which ·match·es a literal
16085 * in the ·lexical space· of {item type definition}
16086 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000016087
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000016088 if (value == NULL)
16089 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000016090 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016091 cur = value;
16092 do {
16093 while (IS_BLANK_CH(*cur))
16094 cur++;
16095 end = cur;
16096 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
16097 end++;
16098 if (end == cur)
16099 break;
16100 tmp = xmlStrndup(cur, end - cur);
16101 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016102 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016103 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016104 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 an item of list simple type '%s'\n",
16108 type->name, NULL);
16109 break;
16110 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016111 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016112 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016113 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016114 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016115 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016116 cur = end;
16117 } while (*cur != 0);
16118 /*
16119 * Check facets.
16120 */
16121 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016122 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016123 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016124 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016125 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016126 } else if ((ret == 0) && (applyFacets)) {
16127 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16128 value, len, fireErrors);
16129 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016130 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016131 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16132 "validating facets of list simple type '%s'\n",
16133 type->name, NULL);
16134 } else if (ret > 0) {
16135 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016136 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016137 Disabled, since the facet validation already reports errors.
16138 if (fireErrors)
16139 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016140 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016141 }
16142
Daniel Veillard01fa6152004-06-29 17:04:39 +000016143 }
16144 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
16145 xmlSchemaTypeLinkPtr memberLink;
16146
16147 /*
16148 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
16149 * not apply directly; however, the normalization behavior of ·union·
16150 * types is controlled by the value of whiteSpace on that one of the
16151 * ·memberTypes· against which the ·union· is successfully validated.
16152 *
16153 * This means that the value is normalized by the first validating
16154 * member type, then the facets of the union type are applied. This
16155 * needs changing of the value!
16156 */
16157
16158 /*
16159 * 1.2.3 if {variety} is ·union· then the string must ·match· a
16160 * literal in the ·lexical space· of at least one member of
16161 * {member type definitions}
16162 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016163#ifdef DEBUG_UNION_VALIDATION
16164 printf("Union ST : '%s'\n", (const char *) type->name);
16165 printf(" fireErrors : %d\n", fireErrors);
16166 printf(" applyFacets: %d\n", applyFacets);
16167#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000016168 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
16169 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016170 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016171 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016172 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016173 type->name, NULL);
16174 ret = -1;
16175 }
16176 if (ret == 0) {
16177 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016178 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
16179 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016180 if ((ret <= 0) || (ret == 0))
16181 break;
16182 memberLink = memberLink->next;
16183 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016184 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016185 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016186 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016187 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016188 type->name, NULL);
16189 } else if (ret > 0) {
16190 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016191 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016192 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016193 }
16194 }
16195 /*
16196 * Apply facets (pattern, enumeration).
16197 */
16198 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
16199 int mws;
16200 /*
16201 * The normalization behavior of ·union· types is controlled by
16202 * the value of whiteSpace on that one of the ·memberTypes·
16203 * against which the ·union· is successfully validated.
16204 */
16205 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016206 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016207 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16208 "the value was already normalized for the union simple "
16209 "type '%s'.\n", type->name, NULL);
16210 }
16211 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
16212 if (mws > ctxt->valueWS) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016213 if (mws == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000016214 normValue = xmlSchemaCollapseString(value);
16215 else
16216 normValue = xmlSchemaWhiteSpaceReplace(value);
16217 if (normValue != NULL)
16218 value = (const xmlChar *) normValue;
16219 }
16220
16221 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16222 value, 0, fireErrors);
16223 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016224 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016225 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16226 "validating facets of union simple type '%s'\n",
16227 type->name, NULL);
16228 } else if (ret > 0) {
16229 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
16230 /*
16231 if (fireErrors)
16232 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16233 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016234 }
16235 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016236 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016237 ctxt->valueWS = wtsp;
16238 if (normValue != NULL)
16239 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016240 return (ret);
16241}
16242
16243/**
16244 * xmlSchemaValidateSimpleTypeElement:
16245 * @ctxt: a schema validation context
16246 * @node: the element node to be validated.
16247 *
16248 * Validate the element against a simple type.
16249 *
16250 * Returns 0 if the element is valid, a positive error code
16251 * number otherwise and -1 in case of an internal or API error.
16252 */
16253static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016254xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016255 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016256 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016257 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016258{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016259 xmlSchemaTypePtr oldtype;
16260 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016261 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016262 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016263 int ret = 0, retval = 0;
16264
Daniel Veillard01fa6152004-06-29 17:04:39 +000016265 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016266 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16267 "Internal error: xmlSchemaValidateElementBySimpleType, "
16268 "bad arguments", NULL);
16269 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016270 }
16271
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016272 oldtype = ctxt->type;
16273 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016274 /*
16275 * cvc-type: 3.1.2 The element information item must have no element
16276 * information item [children].
16277 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016278 /*
16279 * STREAM: Child nodes are processed.
16280 */
16281 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016282 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016283 /*
16284 * TODO: Entities, will they produce elements as well?
16285 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016286 if (cur->type == XML_ELEMENT_NODE) {
16287 xmlSchemaVCustomErr(ctxt,
16288 XML_SCHEMAV_CVC_TYPE_3_1_2,
16289 node, type,
16290 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016291 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016292 }
16293 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016294 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016295
Daniel Veillard01fa6152004-06-29 17:04:39 +000016296 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016297 * cvc-type 3.1.1:
16298 *
16299 * The attributes of must be empty, excepting those whose namespace name
16300 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
16301 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016302 */
16303 /*
16304 * STREAM: Attribute nodes are processed.
16305 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016306 attr = node->properties;
16307 while (attr != NULL) {
16308 if ((attr->ns == NULL) ||
16309 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
16310 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
16311 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
16312 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
16313 (!xmlStrEqual
16314 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016315 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016316 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
16317 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016318 }
16319 attr = attr->next;
16320 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016321 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016322 * This will skip validation if the type is 'anySimpleType' and
16323 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016324 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016325 if ((! isNil) &&
16326 (valSimpleContent == 1) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016327 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
16328 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016329 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016330
16331 value = xmlNodeGetContent(node);
16332 /*
16333 * NOTE: This call will not check the content nodes, since
16334 * this should be checked here already.
16335 */
16336 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
16337 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016338 if (value != NULL)
16339 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016340 if (retval != 0)
16341 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000016342 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016343 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016344 return (ret);
16345}
Daniel Veillard4255d502002-04-16 15:50:10 +000016346
16347/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016348 * xmlSchemaValQNameAcquire:
16349 * @value: the lexical represantation of the QName value
16350 * @node: the node to search for the corresponding namespace declaration
16351 * @nsName: the resulting namespace name if found
16352 *
16353 * Checks that a value conforms to the lexical space of the type QName;
16354 * if valid, the corresponding namespace name is searched and retured
16355 * as a copy in @nsName. The local name is returned in @localName as
16356 * a copy.
16357 *
16358 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
16359 * namespace declaration was found in scope; -1 in case of an internal or
16360 * API error.
16361 */
16362static int
16363xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
16364 xmlChar **nsName, xmlChar **localName)
16365{
16366 int ret;
16367 xmlChar *local = NULL;
16368
16369 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
16370 return (-1);
16371 *nsName = NULL;
16372 *localName = NULL;
16373 ret = xmlValidateQName(value, 1);
16374 if (ret == 0) {
16375 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016376 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016377
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016378 /*
16379 * NOTE: xmlSplitQName2 will return a duplicated
16380 * string.
16381 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016382 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016383 if (local == NULL)
16384 local = xmlStrdup(value);
16385 ns = xmlSearchNs(node->doc, node, prefix);
16386 /*
16387 * A namespace need not to be found if the prefix is NULL.
16388 */
16389 if (ns != NULL) {
16390 /*
16391 * TODO: Is it necessary to duplicate the URI here?
16392 */
16393 *nsName = xmlStrdup(ns->href);
16394 } else if (prefix != NULL) {
16395 xmlFree(prefix);
16396 if (local != NULL)
16397 xmlFree(local);
16398 return (2);
16399 }
16400 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016401 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016402 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016403 } else
16404 return (1);
16405 return (ret);
16406}
16407
16408/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016409 * xmlSchemaHasElemContent:
16410 * @node: the node
16411 *
16412 * Scours the content of the given node for element
16413 * nodes.
16414 *
16415 * Returns 1 if an element node is found,
16416 * 0 otherwise.
16417 */
16418static int
16419xmlSchemaHasElemContent(xmlNodePtr node)
16420{
16421 if (node == NULL)
16422 return (0);
16423 node = node->children;
16424 while (node != NULL) {
16425 if (node->type == XML_ELEMENT_NODE)
16426 return (1);
16427 node = node->next;
16428 }
16429 return (0);
16430}
16431/**
16432 * xmlSchemaHasElemOrCharContent:
16433 * @node: the node
16434 *
16435 * Scours the content of the given node for element
16436 * and character nodes.
16437 *
16438 * Returns 1 if an element or character node is found,
16439 * 0 otherwise.
16440 */
16441static int
16442xmlSchemaHasElemOrCharContent(xmlNodePtr node)
16443{
16444 if (node == NULL)
16445 return (0);
16446 node = node->children;
16447 while (node != NULL) {
16448 switch (node->type) {
16449 case XML_ELEMENT_NODE:
16450 /*
16451 * TODO: Ask Daniel if these are all character nodes.
16452 */
16453 case XML_TEXT_NODE:
16454 case XML_CDATA_SECTION_NODE:
16455 /*
16456 * TODO: How XML_ENTITY_NODEs evaluated?
16457 */
16458 case XML_ENTITY_REF_NODE:
16459 case XML_ENTITY_NODE:
16460 return (1);
16461 break;
16462 default:
16463 break;
16464 }
16465 node = node->next;
16466 }
16467 return (0);
16468}
16469
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016470/************************************************************************
16471 * *
16472 * Identity-constraints (IDC) *
16473 * *
16474 ************************************************************************/
16475
16476#ifdef IDC_ENABLED
16477
16478/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016479 * xmlSchemaAugmentIDC:
16480 * @idcDef: the IDC definition
16481 *
16482 * Creates an augmented IDC definition item.
16483 *
16484 * Returns the item, or NULL on internal errors.
16485 */
16486static void
16487xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
16488 xmlSchemaValidCtxtPtr vctxt)
16489{
16490 xmlSchemaIDCAugPtr aidc;
16491
16492 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
16493 if (aidc == NULL) {
16494 xmlSchemaVErrMemory(vctxt,
16495 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
16496 NULL);
16497 return;
16498 }
16499 aidc->bubbleDepth = -1;
16500 aidc->def = idcDef;
16501 aidc->next = NULL;
16502 if (vctxt->aidcs == NULL)
16503 vctxt->aidcs = aidc;
16504 else {
16505 aidc->next = vctxt->aidcs;
16506 vctxt->aidcs = aidc;
16507 }
16508}
16509
16510/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016511 * xmlSchemaIDCNewBinding:
16512 * @idcDef: the IDC definition of this binding
16513 *
16514 * Creates a new IDC binding.
16515 *
16516 * Returns the new binding in case of succeeded, NULL on internal errors.
16517 */
16518static xmlSchemaPSVIIDCBindingPtr
16519xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
16520{
16521 xmlSchemaPSVIIDCBindingPtr ret;
16522
16523 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
16524 sizeof(xmlSchemaPSVIIDCBinding));
16525 if (ret == NULL) {
16526 xmlSchemaVErrMemory(NULL,
16527 "allocating a PSVI IDC binding item", NULL);
16528 return (NULL);
16529 }
16530 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
16531 ret->definition = idcDef;
16532 return (ret);
16533}
16534
16535/**
16536 * xmlSchemaIDCStoreNodeTableItem:
16537 * @vctxt: the WXS validation context
16538 * @item: the IDC node table item
16539 *
16540 * The validation context is used to store an IDC node table items.
16541 * They are stored to avoid copying them if IDC node-tables are merged
16542 * with corresponding parent IDC node-tables (bubbling).
16543 *
16544 * Returns 0 if succeeded, -1 on internal errors.
16545 */
16546static int
16547xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
16548 xmlSchemaPSVIIDCNodePtr item)
16549{
16550 /*
16551 * Add to gobal list.
16552 */
16553 if (vctxt->idcNodes == NULL) {
16554 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16555 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
16556 if (vctxt->idcNodes == NULL) {
16557 xmlSchemaVErrMemory(vctxt,
16558 "allocating the IDC node table item list", NULL);
16559 return (-1);
16560 }
16561 vctxt->sizeIdcNodes = 20;
16562 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
16563 vctxt->sizeIdcNodes *= 2;
16564 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16565 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
16566 sizeof(xmlSchemaPSVIIDCNodePtr));
16567 if (vctxt->idcNodes == NULL) {
16568 xmlSchemaVErrMemory(vctxt,
16569 "re-allocating the IDC node table item list", NULL);
16570 return (-1);
16571 }
16572 }
16573 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
16574
16575 return (0);
16576}
16577
16578/**
16579 * xmlSchemaIDCStoreKey:
16580 * @vctxt: the WXS validation context
16581 * @item: the IDC key
16582 *
16583 * The validation context is used to store an IDC key.
16584 *
16585 * Returns 0 if succeeded, -1 on internal errors.
16586 */
16587static int
16588xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
16589 xmlSchemaPSVIIDCKeyPtr key)
16590{
16591 /*
16592 * Add to gobal list.
16593 */
16594 if (vctxt->idcKeys == NULL) {
16595 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16596 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
16597 if (vctxt->idcKeys == NULL) {
16598 xmlSchemaVErrMemory(vctxt,
16599 "allocating the IDC key storage list", NULL);
16600 return (-1);
16601 }
16602 vctxt->sizeIdcKeys = 40;
16603 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
16604 vctxt->sizeIdcKeys *= 2;
16605 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16606 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
16607 sizeof(xmlSchemaPSVIIDCKeyPtr));
16608 if (vctxt->idcKeys == NULL) {
16609 xmlSchemaVErrMemory(vctxt,
16610 "re-allocating the IDC key storage list", NULL);
16611 return (-1);
16612 }
16613 }
16614 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
16615
16616 return (0);
16617}
16618
16619/**
16620 * xmlSchemaIDCAppendNodeTableItem:
16621 * @bind: the IDC binding
16622 * @ntItem: the node-table item
16623 *
16624 * Appends the IDC node-table item to the binding.
16625 *
16626 * Returns 0 on success and -1 on internal errors.
16627 */
16628static int
16629xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
16630 xmlSchemaPSVIIDCNodePtr ntItem)
16631{
16632 if (bind->nodeTable == NULL) {
16633 bind->sizeNodes = 10;
16634 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16635 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
16636 if (bind->nodeTable == NULL) {
16637 xmlSchemaVErrMemory(NULL,
16638 "allocating an array of IDC node-table items", NULL);
16639 return(-1);
16640 }
16641 } else if (bind->sizeNodes <= bind->nbNodes) {
16642 bind->sizeNodes *= 2;
16643 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16644 xmlRealloc(bind->nodeTable, bind->sizeNodes *
16645 sizeof(xmlSchemaPSVIIDCNodePtr));
16646 if (bind->nodeTable == NULL) {
16647 xmlSchemaVErrMemory(NULL,
16648 "re-allocating an array of IDC node-table items", NULL);
16649 return(-1);
16650 }
16651 }
16652 bind->nodeTable[bind->nbNodes++] = ntItem;
16653 return(0);
16654}
16655
16656/**
16657 * xmlSchemaIDCAquireBinding:
16658 * @vctxt: the WXS validation context
16659 * @matcher: the IDC matcher
16660 *
16661 * Looks up an PSVI IDC binding, for the IDC definition and
16662 * of the given matcher. If none found, a new one is created
16663 * and added to the IDC table.
16664 *
16665 * Returns an IDC binding or NULL on internal errors.
16666 */
16667static xmlSchemaPSVIIDCBindingPtr
16668xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
16669 xmlSchemaIDCMatcherPtr matcher)
16670{
16671 xmlSchemaElemInfoPtr info;
16672
16673 info = vctxt->elemInfos[matcher->depth];
16674
16675 if (info->idcTable == NULL) {
16676 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
16677 if (info->idcTable == NULL)
16678 return (NULL);
16679 return(info->idcTable);
16680 } else {
16681 xmlSchemaPSVIIDCBindingPtr bind = NULL;
16682
16683 bind = info->idcTable;
16684 do {
16685 if (bind->definition == matcher->aidc->def)
16686 return(bind);
16687 if (bind->next == NULL) {
16688 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
16689 if (bind->next == NULL)
16690 return (NULL);
16691 return(bind->next);
16692 }
16693 bind = bind->next;
16694 } while (bind != NULL);
16695 }
16696 return (NULL);
16697}
16698
16699/**
16700 * xmlSchemaIDCFreeKey:
16701 * @key: the IDC key
16702 *
16703 * Frees an IDC key together with its compiled value.
16704 */
16705static void
16706xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
16707{
16708 if (key->compValue != NULL)
16709 xmlSchemaFreeValue(key->compValue);
16710 xmlFree(key);
16711}
16712
16713/**
16714 * xmlSchemaIDCFreeBinding:
16715 *
16716 * Frees an IDC binding. Note that the node table-items
16717 * are not freed.
16718 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016719static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016720xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
16721{
16722 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016723 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
16724 int i;
16725 /*
16726 * Node-table items for keyrefs are not stored globally
16727 * to the validation context, since they are not bubbled.
16728 * We need to free them here.
16729 */
16730 for (i = 0; i < bind->nbNodes; i++) {
16731 xmlFree(bind->nodeTable[i]->keys);
16732 xmlFree(bind->nodeTable[i]);
16733 }
16734 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016735 xmlFree(bind->nodeTable);
16736 }
16737 xmlFree(bind);
16738}
16739
16740/**
16741 * xmlSchemaIDCFreeIDCTable:
16742 * @bind: the first IDC binding in the list
16743 *
16744 * Frees an IDC table, i.e. all the IDC bindings in the list.
16745 */
16746static void
16747xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
16748{
16749 xmlSchemaPSVIIDCBindingPtr prev;
16750
16751 while (bind != NULL) {
16752 prev = bind;
16753 bind = bind->next;
16754 xmlSchemaIDCFreeBinding(prev);
16755 }
16756}
16757
16758/**
16759 * xmlSchemaIDCFreeMatcherList:
16760 * @matcher: the first IDC matcher in the list
16761 *
16762 * Frees a list of IDC matchers.
16763 */
16764static void
16765xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
16766{
16767 xmlSchemaIDCMatcherPtr next;
16768
16769 while (matcher != NULL) {
16770 next = matcher->next;
16771 if (matcher->keySeqs != NULL) {
16772 int i;
16773 for (i = 0; i < matcher->sizeKeySeqs; i++)
16774 if (matcher->keySeqs[i] != NULL)
16775 xmlFree(matcher->keySeqs[i]);
16776 xmlFree(matcher->keySeqs);
16777 }
16778 xmlFree(matcher);
16779 matcher = next;
16780 }
16781}
16782
16783/**
16784 * xmlSchemaAreValuesEqual:
16785 * @ta: the first type
16786 * @a: the first value
16787 * @tb: the second type
16788 * @b: the second value
16789 *
16790 * Compares two values.
16791 *
16792 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
16793 */
16794static int
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016795xmlSchemaAreValuesEqual(xmlSchemaValidCtxtPtr vctxt,
16796 xmlSchemaTypePtr ta,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016797 xmlSchemaValPtr a,
16798 xmlSchemaTypePtr tb,
16799 xmlSchemaValPtr b)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016800{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016801 /* Same user derived/built-in derived/built-in primitive types. */
16802 if (ta == tb)
16803 goto compareValue;
16804
16805 /*
16806 * Comparison with anySimpleTypes is not supported by this implemention.
16807 */
16808 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
16809 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
16810 return(0);
16811
16812 /*
16813 * 4.2.1 equal (data-types)
16814 *
16815 * the ·value space·s of all ·primitive· datatypes are disjoint
16816 * (they do not share any values)
16817 */
16818 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
16819 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
16820 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
16821 return(0);
16822
16823 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16824 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
16825 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16826 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
16827 TODO
16828 return(0);
16829 }
16830 /*
16831 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
16832 * T then the ·value space· of T' is a subset of the ·value space· of T.
16833 */
16834 /*
16835 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
16836 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
16837 */
16838
16839 {
16840 xmlSchemaTypePtr pta = ta, ptb = tb;
16841
16842 /* Note that we will compare the primitives here. */
16843 while ((pta->builtInType == 0) ||
16844 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16845 pta = pta->baseType;
16846 while ((ptb->builtInType == 0) ||
16847 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16848 ptb = ptb->baseType;
16849 if (pta == ptb)
16850 goto compareValue;
16851 return(0);
16852 }
16853compareValue:
16854 {
16855#ifdef IDC_VALUE_SUPPORT
16856 int ret;
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016857 int aws, bws;
16858
16859 aws = xmlSchemaGetWhiteSpaceFacetValue(ta);
16860 bws = xmlSchemaGetWhiteSpaceFacetValue(tb);
16861
16862 ret = xmlSchemaCompareValuesWhtsp(
16863 a, (xmlSchemaWhitespaceValueType) aws,
16864 b, (xmlSchemaWhitespaceValueType) bws);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016865 if (ret == 0)
16866 return(1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016867 else if (ret == -2) {
16868 xmlSchemaVErr(vctxt, vctxt->node,
16869 XML_SCHEMAV_INTERNAL,
16870 "Internal error: xmlSchemaAreValuesEqual, "
16871 "failed to compare the values.\n",
16872 NULL, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016873 return(-1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016874 } else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016875 return(0);
16876#else
16877 return (1);
16878#endif
16879 }
16880}
16881
16882/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016883 * xmlSchemaIDCAddStateObject:
16884 * @vctxt: the WXS validation context
16885 * @matcher: the IDC matcher
16886 * @sel: the XPath information
16887 * @parent: the parent "selector" state object if any
16888 * @type: "selector" or "field"
16889 *
16890 * Creates/reuses and activates state objects for the given
16891 * XPath information; if the XPath expression consists of unions,
16892 * multiple state objects are created for every unioned expression.
16893 *
16894 * Returns 0 on success and -1 on internal errors.
16895 */
16896static int
16897xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
16898 xmlSchemaIDCMatcherPtr matcher,
16899 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016900 int type)
16901{
16902 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016903
16904 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016905 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016906 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016907 if (vctxt->xpathStatePool != NULL) {
16908 sto = vctxt->xpathStatePool;
16909 vctxt->xpathStatePool = sto->next;
16910 sto->next = NULL;
16911 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016912 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016913 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016914 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016915 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
16916 if (sto == NULL) {
16917 xmlSchemaVErrMemory(NULL,
16918 "allocating an IDC state object", NULL);
16919 return (-1);
16920 }
16921 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
16922 }
16923 /*
16924 * Add to global list.
16925 */
16926 if (vctxt->xpathStates != NULL)
16927 sto->next = vctxt->xpathStates;
16928 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016929
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016930 /*
16931 * Free the old xpath validation context.
16932 */
16933 if (sto->xpathCtxt != NULL)
16934 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
16935
16936 /*
16937 * Create a new XPath (pattern) validation context.
16938 */
16939 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
16940 (xmlPatternPtr) sel->xpathComp);
16941 if (sto->xpathCtxt == NULL) {
16942 xmlSchemaVErr(vctxt, vctxt->node,
16943 XML_SCHEMAV_INTERNAL,
16944 "Internal error: xmlSchemaIDCAddStateObject, "
16945 "failed to create the XPath validation context.\n",
16946 NULL, NULL);
16947 return (-1);
16948 }
16949 sto->type = type;
16950 sto->depth = vctxt->depth;
16951 sto->matcher = matcher;
16952 sto->sel = sel;
16953 sto->nbHistory = 0;
16954
16955#if DEBUG_IDC
16956 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
16957 sto->sel->xpath);
16958#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016959 return (0);
16960}
16961
16962/**
16963 * xmlSchemaXPathEvaluate:
16964 * @vctxt: the WXS validation context
16965 * @nodeType: the nodeType of the current node
16966 *
16967 * Evaluates all active XPath state objects.
16968 *
16969 * Returns the number of IC "field" state objects which resolved to
16970 * this node, 0 if none resolved and -1 on internal errors.
16971 */
16972static int
16973xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016974 xmlElementType nodeType)
16975{
16976 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016977 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016978
16979 if (vctxt->xpathStates == NULL)
16980 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016981
16982 if (nodeType == XML_ATTRIBUTE_NODE)
16983 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016984#if DEBUG_IDC
16985 {
16986 xmlChar *str = NULL;
16987 xmlGenericError(xmlGenericErrorContext,
16988 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016989 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
16990 vctxt->nodeInfo->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016991 FREE_AND_NULL(str)
16992 }
16993#endif
16994 /*
16995 * Process all active XPath state objects.
16996 */
16997 first = vctxt->xpathStates;
16998 sto = first;
16999 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017000#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017001 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017002 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
17003 sto->matcher->aidc->def->name, sto->sel->xpath);
17004 else
17005 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
17006 sto->matcher->aidc->def->name, sto->sel->xpath);
17007#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017008
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017009#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017010 if (nodeType == XML_ELEMENT_NODE)
17011 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
17012 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
17013 else
17014 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
17015 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
17016
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017017#else
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017018 res = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017019#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017020 if (res == -1) {
17021 xmlSchemaVErr(vctxt, vctxt->node,
17022 XML_SCHEMAV_INTERNAL,
17023 "Internal error: xmlSchemaXPathEvaluate, "
17024 "failed to evaluate a node.\n",
17025 NULL, NULL);
17026 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017027 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017028 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017029 goto next_sto;
17030 /*
17031 * Full match.
17032 */
17033#if DEBUG_IDC
17034 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017035 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017036#endif
17037 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017038 * Register a match in the state object history.
17039 */
17040 if (sto->history == NULL) {
17041 sto->history = (int *) xmlMalloc(5 * sizeof(int));
17042 if (sto->history == NULL) {
17043 xmlSchemaVErrMemory(NULL,
17044 "allocating the state object history", NULL);
17045 return(-1);
17046 }
17047 sto->sizeHistory = 10;
17048 } else if (sto->sizeHistory <= sto->nbHistory) {
17049 sto->sizeHistory *= 2;
17050 sto->history = (int *) xmlRealloc(sto->history,
17051 sto->sizeHistory * sizeof(int));
17052 if (sto->history == NULL) {
17053 xmlSchemaVErrMemory(NULL,
17054 "re-allocating the state object history", NULL);
17055 return(-1);
17056 }
17057 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017058 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017059
17060#ifdef DEBUG_IDC
17061 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
17062 vctxt->depth);
17063#endif
17064
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017065 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
17066 xmlSchemaIDCSelectPtr sel;
17067 /*
17068 * Activate state objects for the IDC fields of
17069 * the IDC selector.
17070 */
17071#if DEBUG_IDC
17072 xmlGenericError(xmlGenericErrorContext, "IDC: "
17073 "activating field states\n");
17074#endif
17075 sel = sto->matcher->aidc->def->fields;
17076 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017077 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
17078 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
17079 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017080 sel = sel->next;
17081 }
17082 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
17083 /*
17084 * An IDC key node was found.
17085 */
17086#if DEBUG_IDC
17087 xmlGenericError(xmlGenericErrorContext,
17088 "IDC: key found\n");
17089#endif
17090 /*
17091 * Notify that the character value of this node is
17092 * needed.
17093 */
17094 if (resolved == 0)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017095 vctxt->nodeInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017096 resolved++;
17097 }
17098next_sto:
17099 if (sto->next == NULL) {
17100 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017101 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017102 */
17103 head = first;
17104 sto = vctxt->xpathStates;
17105 } else
17106 sto = sto->next;
17107 }
17108 return (resolved);
17109}
17110
17111/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017112 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017113 * @vctxt: the WXS validation context
17114 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017115 * @compValue: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017116 *
17117 * Processes and pops the history items of the IDC state objects.
17118 * IDC key-sequences are validated/created on IDC bindings.
17119 *
17120 * Returns 0 on success and -1 on internal errors.
17121 */
17122static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017123xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017124 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017125{
17126 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017127 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017128 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017129 xmlSchemaTypePtr type = vctxt->nodeInfo->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017130
17131 if (vctxt->xpathStates == NULL)
17132 return (0);
17133 sto = vctxt->xpathStates;
17134
17135#if DEBUG_IDC
17136 {
17137 xmlChar *str = NULL;
17138 xmlGenericError(xmlGenericErrorContext,
17139 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017140 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17141 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017142 FREE_AND_NULL(str)
17143 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017144#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017145 /*
17146 * Evaluate the state objects.
17147 */
17148 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017149#ifdef IDC_XPATH_SUPPORT
17150 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
17151 #if DEBUG_IDC
17152 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
17153 sto->sel->xpath);
17154 #endif
17155#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017156 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017157 goto deregister_check;
17158
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017159 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017160
17161 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017162 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017163 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017164 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017165 sto = sto->next;
17166 continue;
17167 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017168
17169 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
17170 if (! IS_SIMPLE_TYPE(type)) {
17171 /*
17172 * Not qualified if the field resolves to a node of non
17173 * simple type.
17174 */
17175 xmlSchemaVCustomErr(vctxt,
17176 XML_SCHEMAV_CVC_IDC,
17177 vctxt->node,
17178 (xmlSchemaTypePtr) sto->matcher->aidc->def,
17179 "The field '%s' does evaluate to a node of "
17180 "non-simple type", sto->sel->xpath);
17181
17182 sto->nbHistory--;
17183 goto deregister_check;
17184 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017185 if ((key == NULL) && (vctxt->nodeInfo->value == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017186 /*
17187 * Failed to provide the normalized value; maby
17188 * the value was invalid.
17189 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017190 xmlSchemaVCustomErr(vctxt,
17191 XML_SCHEMAV_CVC_IDC,
17192 vctxt->nodeInfo->node,
17193 (xmlSchemaTypePtr) sto->matcher->aidc->def,
17194 "Warning: No precomputed value available, the value "
17195 "was either invalid or something strange happend", NULL);
17196 /*
17197 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017198 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017199 "Internal error: xmlSchemaXPathProcessHistory, "
17200 "computed value not available.\n",
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017201 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017202 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017203 sto->nbHistory--;
17204 goto deregister_check;
17205 } else {
17206 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
17207 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017208 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017209
17210 /*
17211 * The key will be anchored on the matcher's list of
17212 * key-sequences. The position in this list is determined
17213 * by the target node's depth relative to the matcher's
17214 * depth of creation (i.e. the depth of the scope element).
17215 */
17216 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017217 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017218
17219 /*
17220 * Create/grow the array of key-sequences.
17221 */
17222 if (matcher->keySeqs == NULL) {
17223 if (pos > 9)
17224 matcher->sizeKeySeqs = pos * 2;
17225 else
17226 matcher->sizeKeySeqs = 10;
17227 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17228 xmlMalloc(matcher->sizeKeySeqs *
17229 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17230 if (matcher->keySeqs == NULL) {
17231 xmlSchemaVErrMemory(NULL,
17232 "allocating an array of key-sequences",
17233 NULL);
17234 return(-1);
17235 }
17236 memset(matcher->keySeqs, 0,
17237 matcher->sizeKeySeqs *
17238 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17239 } else if (pos >= matcher->sizeKeySeqs) {
17240 int i = matcher->sizeKeySeqs;
17241
17242 matcher->sizeKeySeqs *= 2;
17243 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17244 xmlRealloc(matcher->keySeqs,
17245 matcher->sizeKeySeqs *
17246 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017247 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017248 xmlSchemaVErrMemory(NULL,
17249 "reallocating an array of key-sequences",
17250 NULL);
17251 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017252 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017253 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017254 * The array needs to be NULLed.
17255 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017256 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017257 for (; i < matcher->sizeKeySeqs; i++)
17258 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017259 }
17260
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017261 /*
17262 * Get/create the key-sequence.
17263 */
17264 keySeq = matcher->keySeqs[pos];
17265 if (keySeq == NULL) {
17266 goto create_sequence;
17267 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017268 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017269 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017270 * cvc-identity-constraint:
17271 * 3 For each node in the ·target node set· all
17272 * of the {fields}, with that node as the context
17273 * node, evaluate to either an empty node-set or
17274 * a node-set with exactly one member, which must
17275 * have a simple type.
17276 *
17277 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017278 */
17279 xmlSchemaVCustomErr(vctxt,
17280 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017281 vctxt->node, (xmlSchemaTypePtr) matcher->aidc->def,
17282 "The field '%s' evaluates to a node-set "
17283 "with more than one member", sto->sel->xpath);
17284 sto->nbHistory--;
17285 goto deregister_check;
17286 } else {
17287 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017288 }
17289 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017290
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017291create_sequence:
17292 /*
17293 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017294 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017295 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
17296 matcher->aidc->def->nbFields *
17297 sizeof(xmlSchemaPSVIIDCKeyPtr));
17298 if (keySeq == NULL) {
17299 xmlSchemaVErrMemory(NULL,
17300 "allocating an IDC key-sequence", NULL);
17301 return(-1);
17302 }
17303 memset(keySeq, 0, matcher->aidc->def->nbFields *
17304 sizeof(xmlSchemaPSVIIDCKeyPtr));
17305 matcher->keySeqs[pos] = keySeq;
17306create_key:
17307 /*
17308 * Created a key once per node only.
17309 */
17310 if (key == NULL) {
17311 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
17312 sizeof(xmlSchemaPSVIIDCKey));
17313 if (key == NULL) {
17314 xmlSchemaVErrMemory(NULL,
17315 "allocating a IDC key", NULL);
17316 xmlFree(keySeq);
17317 matcher->keySeqs[pos] = NULL;
17318 return(-1);
17319 }
17320 /*
17321 * Consume the compiled value.
17322 */
17323 key->type = type;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017324 key->compValue = vctxt->nodeInfo->value;
17325 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017326 /*
17327 * Store the key in a global list.
17328 */
17329 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
17330 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017331 return (-1);
17332 }
17333 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017334 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017335 }
17336 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017337
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017338 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
17339 xmlSchemaPSVIIDCBindingPtr bind;
17340 xmlSchemaPSVIIDCNodePtr ntItem;
17341 xmlSchemaIDCMatcherPtr matcher;
17342 xmlSchemaIDCPtr idc;
17343 int pos, i, j, nbKeys;
17344 /*
17345 * Here we have the following scenario:
17346 * An IDC 'selector' state object resolved to a target node,
17347 * during the time this target node was in the
17348 * ancestor-or-self axis, the 'field' state object(s) looked
17349 * out for matching nodes to create a key-sequence for this
17350 * target node. Now we are back to this target node and need
17351 * to put the key-sequence, together with the target node
17352 * itself, into the node-table of the corresponding IDC
17353 * binding.
17354 */
17355 matcher = sto->matcher;
17356 idc = matcher->aidc->def;
17357 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017358 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017359 /*
17360 * Check if the matcher has any key-sequences at all, plus
17361 * if it has a key-sequence for the current target node.
17362 */
17363 if ((matcher->keySeqs == NULL) ||
17364 (matcher->sizeKeySeqs <= pos)) {
17365 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17366 goto selector_key_error;
17367 else
17368 goto selector_leave;
17369 }
17370
17371 keySeq = &(matcher->keySeqs[pos]);
17372 if (*keySeq == NULL) {
17373 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17374 goto selector_key_error;
17375 else
17376 goto selector_leave;
17377 }
17378
17379 for (i = 0; i < nbKeys; i++) {
17380 if ((*keySeq)[i] == NULL) {
17381 /*
17382 * Not qualified, if not all fields did resolve.
17383 */
17384 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
17385 /*
17386 * All fields of a "key" IDC must resolve.
17387 */
17388 goto selector_key_error;
17389 }
17390 goto selector_leave;
17391 }
17392 }
17393 /*
17394 * All fields did resolve.
17395 */
17396
17397 /*
17398 * 4.1 If the {identity-constraint category} is unique(/key),
17399 * then no two members of the ·qualified node set· have
17400 * ·key-sequences· whose members are pairwise equal, as
17401 * defined by Equal in [XML Schemas: Datatypes].
17402 *
17403 * Get the IDC binding from the matcher and check for
17404 * duplicate key-sequences.
17405 */
17406 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
17407 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
17408 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017409 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017410
17411 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017412 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017413 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017414 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017415 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017416 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017417 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017418 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017419 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017420 bkey = bkeySeq[j];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017421 res = xmlSchemaAreValuesEqual(vctxt, ckey->type,
17422 ckey->compValue, bkey->type, bkey->compValue);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017423 if (res == -1) {
17424 return (-1);
17425 } else if (res == 0)
17426 break;
17427 }
17428 if (res == 1) {
17429 /*
17430 * Duplicate found.
17431 */
17432 break;
17433 }
17434 i++;
17435 } while (i < bind->nbNodes);
17436 if (i != bind->nbNodes) {
17437 /*
17438 * TODO: Try to report the key-sequence.
17439 */
17440 xmlSchemaVCustomErr(vctxt,
17441 XML_SCHEMAV_CVC_IDC,
17442 vctxt->node,
17443 (xmlSchemaTypePtr) idc,
17444 "Duplicate key-sequence found", NULL);
17445
17446 goto selector_leave;
17447 }
17448 }
17449 /*
17450 * Add a node-table item to the IDC binding.
17451 */
17452 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
17453 sizeof(xmlSchemaPSVIIDCNode));
17454 if (ntItem == NULL) {
17455 xmlSchemaVErrMemory(NULL,
17456 "allocating an IDC node-table item", NULL);
17457 xmlFree(*keySeq);
17458 *keySeq = NULL;
17459 return(-1);
17460 }
17461 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
17462
17463 /*
17464 * Store the node-table item on global list.
17465 */
17466 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
17467 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
17468 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017469 xmlFree(*keySeq);
17470 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017471 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017472 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017473 }
17474 /*
17475 * Init the node-table item. Consume the key-sequence.
17476 */
17477 ntItem->node = vctxt->node;
17478 ntItem->keys = *keySeq;
17479 *keySeq = NULL;
17480 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
17481 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17482 /*
17483 * Free the item, since keyref items won't be
17484 * put on a global list.
17485 */
17486 xmlFree(ntItem->keys);
17487 xmlFree(ntItem);
17488 }
17489 return (-1);
17490 }
17491
17492 goto selector_leave;
17493selector_key_error:
17494 /*
17495 * 4.2.1 (KEY) The ·target node set· and the
17496 * ·qualified node set· are equal, that is, every
17497 * member of the ·target node set· is also a member
17498 * of the ·qualified node set· and vice versa.
17499 */
17500 xmlSchemaVCustomErr(vctxt,
17501 XML_SCHEMAV_CVC_IDC,
17502 vctxt->node,
17503 (xmlSchemaTypePtr) idc,
17504 "All 'key' fields must evaluate to a node",
17505 NULL);
17506selector_leave:
17507 /*
17508 * Free the key-sequence if not added to the IDC table.
17509 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017510 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017511 xmlFree(*keySeq);
17512 *keySeq = NULL;
17513 }
17514 } /* if selector */
17515
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017516 sto->nbHistory--;
17517
17518deregister_check:
17519 /*
17520 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017521 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017522 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017523#if DEBUG_IDC
17524 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
17525 sto->sel->xpath);
17526#endif
17527 if (vctxt->xpathStates != sto) {
17528 xmlSchemaVErr(vctxt, vctxt->node,
17529 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017530 "Internal error: xmlSchemaXPathProcessHistory, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017531 "The state object to be removed is not the first "
17532 "in the list.\n",
17533 NULL, NULL);
17534 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017535 nextsto = sto->next;
17536 /*
17537 * Unlink from the list of active XPath state objects.
17538 */
17539 vctxt->xpathStates = sto->next;
17540 sto->next = vctxt->xpathStatePool;
17541 /*
17542 * Link it to the pool of reusable state objects.
17543 */
17544 vctxt->xpathStatePool = sto;
17545 sto = nextsto;
17546 } else
17547 sto = sto->next;
17548 } /* while (sto != NULL) */
17549 return (0);
17550}
17551
17552/**
17553 * xmlSchemaIDCRegisterMatchers:
17554 * @vctxt: the WXS validation context
17555 * @elemDecl: the element declaration
17556 *
17557 * Creates helper objects to evaluate IDC selectors/fields
17558 * successively.
17559 *
17560 * Returns 0 if OK and -1 on internal errors.
17561 */
17562static int
17563xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
17564 xmlSchemaElementPtr elemDecl)
17565{
17566 xmlSchemaIDCMatcherPtr matcher, last = NULL;
17567 xmlSchemaIDCPtr idc, refIdc;
17568 xmlSchemaIDCAugPtr aidc;
17569
17570 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
17571 if (idc == NULL)
17572 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017573
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017574#if DEBUG_IDC
17575 {
17576 xmlChar *str = NULL;
17577 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017578 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017579 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17580 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017581 FREE_AND_NULL(str)
17582 }
17583#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017584 if (vctxt->nodeInfo->idcMatchers != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017585 xmlSchemaVErr(vctxt, vctxt->node,
17586 XML_SCHEMAV_INTERNAL,
17587 "Internal error: xmlSchemaIDCRegisterMatchers: "
17588 "The chain of IDC matchers is expected to be empty.\n",
17589 NULL, NULL);
17590 return (-1);
17591 }
17592 do {
17593 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17594 /*
17595 * Since IDCs bubbles are expensive we need to know the
17596 * depth at which the bubbles should stop; this will be
17597 * the depth of the top-most keyref IDC. If no keyref
17598 * references a key/unique IDC, the bubbleDepth will
17599 * be -1, indicating that no bubbles are needed.
17600 */
17601 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
17602 if (refIdc != NULL) {
17603 /*
17604 * Lookup the augmented IDC.
17605 */
17606 aidc = vctxt->aidcs;
17607 while (aidc != NULL) {
17608 if (aidc->def == refIdc)
17609 break;
17610 aidc = aidc->next;
17611 }
17612 if (aidc == NULL) {
17613 xmlSchemaVErr(vctxt, vctxt->node,
17614 XML_SCHEMAV_INTERNAL,
17615 "Internal error: xmlSchemaIDCRegisterMatchers: "
17616 "Could not find an augmented IDC item for an IDC "
17617 "definition.\n",
17618 NULL, NULL);
17619 return (-1);
17620 }
17621 if ((aidc->bubbleDepth == -1) ||
17622 (vctxt->depth < aidc->bubbleDepth))
17623 aidc->bubbleDepth = vctxt->depth;
17624 }
17625 }
17626 /*
17627 * Lookup the augmented IDC item for the IDC definition.
17628 */
17629 aidc = vctxt->aidcs;
17630 while (aidc != NULL) {
17631 if (aidc->def == idc)
17632 break;
17633 aidc = aidc->next;
17634 }
17635 if (aidc == NULL) {
17636 xmlSchemaVErr(vctxt, vctxt->node,
17637 XML_SCHEMAV_INTERNAL,
17638 "Internal error: xmlSchemaIDCRegisterMatchers: "
17639 "Could not find an augmented IDC item for an IDC definition.\n",
17640 NULL, NULL);
17641 return (-1);
17642 }
17643 /*
17644 * Create an IDC matcher for every IDC definition.
17645 */
17646 matcher = (xmlSchemaIDCMatcherPtr)
17647 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
17648 if (matcher == NULL) {
17649 xmlSchemaVErrMemory(vctxt,
17650 "allocating an IDC matcher", NULL);
17651 return (-1);
17652 }
17653 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
17654 if (last == NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017655 vctxt->nodeInfo->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017656 else
17657 last->next = matcher;
17658 last = matcher;
17659
17660 matcher->type = IDC_MATCHER;
17661 matcher->depth = vctxt->depth;
17662 matcher->aidc = aidc;
17663#if DEBUG_IDC
17664 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
17665#endif
17666 /*
17667 * Init the automaton state object.
17668 */
17669 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017670 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017671 return (-1);
17672
17673 idc = idc->next;
17674 } while (idc != NULL);
17675 return (0);
17676}
17677
17678/**
17679 * xmlSchemaBubbleIDCNodeTables:
17680 * @depth: the current tree depth
17681 *
17682 * Merges IDC bindings of an element at @depth into the corresponding IDC
17683 * bindings of its parent element. If a duplicate note-table entry is found,
17684 * both, the parent node-table entry and child entry are discarded from the
17685 * node-table of the parent.
17686 *
17687 * Returns 0 if OK and -1 on internal errors.
17688 */
17689static int
17690xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
17691{
17692 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017693 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
17694 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017695 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
17696 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017697 int i, j, k, ret = 0, oldNum, newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017698 int duplTop;
17699
17700 /*
17701 * The node table has the following sections:
17702 *
17703 * O --> old node-table entries (first)
17704 * O
17705 * + --> new node-table entries
17706 * +
17707 * % --> new duplicate node-table entries
17708 * %
17709 * # --> old duplicate node-table entries
17710 * # (last)
17711 *
17712 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017713 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017714 if (bind == NULL) {
17715 /* Fine, no table, no bubbles. */
17716 return (0);
17717 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017718
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017719 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
17720 /*
17721 * Walk all bindings; create new or add to existing bindings.
17722 * Remove duplicate key-sequences.
17723 */
17724start_binding:
17725 while (bind != NULL) {
17726 /*
17727 * Skip keyref IDCs.
17728 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017729 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17730 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017731 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017732 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017733 /*
17734 * Check if the key/unique IDC table needs to be bubbled.
17735 */
17736 aidc = vctxt->aidcs;
17737 do {
17738 if (aidc->def == bind->definition) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017739 if (aidc->bubbleDepth >= vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017740 bind = bind->next;
17741 goto start_binding;
17742 }
17743 break;
17744 }
17745 aidc = aidc->next;
17746 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017747
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017748 if (parTable != NULL)
17749 parBind = *parTable;
17750 while (parBind != NULL) {
17751 /*
17752 * Search a matching parent binding for the
17753 * IDC definition.
17754 */
17755 if (parBind->definition == bind->definition) {
17756
17757 /*
17758 * Compare every node-table entry of the child node,
17759 * i.e. the key-sequence within, ...
17760 */
17761 oldNum = parBind->nbNodes; /* Skip newly added items. */
17762 duplTop = oldNum + parBind->nbDupls;
17763
17764 for (i = 0; i < bind->nbNodes; i++) {
17765 node = bind->nodeTable[i];
17766 if (node == NULL)
17767 continue;
17768 /*
17769 * ...with every key-sequence of the parent node, already
17770 * evaluated to be a duplicate key-sequence.
17771 */
17772 if (parBind->nbDupls != 0) {
17773 j = bind->nbNodes + newDupls;
17774 while (j < duplTop) {
17775 parNode = parBind->nodeTable[j];
17776 for (k = 0; k < bind->definition->nbFields; k++) {
17777 key = node->keys[k];
17778 parKey = parNode->keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017779 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017780 key->compValue,
17781 parKey->type, parKey->compValue);
17782 if (ret == -1) {
17783 /* TODO: Internal error */
17784 return(-1);
17785 } else if (ret == 0)
17786 break;
17787
17788 }
17789 if (ret == 1)
17790 /* Duplicate found. */
17791 break;
17792 j++;
17793 }
17794 if (j != duplTop) {
17795 /* Duplicate found. */
17796 continue;
17797 }
17798 }
17799 /*
17800 * ... and with every key-sequence of the parent node.
17801 */
17802 j = 0;
17803 while (j < oldNum) {
17804 parNode = parBind->nodeTable[j];
17805 /*
17806 * Compare key by key.
17807 */
17808 for (k = 0; k < parBind->definition->nbFields; k++) {
17809 key = node->keys[k];
17810 parKey = parNode->keys[k];
17811
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017812 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017813 key->compValue,
17814 parKey->type, parKey->compValue);
17815 if (ret == -1) {
17816 /* TODO: Internal error */
17817 } else if (ret == 0)
17818 break;
17819
17820 }
17821 if (ret == 1)
17822 /*
17823 * The key-sequences are equal.
17824 */
17825 break;
17826 j++;
17827 }
17828 if (j != oldNum) {
17829 /*
17830 * Handle duplicates.
17831 */
17832 newDupls++;
17833 oldNum--;
17834 parBind->nbNodes--;
17835 /*
17836 * Move last old item to pos of duplicate.
17837 */
17838 parBind->nodeTable[j] =
17839 parBind->nodeTable[oldNum];
17840
17841 if (parBind->nbNodes != oldNum) {
17842 /*
17843 * If new items exist, move last new item to
17844 * last of old items.
17845 */
17846 parBind->nodeTable[oldNum] =
17847 parBind->nodeTable[parBind->nbNodes];
17848 }
17849 /*
17850 * Move duplicate to last pos of new/old items.
17851 */
17852 parBind->nodeTable[parBind->nbNodes] = parNode;
17853
17854 } else {
17855 /*
17856 * Add the node-table entry (node and key-sequence) of
17857 * the child node to the node table of the parent node.
17858 */
17859 if (parBind->nodeTable == NULL) {
17860 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17861 xmlMalloc(1 * sizeof(xmlSchemaPSVIIDCNodePtr));
17862 if (parBind->nodeTable == NULL) {
17863 xmlSchemaVErrMemory(NULL,
17864 "allocating IDC list of node-table items", NULL);
17865 return(-1);
17866 }
17867 parBind->sizeNodes = 1;
17868 } else if (duplTop >= parBind->sizeNodes) {
17869 parBind->sizeNodes++;
17870 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17871 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
17872 sizeof(xmlSchemaPSVIIDCNodePtr));
17873 if (parBind->nodeTable == NULL) {
17874 xmlSchemaVErrMemory(NULL,
17875 "re-allocating IDC list of node-table items", NULL);
17876 return(-1);
17877 }
17878 }
17879
17880 /*
17881 * Move first old duplicate to last position
17882 * of old duplicates +1.
17883 */
17884 if (parBind->nbDupls != 0) {
17885 parBind->nodeTable[duplTop] =
17886 parBind->nodeTable[parBind->nbNodes + newDupls];
17887 }
17888 /*
17889 * Move first new duplicate to last position of
17890 * new duplicates +1.
17891 */
17892 if (newDupls != 0) {
17893 parBind->nodeTable[parBind->nbNodes + newDupls] =
17894 parBind->nodeTable[parBind->nbNodes];
17895 }
17896 /*
17897 * Append the new node-table entry to the 'new node-table
17898 * entries' section.
17899 */
17900 parBind->nodeTable[parBind->nbNodes] = node;
17901 parBind->nbNodes++;
17902 duplTop++;
17903 }
17904 }
17905 parBind->nbDupls += newDupls;
17906 break;
17907 }
17908 if (parBind->next == NULL)
17909 lastParBind = parBind;
17910 parBind = parBind->next;
17911 }
17912 if (parBind == NULL) {
17913 /*
17914 * No binding for the IDC was found: create a new one and
17915 * copy all node-tables.
17916 */
17917 parBind = xmlSchemaIDCNewBinding(bind->definition);
17918 if (parBind == NULL)
17919 return(-1);
17920
17921 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17922 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
17923 if (parBind->nodeTable == NULL) {
17924 xmlSchemaVErrMemory(NULL,
17925 "allocating an array of IDC node-table items", NULL);
17926 xmlSchemaIDCFreeBinding(parBind);
17927 return(-1);
17928 }
17929 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017930 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017931 memcpy(parBind->nodeTable, bind->nodeTable,
17932 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017933 if (*parTable == NULL)
17934 *parTable = parBind;
17935 else
17936 lastParBind->next = parBind;
17937 }
17938 bind = bind->next;
17939 }
17940 return (0);
17941}
17942
17943/**
17944 * xmlSchemaCheckCVCIDCKeyRef:
17945 * @vctxt: the WXS validation context
17946 * @elemDecl: the element declaration
17947 *
17948 * Check the cvc-idc-keyref constraints.
17949 */
17950static int
17951xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
17952{
17953 xmlSchemaPSVIIDCBindingPtr refbind, bind;
17954
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017955 refbind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017956 /*
17957 * Find a keyref.
17958 */
17959 while (refbind != NULL) {
17960 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17961 int i, j, k, res;
17962 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
17963 xmlSchemaPSVIIDCKeyPtr refKey, key;
17964
17965 /*
17966 * Find the referred key/unique.
17967 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017968 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017969 do {
17970 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
17971 bind->definition)
17972 break;
17973 bind = bind->next;
17974 } while (bind != NULL);
17975
17976 /*
17977 * Search for a matching key-sequences.
17978 */
17979 for (i = 0; i < refbind->nbNodes; i++) {
17980 res = 0;
17981 if (bind != NULL) {
17982 refKeys = refbind->nodeTable[i]->keys;
17983 for (j = 0; j < bind->nbNodes; j++) {
17984 keys = bind->nodeTable[j]->keys;
17985 for (k = 0; k < bind->definition->nbFields; k++) {
17986 refKey = refKeys[k];
17987 key = keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017988 res = xmlSchemaAreValuesEqual(vctxt,
17989 key->type, key->compValue,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017990 refKey->type, refKey->compValue);
17991 if (res == 0)
17992 break;
17993 else if (res == -1) {
17994 return (-1);
17995 }
17996 }
17997 if (res == 1) {
17998 /*
17999 * Match found.
18000 */
18001 break;
18002 }
18003 }
18004 }
18005 if (res == 0) {
18006 /* TODO: Report the key-sequence. */
18007 xmlSchemaVCustomErr(vctxt,
18008 XML_SCHEMAV_CVC_IDC,
18009 refbind->nodeTable[i]->node,
18010 (xmlSchemaTypePtr) refbind->definition,
18011 "No matching key-sequence found", NULL);
18012 }
18013 }
18014 }
18015 refbind = refbind->next;
18016 }
18017 return (0);
18018}
18019#endif /* IDC_ENABLED */
18020
18021#ifdef ELEM_INFO_ENABLED
18022/**
18023 * xmlSchemaBeginElement:
18024 * @vctxt: the WXS validation context
18025 *
18026 * Just a temporary workaround to simulate streaming validation
18027 * a bit.
18028 */
18029static void
18030xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
18031{
18032 vctxt->depth++;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018033 vctxt->nodeInfo = xmlSchemaGetFreshElemInfo(vctxt, vctxt->depth);
18034 vctxt->nodeInfo->node = vctxt->node;
18035 vctxt->nodeInfo->localName = vctxt->node->name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018036 if (vctxt->node->ns != NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018037 vctxt->nodeInfo->namespaceName = vctxt->node->ns->href;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018038 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018039 vctxt->nodeInfo->namespaceName = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018040}
18041
18042/**
18043 * xmlSchemaEndElement:
18044 * @vctxt: the WXS validation context
18045 *
18046 * Just a temporary workaround to simulate streaming validation
18047 * a bit.
18048 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018049static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018050xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
18051{
18052 if (vctxt->depth < 0) {
18053 /* TODO: raise error? */
18054 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018055 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018056 }
18057#ifdef IDC_ENABLED
18058 /*
18059 * Evaluate the history of changes of active state objects.
18060 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018061 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
18062 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018063
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018064 if (vctxt->nodeInfo->value != NULL) {
18065 xmlSchemaFreeValue(vctxt->nodeInfo->value);
18066 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018067 }
18068 /*
18069 * TODO: 6 The element information item must be ·valid· with respect to each of
18070 * the {identity-constraint definitions} as per Identity-constraint
18071 * Satisfied (§3.11.4).
18072 */
18073 /*
18074 * Validate IDC keyrefs.
18075 */
18076 xmlSchemaCheckCVCIDCKeyRef(vctxt);
18077#endif
18078
18079 /*
18080 * Merge/free the IDC table.
18081 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018082 if (vctxt->nodeInfo->idcTable != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018083#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018084#ifdef DEBUG_IDC
18085 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018086 vctxt->nodeInfo->namespaceName,
18087 vctxt->nodeInfo->localName,
18088 vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018089#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018090 if (vctxt->depth > 0) {
18091 /*
18092 * Merge the IDC node table with the table of the parent node.
18093 */
18094 xmlSchemaBubbleIDCNodeTables(vctxt);
18095 }
18096 /*
18097 * TODO: Don't free the PSVI IDC tables if they are
18098 * requested for the PSVI.
18099 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018100 xmlSchemaIDCFreeIDCTable(vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018101#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018102 vctxt->nodeInfo->idcTable = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018103 }
18104
18105 /*
18106 * Cleanup IDC matchers.
18107 */
18108#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018109 if (vctxt->nodeInfo->idcMatchers != NULL) {
18110 xmlSchemaIDCFreeMatcherList(vctxt->nodeInfo->idcMatchers);
18111 vctxt->nodeInfo->idcMatchers = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018112 }
18113#endif
18114
18115 /*
18116 * Skip further processing if we are on the validation root.
18117 */
18118 if (vctxt->depth == 0) {
18119 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018120 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018121 }
18122
18123 /*
18124 * Reset the bubbleDepth if needed.
18125 */
18126#ifdef IDC_ENABLED
18127 if (vctxt->aidcs != NULL) {
18128 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
18129 do {
18130 if (aidc->bubbleDepth == vctxt->depth) {
18131 /*
18132 * A bubbleDepth of a key/unique IDC matches the current
18133 * depth, this means that we are leaving the scope of the
18134 * top-most keyref IDC.
18135 */
18136 aidc->bubbleDepth = -1;
18137 }
18138 aidc = aidc->next;
18139 } while (aidc != NULL);
18140 }
18141#endif
18142 vctxt->depth--;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018143 /*
18144 * Clear the current elemInfo.
18145 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018146 if (vctxt->nodeInfo->value != NULL) {
18147 xmlSchemaFreeValue(vctxt->nodeInfo->value);
18148 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018149 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018150 vctxt->nodeInfo = vctxt->elemInfos[vctxt->depth];
18151 vctxt->node = vctxt->nodeInfo->node;
18152
18153 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018154}
18155
18156#endif /* ELEM_INFO_ENABLED */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018157
18158/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018159 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000018160 * @ctxt: a schema validation context
18161 * @node: the top node.
18162 *
18163 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018164 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000018165 *
18166 * Returns 0 if the element is schemas valid, a positive error code
18167 * number otherwise and -1 in case of internal or API error.
18168 */
18169static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018170xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
18171 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018172{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018173 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018174 int ret = 0;
18175 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018176 xmlAttrPtr attr;
18177 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018178 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000018179
18180 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018181 * This one is called by xmlSchemaValidateElementByWildcardInternal,
18182 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018183 * Note that @elemDecl will be the declaration and never the
18184 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018185 */
Daniel Veillard3646d642004-06-02 19:19:14 +000018186
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018187 if (ctxt == NULL) {
18188 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
18189 "Internal error: xmlSchemaValidateElementByDeclaration, "
18190 "bad arguments.\n",
18191 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018192 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018193 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018194
18195 elem = ctxt->node;
18196
18197 /*
18198 * cvc-elt (3.3.4) : 1
18199 */
18200 if (elemDecl == NULL) {
18201 xmlSchemaVCustomErr(ctxt,
18202 XML_SCHEMAV_CVC_ELT_1,
18203 elem, NULL,
18204 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018205 /*
18206 * Evaluate IDCs even if an error occured.
18207 */
18208#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018209 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018210 return (-1);
18211#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018212 return (ctxt->err);
18213 }
18214 /*
18215 * cvc-elt (3.3.4) : 2
18216 */
18217 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
18218 xmlSchemaVCustomErr(ctxt,
18219 XML_SCHEMAV_CVC_ELT_2,
18220 elem, NULL,
18221 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018222 /*
18223 * Evaluate IDCs even if an error occured.
18224 */
18225#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018226 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018227 return (-1);
18228#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018229 return (ctxt->err);
18230 }
18231
18232 /*
18233 * cvc-elt (3.3.4) : 3
18234 * Handle 'xsi:nil'.
18235 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018236
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018237 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018238 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018239 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18240 ctxt->node = (xmlNodePtr) attr;
18241 ctxt->cur = attr->children;
18242 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
18243 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
18244 BAD_CAST attrValue, 1, 1, 1, 1);
18245 ctxt->node = elem;
18246 ctxt->type = (xmlSchemaTypePtr) elemDecl;
18247 if (ret < 0) {
18248 xmlSchemaVCustomErr(ctxt,
18249 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018250 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018251 "Internal error: xmlSchemaValidateElementByDeclaration, "
18252 "validating the attribute 'xsi:nil'", NULL);
18253 if (attrValue != NULL)
18254 xmlFree(attrValue);
18255 return (-1);
18256 }
18257 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018258 /*
18259 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018260 */
18261 xmlSchemaVCustomErr(ctxt,
18262 XML_SCHEMAV_CVC_ELT_3_1,
18263 elem, NULL,
18264 "The element is not 'nillable'", NULL);
18265 } else {
18266 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018267 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018268 ret = 0;
18269 /*
18270 * cvc-elt (3.3.4) : 3.2.1
18271 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018272 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
18273 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018274 xmlSchemaVCustomErr(ctxt,
18275 XML_SCHEMAV_CVC_ELT_3_2_1,
18276 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018277 elem, (xmlSchemaTypePtr) elemDecl,
18278 "The 'nilled' element must have no character or "
18279 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018280 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
18281 }
18282 /*
18283 * cvc-elt (3.3.4) : 3.2.2
18284 */
18285 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
18286 (elemDecl->value != NULL)) {
18287 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
18288 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018289 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018290 "There is a fixed value constraint defined for "
18291 "the 'nilled' element", NULL);
18292 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
18293 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018294 if (ret == 0)
18295 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018296 }
18297 }
18298 if (attrValue != NULL)
18299 xmlFree(attrValue);
18300 }
18301
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018302
18303 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018304 /*
18305 * cvc-elt (3.3.4) : 4
18306 * Handle 'xsi:type'.
18307 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018308
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018309 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
18310 if (attr != NULL) {
18311 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018312
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018313 /*
18314 * TODO: We should report a *warning* that the type was overriden
18315 * by the instance.
18316 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018317
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018318 /*
18319 * cvc-elt (3.3.4) : 4.1
18320 */
18321 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18322 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
18323 &nsName, &local);
18324 if (ret < 0) {
18325 xmlSchemaVCustomErr(ctxt,
18326 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018327 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018328 "Internal error: xmlSchemaValidateElementByDeclaration, "
18329 "validating the attribute 'xsi:type'", NULL);;
18330 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018331 FREE_AND_NULL(nsName)
18332 FREE_AND_NULL(local)
18333 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018334 } else if (ret == 1) {
18335 xmlSchemaVSimpleTypeErr(ctxt,
18336 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18337 (xmlNodePtr) attr, attrValue,
18338 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
18339 } else if (ret == 2) {
18340 xmlSchemaVCustomErr(ctxt,
18341 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18342 (xmlNodePtr) attr,
18343 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18344 "The QName value '%s' has no "
18345 "corresponding namespace declaration in scope",
18346 attrValue);
18347 } else {
18348 /*
18349 * cvc-elt (3.3.4) : 4.2
18350 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018351 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
18352 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018353 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018354
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018355 xmlSchemaVCustomErr(ctxt,
18356 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018357 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018358 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18359 "The value %s does not resolve to a type "
18360 "definition",
18361 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
18362 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018363 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018364 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018365 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018366 */
18367 }
18368 }
18369 FREE_AND_NULL(attrValue)
18370 FREE_AND_NULL(nsName)
18371 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018372 }
18373 /* TODO: Change the handling of missing types according to
18374 * the spec.
18375 */
18376 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018377 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018378 XML_SCHEMAV_CVC_TYPE_1,
18379 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018380 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018381 /*
18382 * Evaluate IDCs even if an error occured.
18383 */
18384#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018385 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018386 return (-1);
18387#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018388 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018389 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018390
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018391 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018392 * Remember the actual-type definition.
18393 */
18394#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018395 ctxt->nodeInfo->typeDef = actualType;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018396#endif
18397
18398 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018399 * TODO: Since this should be already checked by the content model automaton,
18400 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
18401 * has been changed to XML_SCHEMAV_INTERNAL.
18402 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018403 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000018404 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018405 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018406 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018407 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018408 "Element %s: missing child %s\n",
18409 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018410 }
18411 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018412 }
18413 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018414 /*
18415 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018416 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018417 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000018418 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018419 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018420 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018421 "Element %s: missing child %s found %s\n",
18422 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018423 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018424 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018425 */
18426 if (elemHasContent == -1)
18427 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018428
18429 /*
18430 * IDC: Register identity-constraint XPath matchers.
18431 */
18432#ifdef IDC_ENABLED
18433 if (elemDecl->idcs != NULL)
18434 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
18435 /*
18436 * Evaluate IDCs.
18437 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018438 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018439 return (-1);
18440#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018441 /*
18442 * cvc-elt (3.3.4) : 5
18443 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018444 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018445 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018446 * cvc-elt (3.3.4) : 5.1
18447 * If the declaration has a {value constraint},
18448 * the item has neither element nor character [children] and
18449 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018450 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018451 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
18452 /*
18453 * cvc-elt (3.3.4) : 5.1.1
18454 * If the ·actual type definition· is a ·local type definition·
18455 * then the canonical lexical representation of the {value constraint}
18456 * value must be a valid default for the ·actual type definition· as
18457 * defined in Element Default Valid (Immediate) (§3.3.6).
18458 */
18459 /*
18460 * NOTE: 'local' above means types aquired by xsi:type.
18461 */
18462 ret = 0;
18463 if (actualType != elemDecl->subtypes) {
18464 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
18465 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018466 elemDecl->value, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018467 if (ret < 0) {
18468 xmlSchemaVCustomErr(ctxt,
18469 XML_SCHEMAV_INTERNAL,
18470 elem, actualType,
18471 "Internal error: xmlSchemaValidateElementByDeclaration, "
18472 "validating a default value", NULL);
18473 return (-1);
18474 }
18475 }
18476 /*
18477 * cvc-elt (3.3.4) : 5.1.2
18478 * The element information item with the canonical lexical
18479 * representation of the {value constraint} value used as its
18480 * ·normalized value· must be ·valid· with respect to the
18481 * ·actual type definition· as defined by Element Locally Valid (Type)
18482 * (§3.3.4).
18483 */
18484 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018485 * Disable validation of the simple content, if it was already
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018486 * done above.
18487 */
18488 if (ret == 0) {
18489 if (actualType != elemDecl->subtypes)
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018490 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018491 else
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018492 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018493 ctxt->node = elem;
18494 if (ret < 0) {
18495 xmlSchemaVCustomErr(ctxt,
18496 XML_SCHEMAV_INTERNAL,
18497 elem, actualType,
18498 "Internal error: xmlSchemaValidateElementByDeclaration, "
18499 "validating against the type", NULL);
18500 return (-1);
18501 }
18502 /*
18503 * PSVI: Create a text node on the instance element.
18504 */
18505 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
18506 xmlNodePtr textChild;
18507
18508 textChild = xmlNewText(elemDecl->value);
18509 if (textChild == NULL) {
18510 xmlSchemaVCustomErr(ctxt,
18511 XML_SCHEMAV_INTERNAL,
18512 elem, actualType,
18513 "Internal error: xmlSchemaValidateElementByDeclaration, "
18514 "could not create a default text node for the instance",
18515 NULL);
18516 } else
18517 xmlAddChild(elem, textChild);
18518 }
18519 }
18520
18521 } else {
18522 /*
18523 * 5.2.1 The element information item must be ·valid· with respect
18524 * to the ·actual type definition· as defined by Element Locally
18525 * Valid (Type) (§3.3.4).
18526 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018527 ret = xmlSchemaValidateElementByType(ctxt, actualType, nilled, 1);
18528 /*
18529 * Consume the computed value for IDCs, ect. Note that default
18530 * values are not supported yet.
18531 */
18532#ifdef ELEM_INFO_ENABLED
18533 if (ctxt->value != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018534 ctxt->nodeInfo->value = ctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018535 ctxt->value = NULL;
18536 }
18537#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018538 ctxt->node = elem;
18539 if (ret < 0) {
18540 xmlSchemaVCustomErr(ctxt,
18541 XML_SCHEMAV_INTERNAL,
18542 elem, actualType,
18543 "Internal error: xmlSchemaValidateElementByDeclaration, "
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018544 "calling validation by type", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018545 return (-1);
18546 }
18547 /*
18548 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
18549 * not applied, all of the following must be true:
18550 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018551 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
18552 /*
18553 * 5.2.2.1 The element information item must have no element
18554 * information item [children].
18555 *
18556 * TODO REDUNDANT: If the actual type exists, the above call to
18557 * xmlSchemaValidateElementByType will already check for element
18558 * nodes.
18559 */
18560 if (xmlSchemaHasElemContent(elem)) {
18561 xmlSchemaVCustomErr(ctxt,
18562 XML_SCHEMAV_CVC_ELT_5_2_2_1,
18563 elem, (xmlSchemaTypePtr) elemDecl,
18564 "Elements in the content are not allowed if it is "
18565 "constrained by a fixed value", NULL);
18566 } else {
18567 /*
18568 * 5.2.2.2 The appropriate case among the following must
18569 * be true:
18570 */
18571
18572 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
18573 xmlChar *value;
18574 /*
18575 * 5.2.2.2.1 If the {content type} of the ·actual type
18576 * definition· is mixed, then the *initial value* of the
18577 * item must match the canonical lexical representation
18578 * of the {value constraint} value.
18579 *
18580 * ... the *initial value* of an element information
18581 * item is the string composed of, in order, the
18582 * [character code] of each character information item in
18583 * the [children] of that element information item.
18584 */
18585 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18586 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18587 /*
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 xmlSchemaVCustomErr(ctxt,
18592 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
18593 elem, (xmlSchemaTypePtr) elemDecl,
18594 "The value does not match the cononical "
18595 "lexical representation of the fixed constraint",
18596 NULL);
18597 }
18598 if (value != NULL)
18599 xmlFree(value);
18600 } else if ((actualType->contentType ==
18601 XML_SCHEMA_CONTENT_SIMPLE) ||
18602 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
18603 xmlChar *value;
18604
18605 /*
18606 * 5.2.2.2.2 If the {content type} of the ·actual type
18607 * definition· is a simple type definition, then the
18608 * *actual value* of the item must match the canonical
18609 * lexical representation of the {value constraint} value.
18610 */
18611 /*
18612 * TODO: *actual value* is the normalized value, impl. this.
18613 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018614 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018615 *
18616 */
18617 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18618 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18619 xmlSchemaVCustomErr(ctxt,
18620 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
18621 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018622 "The normalized value does not match the canonical "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018623 "lexical representation of the fixed constraint",
18624 NULL);
18625 }
18626 if (value != NULL)
18627 xmlFree(value);
18628
18629 }
18630 /*
18631 * TODO: What if the content type is not 'mixed' or simple?
18632 */
18633
18634 }
18635
18636 }
18637 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018638 /*
18639 * TODO: 7 If the element information item is the ·validation root·, it must be
18640 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
18641 */
18642
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018643 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018644}
18645
Daniel Veillard4255d502002-04-16 15:50:10 +000018646/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018647 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018648 * @ctxt: a schema validation context
18649 * @node: the top node.
18650 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018651 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
18652 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018653 *
18654 * Returns 0 if the element is valid, a positive error code
18655 * number otherwise and -1 in case of an internal error.
18656 */
18657static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018658xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
18659 xmlSchemaWildcardPtr wild,
18660 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018661{
18662 const xmlChar *uri;
18663 int ret = 0;
18664 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018665
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018666 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018667 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
18668 if (ret == -1) {
18669 xmlSchemaVCustomErr(ctxt,
18670 XML_SCHEMAV_INTERNAL,
18671 ctxt->node, NULL,
18672 "Internal error: xmlSchemaValidateElement, "
18673 "assembling schema by xsi", NULL);
18674 return (-1);
18675 }
18676 /*
18677 * NOTE: We won't react on schema parser errors here.
18678 * TODO: But a warning would be nice.
18679 */
18680 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018681 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
18682 xmlSchemaElementPtr decl = NULL;
18683
18684 if (node->ns != NULL)
18685 decl = xmlHashLookup3(ctxt->schema->elemDecl,
18686 node->name, node->ns->href, NULL);
18687 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018688 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
18689 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018690 if (decl != NULL) {
18691 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018692 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018693 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018694 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018695 "Internal error: xmlSchemaValidateAnyInternal, "
18696 "validating an element in the context of a wildcard.",
18697 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000018698 }
18699 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018700 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
18701 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018702 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018703 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018704 /*
18705 * Evaluate IDCs even if a validation error occured.
18706 */
18707#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018708 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018709 return(-1);
18710#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018711 return (ctxt->err);
18712 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018713 /*
18714 * Evaluate IDCs; we need to know if an IDC field resolves to
18715 * such a node. This node has no type definition and will
18716 * definitely result in an IDC validation error if an IDC field
18717 * resolves.
18718 */
18719#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018720 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018721 return(-1);
18722#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018723 }
18724 if (node->children != NULL) {
18725 child = node->children;
18726 do {
18727 if (child->type == XML_ELEMENT_NODE) {
18728 if (child->ns != NULL)
18729 uri = child->ns->href;
18730 else
18731 uri = NULL;
18732 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018733 /* TODO: error code. */
18734 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018735 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018736 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000018737 return (ctxt->err);
18738 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018739#ifdef ELEM_INFO_ENABLED
18740 ctxt->node = child;
18741 xmlSchemaBeginElement(ctxt);
18742#endif
18743 /*
18744 * Recurse over the children.
18745 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018746 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
18747 wild, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018748 if (ret == -1)
18749 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018750#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018751 if (xmlSchemaEndElement(ctxt) == -1)
18752 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018753#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018754 if (ret != 0)
18755 return (ret);
18756 }
18757 child = child->next;
18758 } while (child != NULL);
18759 }
18760 return (0);
18761}
18762
18763/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018764 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018765 * @ctxt: a schema validation context
18766 *
18767 * Returns 0 if the element is valid, a positive error code
18768 * number otherwise and -1 in case of an internal or API error.
18769 */
18770static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018771xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
18772 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018773{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018774 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
18775 (ctxt->node == NULL)) {
18776 xmlSchemaVCustomErr(ctxt,
18777 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
18778 "Internal error: xmlSchemaValidateElementByWildcard, "
18779 "bad arguments", NULL);
18780 return (-1);
18781 }
18782 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
18783 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000018784}
18785
18786/**
William M. Brack2f2a6632004-08-20 23:09:47 +000018787 * xmlSchemaValidateAnyTypeContent:
18788 * @ctxt: a schema validation context
18789 * @node: the current element
18790 *
18791 * This one validates the content of an element of the type
18792 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
18793 * thus elements in the subtree will be validated, if a corresponding
18794 * declaration in the schema exists.
18795 *
18796 * Returns 0 if the element and its subtree is valid, a positive error code
18797 * otherwise and -1 in case of an internal or API error.
18798 */
18799static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018800xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
18801 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000018802{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018803 xmlSchemaTypePtr oldtype;
18804 xmlNodePtr top, cur;
18805 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000018806 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018807
18808 if ((type == NULL) || (ctxt->node == NULL))
18809 return (-1);
18810
18811 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018812 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018813
18814 oldtype = ctxt->type;
18815 top = ctxt->node;
18816 /*
18817 * STREAM: Child nodes are processed.
18818 */
18819 cur = ctxt->node->children;
18820 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018821 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018822 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018823 /*
18824 * The process contents of the wildcard is "lax", thus
18825 * we need to validate the element if a declaration
18826 * exists.
18827 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018828 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018829 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018830 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018831 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018832 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018833 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018834 ctxt->node = cur;
18835 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
18836 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000018837 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018838 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000018839 "Internal error: xmlSchemaValidateAnyTypeContent, "
18840 "validating an element in the context of a wildcard.",
18841 NULL, NULL);
18842 return (ret);
18843 } else if (ret > 0)
18844 return (ret);
18845 skipContent = 1;
18846 }
18847 }
18848 /*
18849 * Browse the full subtree, deep first.
18850 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018851 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018852 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018853 cur = cur->children;
18854 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018855 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018856 cur = cur->next;
18857 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018858 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018859 while (cur != top) {
18860 if (cur->parent != NULL)
18861 cur = cur->parent;
18862 if ((cur != top) && (cur->next != NULL)) {
18863 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000018864 break;
18865 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018866 if (cur->parent == NULL) {
18867 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018868 break;
18869 }
18870 }
18871 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018872 if (cur == top)
18873 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018874 } else
18875 break;
18876 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018877 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000018878 return (0);
18879}
18880
18881/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018882 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000018883 * @ctxt: a schema validation context
18884 * @node: the top node.
18885 *
18886 * Validate the content of an element expected to be a complex type type
18887 * xmlschema-1.html#cvc-complex-type
18888 * Validation Rule: Element Locally Valid (Complex Type)
18889 *
18890 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000018891 * number otherwise and -1 in case of internal or API error.
18892 * Note on reported errors: Although it might be nice to report
18893 * the name of the simple/complex type, used to validate the content
18894 * of a node, it is quite unnecessary: for global defined types
18895 * the local name of the element is equal to the NCName of the type,
18896 * for local defined types it makes no sense to output the internal
18897 * computed name of the type. TODO: Instead, one should attach the
18898 * struct of the type involved to the error handler - this allows
18899 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000018900 */
18901static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018902xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018903 xmlSchemaTypePtr type,
18904 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018905{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018906 xmlSchemaTypePtr oldtype;
18907 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018908 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000018909 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018910 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000018911
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018912 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
18913 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018914
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018915 oldtype = ctxt->type;
18916 ctxt->type = type;
18917 elem = ctxt->node;
18918
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018919 /*
18920 * Verify the attributes
18921 */
18922 /*
18923 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018924 */
18925 /* NOTE: removed, since a check for abstract is
18926 * done in the cvc-type constraint.
18927 *
18928 *
18929 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
18930 * xmlSchemaVComplexTypeErr(ctxt,
18931 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
18932 * elem, type,
18933 * "The type definition is abstract");
18934 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
18935 *}
18936 */
18937
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018938 attrs = ctxt->attr;
18939 attrTop = ctxt->attrTop;
18940 /*
18941 * STREAM: Attribute nodes are processed.
18942 */
18943 xmlSchemaRegisterAttributes(ctxt, elem->properties);
18944 xmlSchemaValidateAttributes(ctxt, elem, type);
18945 if (ctxt->attr != NULL)
18946 xmlSchemaFreeAttributeStates(ctxt->attr);
18947 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018948 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018949
18950 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018951 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018952 * model was defined. Somehow ->contModel is always not NULL
18953 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018954 * TODO: Check if the obove still occurs.
18955 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018956 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018957 case XML_SCHEMA_CONTENT_EMPTY: {
18958 /*
18959 * 1 If the {content type} is empty, then the element information
18960 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000018961 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018962 /*
18963 * TODO: Is the entity stuff correct?
18964 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018965 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018966 xmlSchemaVComplexTypeErr(ctxt,
18967 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018968 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018969 "Character or element content is not allowed, "
18970 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018971 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018972 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018973 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018974 case XML_SCHEMA_CONTENT_MIXED:
18975 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018976 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018977 /*
18978 * The type has 'anyType' as its base and no content model
18979 * is defined -> use 'anyType' as the type to validate
18980 * against.
18981 */
18982 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
18983 /* TODO: Handle -1. */
18984 break;
18985 }
18986 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018987 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018988 {
18989 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018990 xmlChar *values[10];
18991 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018992
18993 /*
18994 * Content model check initialization.
18995 */
18996 if (type->contModel != NULL) {
18997 oldregexp = ctxt->regexp;
18998 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
18999 (xmlRegExecCallbacks)
19000 xmlSchemaValidateCallback, ctxt);
19001#ifdef DEBUG_AUTOMATA
19002 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
19003#endif
19004 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019005 /*
19006 * STREAM: Children are processed.
19007 */
19008 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019009 while (child != NULL) {
19010 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019011 if (child->ns != NULL)
19012 nsUri = child->ns->href;
19013 else
19014 nsUri = NULL;
19015 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019016 child->name, nsUri, child);
19017 if (ctxt->err == XML_SCHEMAV_INTERNAL)
19018 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019019 /*
19020 * URGENT TODO: Could we anchor an error report
19021 * here to notify of invalid elements?
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019022 * TODO: Perhaps it would be better to report
19023 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019024 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019025#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000019026 if (ret < 0)
19027 xmlGenericError(xmlGenericErrorContext,
19028 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000019029 else
19030 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019031 " --> %s\n", child->name);
19032#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019033 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019034 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
19035 &values[0], &terminal);
19036 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019037 XML_SCHEMAV_ELEMENT_CONTENT,
19038 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019039 "This element is not expected",
19040 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019041 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019042 /*
19043 * Note that this will skip further validation of the
19044 * content.
19045 */
19046 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019047 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019048 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
19049 /*
19050 * TODO: Ask Daniel if this are all character nodes.
19051 */
19052 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
19053 (child->type == XML_ENTITY_NODE) ||
19054 (child->type == XML_ENTITY_REF_NODE) ||
19055 (child->type == XML_CDATA_SECTION_NODE))) {
19056 /*
19057 * 2.3 If the {content type} is element-only, then the
19058 * element information item has no character information
19059 * item [children] other than those whose [character
19060 * code] is defined as a white space in [XML 1.0 (Second
19061 * Edition)].
19062 */
William M. Brack2f2a6632004-08-20 23:09:47 +000019063 xmlSchemaVComplexTypeErr(ctxt,
19064 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019065 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019066 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019067 "because the content type is element-only");
19068 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019069 break;
19070 }
19071 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019072 }
19073 /*
19074 * Content model check finalization.
19075 */
19076 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019077 if (ret == 0) {
19078 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
19079 &values[0], &terminal);
19080 if (nbval + nbneg != 0) {
19081 /*
19082 * If a next value still exists, I does not have to
19083 * mean that there's an element missing, since it
19084 * might be an optional element. So double check it.
19085 */
19086 ret = xmlRegExecPushString(ctxt->regexp,
19087 NULL, NULL);
19088 if (ret <= 0) {
19089 ret = 1;
19090 xmlSchemaVComplexTypeElemErr(ctxt,
19091 XML_SCHEMAV_ELEMENT_CONTENT,
19092 elem, type, "Missing child element(s)",
19093 nbval, nbneg, values);
19094 } else
19095 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019096#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019097 xmlGenericError(xmlGenericErrorContext,
19098 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019099#endif
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019100 }
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019101#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019102 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019103 xmlGenericError(xmlGenericErrorContext,
19104 "Element %s content check succeeded\n",
19105 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019106#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019107 }
19108 xmlRegFreeExecCtxt(ctxt->regexp);
19109 ctxt->regexp = oldregexp;
19110 }
19111 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019112 break;
19113 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019114 case XML_SCHEMA_CONTENT_BASIC:
19115 /*
19116 * If the simple content was already validated
19117 * (e.g. a default value), the content need not
19118 * to be validated again.
19119 */
19120 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019121 xmlChar *value = NULL;
19122 /*
19123 * We hit a complexType with a simpleContent resolving
19124 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000019125 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019126 /*
19127 * 2.2 If the {content type} is a simple type definition,
19128 * then the element information item has no element
19129 * information item [children], and the ·normalized value·
19130 * of the element information item is ·valid· with respect
19131 * to that simple type definition as defined by String
19132 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019133 */
19134 /*
19135 * STREAM: Children are processed.
19136 */
19137 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019138 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019139 /*
19140 * TODO: Could the entity stuff produce elements
19141 * as well?
19142 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019143 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019144 xmlSchemaVComplexTypeErr(ctxt,
19145 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019146 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019147 "Element content is not allowed, because "
19148 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019149 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19150 break;
19151 }
19152 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019153 }
19154 ctxt->node = elem;
19155 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019156 if (ret == 0) {
19157 /*
19158 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000019159 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019160 /*
19161 * STREAM: Children are processed.
19162 */
19163 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000019164 value = NULL;
19165 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019166 value = xmlNodeGetContent(elem);
19167 /*
19168 * URGENT TODO: Should facets for the simple type validation be
19169 * disabled, if the derivation of facets for complex types
19170 * is implemented?
19171 */
19172 /*
19173 * NOTE: This call won't check the correct types of the
19174 * content nodes, since this should be done here.
19175 */
19176 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000019177 if (ret > 0) {
19178 /*
19179 * NOTE: Although an error will be reported by
19180 * xmlSchemaValidateSimpleTypeValue, the spec wants
19181 * a specific complex type error to be reported
19182 * additionally.
19183 */
19184 xmlSchemaVComplexTypeErr(ctxt,
19185 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019186 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019187 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019188 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19189 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019190 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019191 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019192 "Element '%s': Error while validating character "
19193 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019194 elem->name, type->name);
19195 if (value != NULL)
19196 xmlFree(value);
19197 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019198 return (-1);
19199 }
William M. Brack2f2a6632004-08-20 23:09:47 +000019200 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019201 if (ret == 0) {
19202 /*
19203 * Apply facets of the complexType. Be sure to pass the
19204 * built-in type to xmlSchemaValidateFacetsInternal.
19205 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019206 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000019207 * are used, or if the facets, defined by this complex type,
19208 * are to be used only. This here applies both facet sets.
19209 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000019210
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019211 ret = xmlSchemaValidateFacetsInternal(ctxt,
19212 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019213 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019214 xmlSchemaVComplexTypeErr(ctxt,
19215 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019216 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019217 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019218 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19219 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019220 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019221 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019222 "Element '%s': Error while validating character "
19223 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000019224 "apply facets.\n",
19225 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019226 if (value != NULL)
19227 xmlFree(value);
19228 ctxt->type = oldtype;
19229 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019230 }
19231 }
19232 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019233 xmlFree(value);
19234
Daniel Veillard01fa6152004-06-29 17:04:39 +000019235 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019236 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019237 default:
19238 TODO xmlGenericError(xmlGenericErrorContext,
19239 "unimplemented content type %d\n",
19240 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000019241 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019242 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019243 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019244}
19245
19246/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019247 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000019248 * @ctxt: a schema validation context
19249 * @elem: an element
19250 * @type: the list of type declarations
19251 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019252 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000019253 *
19254 * Returns 0 if the element is schemas valid, a positive error code
19255 * number otherwise and -1 in case of internal or API error.
19256 */
19257static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019258xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019259 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019260 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019261 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019262{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019263 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000019264
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019265
19266 if ((ctxt == NULL) || (type == NULL)) {
19267 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
19268 "Internal error: xmlSchemaValidateElementByType, "
19269 "bad arguments", NULL);
19270 return (-1);
19271 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019272 /*
19273 * This one is called by "xmlSchemaValidateElementByDeclaration".
19274 * It will forward to the proper validation
19275 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019276 */
19277 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019278 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019279 XML_SCHEMAV_CVC_TYPE_1,
19280 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019281 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019282 return (XML_SCHEMAV_CVC_TYPE_1);
19283 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019284
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019285 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019286 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019287 XML_SCHEMAV_CVC_TYPE_2,
19288 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019289 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019290 return (XML_SCHEMAV_CVC_TYPE_2);
19291 }
19292
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019293 switch (type->type) {
19294 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019295 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
19296 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019297 break;
19298 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019299 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019300 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019301 break;
19302 case XML_SCHEMA_TYPE_BASIC:
19303 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
19304 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
19305 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019306 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019307 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019308 break;
19309 default:
19310 ret = -1;
19311 break;
19312 }
19313 if (ret == -1)
19314 return (-1);
19315 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019316 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019317}
19318
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019319static int
19320xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019321 xmlSchemaAttrStatePtr state)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019322{
19323 xmlChar *value;
19324 const xmlChar *defValue;
19325 xmlSchemaValPtr defVal;
19326 int fixed;
19327 int ret;
19328
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019329 if (ctxt->attrInfo->typeDef == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019330 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
19331 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
19332 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019333 ctxt->node = ctxt->attrInfo->node;
19334 ctxt->cur = ctxt->node->children;
19335 value = xmlNodeListGetString(ctxt->node->doc, ctxt->cur, 1);
19336
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019337 /*
19338 * NOTE: This call also checks the content nodes for correct type.
19339 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019340 ret = xmlSchemaValidateSimpleTypeValue(ctxt, ctxt->attrInfo->typeDef,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019341 value, 1, 1, 1, 1);
19342
19343 /*
19344 * Handle 'fixed' attributes.
19345 */
19346 if (ret > 0) {
19347 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
19348 /*
19349 * NOTE: Fixed value constraints will be not
19350 * applied if the value was invalid, because:
19351 * 1. The validation process does not return a precomputed
19352 * value.
19353 * 2. An invalid value implies a violation of a fixed
19354 * value constraint.
19355 */
19356 } else if (ret == 0) {
19357 state->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019358 if (xmlSchemaGetEffectiveValueConstraint(
19359 (xmlSchemaAttributePtr) ctxt->attrInfo->decl,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019360 &fixed, &defValue, &defVal) && (fixed == 1)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019361
19362 int ws = xmlSchemaGetWhiteSpaceFacetValue(
19363 ctxt->attrInfo->typeDef);
19364
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019365 /*
19366 * cvc-au : Attribute Locally Valid (Use)
19367 * For an attribute information item to be·valid·
19368 * with respect to an attribute use its ·normalized
19369 * value· must match the canonical lexical representation
19370 * of the attribute use's {value constraint} value, if it
19371 * is present and fixed.
19372 */
19373 /*
19374 * NOTE: the validation context holds in ctxt->value the
19375 * precomputed value of the attribute; well for some types,
19376 * fallback to string comparison if no computed value
19377 * exists.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019378 * TODO: Use the *normalized* value and the *canonical* fixed
19379 * value.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019380 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019381 if (ctxt->value != NULL) {
19382 if (defVal == NULL) {
19383 xmlSchemaTypePtr prim;
19384 /*
19385 * Oops, the value was not computed.
19386 */
19387 prim = xmlSchemaGetPrimitiveType(ctxt->attrInfo->typeDef);
19388 if (prim->builtInType == XML_SCHEMAS_STRING) {
19389 xmlSchemaTypePtr builtIn;
19390
19391 builtIn = xmlSchemaGetBuiltInTypeAncestor(
19392 ctxt->attrInfo->typeDef);
19393 defVal = xmlSchemaNewStringValue(
19394 builtIn->builtInType, value);
19395 ((xmlSchemaAttributePtr) ctxt->attrInfo->decl)->defVal =
19396 defVal;
19397 value = NULL;
19398 } else {
19399 xmlSchemaVErr(ctxt, ctxt->attrInfo->node,
19400 XML_SCHEMAV_INTERNAL,
19401 "Internal error: xmlSchemaCheckAttrLocallyValid, "
19402 "could not aquire a precomputed vale",
19403 NULL, NULL);
19404 }
19405 }
19406 if (defVal != NULL) {
19407 if (xmlSchemaCompareValuesWhtsp(ctxt->value,
19408 (xmlSchemaWhitespaceValueType) ws,
19409 defVal, (xmlSchemaWhitespaceValueType) ws) != 0)
19410 state->state =
19411 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
19412 }
19413 } else if (! xmlStrEqual(defValue, BAD_CAST value)) {
19414 /*
19415 * TODO: Remove this and ensure computed values to be
19416 * existent.
19417 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019418 state->state =
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019419 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019420 }
19421 }
19422 }
19423 if (value != NULL) {
19424 xmlFree(value);
19425 }
19426 return (ret);
19427}
19428
Daniel Veillard4255d502002-04-16 15:50:10 +000019429/**
19430 * xmlSchemaValidateAttributes:
19431 * @ctxt: a schema validation context
19432 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000019433 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000019434 *
19435 * Validate the attributes of an element.
19436 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000019437 * 1. Existent, invalid attributes are reported in the form
19438 * "prefix:localName".
19439 * Reason: readability - it is easier to find the actual XML
19440 * representation of the attributes QName.
19441 * 2. Missing attributes are reported in the form
19442 * {"URI", "localName"}.
19443 * This is necessary, since the the prefix need not to be declared
19444 * at all, and thus is not computable.
19445 *
Daniel Veillard4255d502002-04-16 15:50:10 +000019446 * Returns 0 if the element is schemas valid, a positive error code
19447 * number otherwise and -1 in case of internal or API error.
19448 */
19449static int
Daniel Veillard3646d642004-06-02 19:19:14 +000019450xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019451{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019452 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000019453 int ret;
19454 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019455 const xmlChar *defValue;
19456 xmlSchemaValPtr defVal;
19457 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019458 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000019459 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019460 int found;
William M. Brack803812b2004-06-03 02:11:24 +000019461 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019462 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019463 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000019464#ifdef DEBUG_ATTR_VALIDATION
19465 int redundant = 0;
19466#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000019467
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019468
Daniel Veillardc0826a72004-08-10 14:17:33 +000019469 /*
19470 * Allow all attributes if the type is anyType.
19471 */
19472 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
19473 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019474
19475 oldnode = ctxt->node;
19476 if (type != NULL)
19477 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000019478 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019479 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000019480 attrDecl = attrUse->attr;
19481#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019482 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000019483 printf("attr use - use: %d\n", attrDecl->occurs);
19484#endif
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019485 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019486
19487 if (curState->decl == attrUse->attr) {
19488#ifdef DEBUG_ATTR_VALIDATION
19489 redundant = 1;
19490#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019491 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019492 attr = curState->attr;
19493#ifdef DEBUG_ATTR_VALIDATION
19494 printf("attr - name: %s\n", attr->name);
19495 if (attr->ns != NULL)
19496 printf("attr - ns: %s\n", attr->ns->href);
19497 else
19498 printf("attr - ns: none\n");
19499#endif
19500 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019501 if (attr == NULL)
19502 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019503 if (attrDecl->ref != NULL) {
19504 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019505 continue;
19506 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019507 if ((attrDecl->refNs == NULL) ||
19508 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019509 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019510 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019511 continue;
19512 }
19513 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019514 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019515 continue;
19516 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019517 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019518 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019519 if (attr->ns == NULL) {
19520 /*
William M. Bracke7091952004-05-11 15:09:58 +000019521 * accept an unqualified attribute only if the target
19522 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019523 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019524 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000019525 /*
19526 * This check was removed, since the target namespace
19527 * was evaluated during parsing and already took
19528 * "attributeFormDefault" into account.
19529 */
19530 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019531 continue;
19532 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019533 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019534 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019535 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019536 attr->ns->href))
19537 continue;
19538 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019539 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019540#ifdef DEBUG_ATTR_VALIDATION
19541 printf("found\n");
19542#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019543 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000019544 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019545 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
19546 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019547 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019548 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019549 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019550 if (!found) {
19551 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
19552 xmlSchemaAttrStatePtr tmp;
19553
Daniel Veillard3646d642004-06-02 19:19:14 +000019554#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019555 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019556#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019557 /*
19558 * Add a new dummy attribute state.
19559 */
19560 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
19561 if (tmp == NULL) {
19562 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
19563 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019564 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019565 }
19566 tmp->attr = NULL;
19567 tmp->state = XML_SCHEMAS_ATTR_MISSING;
19568 tmp->decl = attrDecl;
19569 tmp->next = NULL;
19570
19571 if (reqAttrStates == NULL) {
19572 reqAttrStates = tmp;
19573 reqAttrStatesTop = tmp;
19574 } else {
19575 reqAttrStatesTop->next = tmp;
19576 reqAttrStatesTop = tmp;
19577 }
19578 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
19579 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
19580 &fixed, &defValue, &defVal))) {
19581 xmlSchemaAttrStatePtr tmp;
19582 /*
19583 * Handle non existent default/fixed attributes.
19584 */
19585 tmp = (xmlSchemaAttrStatePtr)
19586 xmlMalloc(sizeof(xmlSchemaAttrState));
19587 if (tmp == NULL) {
19588 xmlSchemaVErrMemory(ctxt,
19589 "registering schema specified attributes", NULL);
19590 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019591 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019592 }
19593 tmp->attr = NULL;
19594 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
19595 tmp->decl = attrDecl;
19596 tmp->value = defValue;
19597 tmp->next = NULL;
19598
19599 if (defAttrStates == NULL) {
19600 defAttrStates = tmp;
19601 defAttrStates = tmp;
19602 } else {
19603 defAttrStates->next = tmp;
19604 defAttrStatesTop = tmp;
19605 }
19606 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019607 }
19608 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000019609 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019610 /*
19611 * Add required attributes to the attribute states of the context.
19612 */
19613 if (reqAttrStates != NULL) {
19614 if (ctxt->attr == NULL) {
19615 ctxt->attr = reqAttrStates;
19616 } else {
19617 ctxt->attrTop->next = reqAttrStates;
19618 }
19619 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019620 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019621 /*
19622 * Process wildcards.
19623 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019624
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019625 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019626#ifdef DEBUG_ATTR_VALIDATION
19627 xmlSchemaWildcardNsPtr ns;
19628 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019629 if (type->attributeWildcard->processContents ==
19630 XML_SCHEMAS_ANY_LAX)
19631 printf("processContents: lax\n");
19632 else if (type->attributeWildcard->processContents ==
19633 XML_SCHEMAS_ANY_STRICT)
19634 printf("processContents: strict\n");
19635 else
19636 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019637 if (type->attributeWildcard->any)
19638 printf("type: any\n");
19639 else if (type->attributeWildcard->negNsSet != NULL) {
19640 printf("type: negated\n");
19641 if (type->attributeWildcard->negNsSet->value == NULL)
19642 printf("ns: (absent)\n");
19643 else
19644 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
19645 } else if (type->attributeWildcard->nsSet != NULL) {
19646 printf("type: set\n");
19647 ns = type->attributeWildcard->nsSet;
19648 while (ns != NULL) {
19649 if (ns->value == NULL)
19650 printf("ns: (absent)\n");
19651 else
19652 printf("ns: %s\n", ns->value);
19653 ns = ns->next;
19654 }
19655 } else
19656 printf("empty\n");
19657
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019658
19659#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000019660 curState = ctxt->attr;
19661 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019662 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
19663 if (curState->attr->ns != NULL)
19664 nsURI = curState->attr->ns->href;
19665 else
19666 nsURI = NULL;
19667 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
19668 nsURI)) {
19669 /*
19670 * Handle processContents.
19671 */
19672 if ((type->attributeWildcard->processContents ==
19673 XML_SCHEMAS_ANY_LAX) ||
19674 (type->attributeWildcard->processContents ==
19675 XML_SCHEMAS_ANY_STRICT)) {
19676
19677 attr = curState->attr;
19678 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019679 attr->name, nsURI);
19680 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019681 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019682 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019683 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
19684 /* TODO
19685 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
19686 */
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019687 } else if (type->attributeWildcard->processContents ==
19688 XML_SCHEMAS_ANY_LAX) {
19689 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019690 } else
19691 curState->state = XML_SCHEMAS_ATTR_WILD_NO_DECL;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019692 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000019693 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019694 }
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019695 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019696 curState = curState->next;
19697 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019698 }
19699
Daniel Veillardc0826a72004-08-10 14:17:33 +000019700 if (ctxt->attr != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019701 int valueNeeded;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019702
19703 /*
19704 * Validate the value of the attribute.
19705 */
19706 if (ctxt->value != NULL) {
19707 xmlSchemaFreeValue(ctxt->value);
19708 ctxt->value = NULL;
19709 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019710 curState = ctxt->attr;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019711 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019712 valueNeeded = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019713 switch (curState->state) {
19714 case XML_SCHEMAS_ATTR_VALIDATE_VALUE:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019715
19716 /*
19717 * Create an attribute info if needed.
19718 */
19719 if (ctxt->attrInfo == NULL) {
19720 ctxt->attrInfo = (xmlSchemaElemInfoPtr)
19721 xmlMalloc(sizeof(xmlSchemaElemInfo));
19722 if (ctxt->attrInfo == NULL) {
19723 xmlSchemaVErrMemory(ctxt,
19724 "allocating an attribute info", NULL);
19725 goto fatal_exit;
19726 }
19727 }
19728 /*
19729 * Init the attribute info.
19730 */
19731 ctxt->attrInfo->flags = 0;
19732 ctxt->attrInfo->node = (xmlNodePtr) curState->attr;
19733 ctxt->attrInfo->decl = (xmlSchemaTypePtr) curState->decl;
19734 ctxt->attrInfo->value = NULL;
19735 if (curState->decl != NULL)
19736 ctxt->attrInfo->typeDef = curState->decl->subtypes;
19737 else
19738 ctxt->attrInfo->typeDef = NULL;
19739 if (curState->attr->ns != NULL)
19740 ctxt->attrInfo->namespaceName =
19741 curState->attr->ns->href;
19742 else
19743 ctxt->attrInfo->namespaceName = NULL;
19744 ctxt->attrInfo->localName = curState->attr->name;
19745
19746 ctxt->nodeInfo = ctxt->attrInfo;
19747
19748#ifdef IDC_ENABLED
19749 /*
19750 * Evaluate IDCs.
19751 */
19752 if (ctxt->xpathStates != NULL) {
19753 ret = xmlSchemaXPathEvaluate(ctxt,
19754 XML_ATTRIBUTE_NODE);
19755 if (ret == -1)
19756 goto fatal_exit;
19757 }
19758
19759#endif
19760 ret = xmlSchemaCheckAttrLocallyValid(ctxt, curState);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019761 if (ret == -1)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019762 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019763 if ((ret != 0) && (ctxt->value != NULL)) {
19764 xmlSchemaFreeValue(ctxt->value);
19765 ctxt->value = NULL;
19766 }
19767 /* No break on purpose. */
19768 case XML_SCHEMAS_ATTR_CHECKED:
19769#ifdef IDC_ENABLED
19770 if (ctxt->xpathStates != NULL) {
19771 /*
19772 * Evaluate IDCs.
19773 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019774 if (ctxt->value != NULL) {
19775 ctxt->attrInfo->value = ctxt->value;
19776 ctxt->value = NULL;
19777 }
19778 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
19779 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019780 }
19781 break;
19782#endif
19783 default:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019784 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019785 }
19786 curState = curState->next;
19787 }
19788
19789 /*
19790 * Report missing and illegal attributes.
19791 */
19792 curState = ctxt->attr;
19793 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019794 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
19795 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019796 if (curState->decl != NULL) {
19797 if (curState->decl->ref != NULL)
19798 attrDecl = curState->decl->refDecl;
19799 else
19800 attrDecl = curState->decl;
19801 } else
19802 attrDecl = NULL;
19803 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
19804 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
19805 } else if (curState->state ==
19806 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
19807 xmlSchemaVCustomErr(ctxt,
19808 XML_SCHEMAV_CVC_ATTRIBUTE_2,
19809 (xmlNodePtr) attr,
19810 (xmlSchemaTypePtr) attrDecl,
19811 "The type definition is absent",
19812 NULL);
19813 } else if (curState->state ==
19814 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
19815 xmlSchemaVCustomErr(ctxt,
19816 XML_SCHEMAV_CVC_AU,
19817 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
19818 "The value does not match the fixed value "
19819 "constraint", NULL);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019820 } else if (curState->state == XML_SCHEMAS_ATTR_WILD_NO_DECL) {
19821 xmlSchemaVWildcardErr(ctxt,
19822 XML_SCHEMAV_CVC_WILDCARD,
19823 (xmlNodePtr) attr,
19824 type->attributeWildcard,
19825 "No global attribute declaration found, but "
19826 "stipulated by the strict processContents of "
19827 "the wildcard");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019828 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019829 /* TODO: "prohibited" won't ever be touched here!.
19830 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
19831 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019832 /*
19833 * TODO: One might report different error messages
19834 * for the following errors.
19835 */
19836 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019837 xmlSchemaVIllegalAttrErr(ctxt,
19838 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
19839 } else {
19840 xmlSchemaVIllegalAttrErr(ctxt,
19841 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
19842 }
19843 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019844 }
19845 curState = curState->next;
19846 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019847 }
19848
19849 /*
19850 * Add missing default/fixed attributes.
19851 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000019852 if (defAttrStates != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019853 curState = defAttrStates;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000019854
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019855 while (curState != NULL) {
19856 attrDecl = curState->decl;
19857 if (attrDecl->ref != NULL)
19858 attrDecl = attrDecl->refDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019859
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000019860#ifdef IDC_ENABLED
19861 /*
19862 * Evaluate IDCs on default attributes.
19863 */
19864 if (ctxt->xpathStates != NULL) {
19865 /*
19866 * Create an attribute info if needed.
19867 */
19868 if (ctxt->attrInfo == NULL) {
19869 ctxt->attrInfo = (xmlSchemaElemInfoPtr)
19870 xmlMalloc(sizeof(xmlSchemaElemInfo));
19871 if (ctxt->attrInfo == NULL) {
19872 xmlSchemaVErrMemory(ctxt,
19873 "allocating an attribute info", NULL);
19874 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019875 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000019876 }
19877 /*
19878 * Init the attribute info.
19879 */
19880 ctxt->attrInfo->flags = 0;
19881 ctxt->attrInfo->decl = (xmlSchemaTypePtr) attrDecl;
19882 ctxt->attrInfo->node = NULL;
19883 ctxt->attrInfo->typeDef = attrDecl->subtypes;
19884 ctxt->attrInfo->namespaceName = attrDecl->targetNamespace;
19885 ctxt->attrInfo->localName = attrDecl->name;
19886
19887 ctxt->nodeInfo = ctxt->attrInfo;
19888
19889 ret = xmlSchemaXPathEvaluate(ctxt,
19890 XML_ATTRIBUTE_NODE);
19891 if (ret == -1)
19892 goto fatal_exit;
19893 if (ctxt->attrInfo->value != NULL) {
19894 xmlSchemaFreeValue(ctxt->attrInfo->value);
19895 ctxt->attrInfo->value = NULL;
19896 }
19897 if (ret > 0) {
19898 ctxt->attrInfo->value = xmlSchemaCopyValue(attrDecl->defVal);
19899 /* TODO: error on NULL return. */
19900 }
19901 /*
19902 * TODO URGENT: This will consume the precomputed default value,
19903 * so we need to clone it somehow.
19904 */
19905 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
19906 goto fatal_exit;
19907 }
19908#endif
19909
19910 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
19911 /*
19912 * PSVI: Add a new attribute node to the current element.
19913 */
19914 if (attrDecl->targetNamespace == NULL) {
19915 xmlNewProp(elem, attrDecl->name, curState->value);
19916 } else {
19917 xmlNsPtr ns;
19918
19919 ns = xmlSearchNsByHref(elem->doc, elem,
19920 attrDecl->targetNamespace);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019921 if (ns == NULL) {
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000019922 xmlChar prefix[12];
19923 int counter = 1;
19924
19925 attr = curState->attr;
19926 /*
19927 * Create a namespace declaration on the validation
19928 * root node if no namespace declaration is in scope.
19929 */
19930 snprintf((char *) prefix, sizeof(prefix), "p");
19931 /*
19932 * This is somehow not performant, since the ancestor
19933 * axis beyond @elem will be searched as well.
19934 */
19935 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
19936 while (ns != NULL) {
19937 if (counter > 1000) {
19938 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
19939 XML_SCHEMAV_INTERNAL,
19940 "Internal error: xmlSchemaValidateAttributes, "
19941 "could not compute a ns prefix for "
19942 "default/fixed attribute '%s'.\n",
19943 attrDecl->name, NULL);
19944
19945 break;
19946 }
19947 snprintf((char *) prefix,
19948 sizeof(prefix), "p%d", counter++);
19949 ns = xmlSearchNs(elem->doc, elem,
19950 BAD_CAST prefix);
19951 }
19952 if (ns == NULL) {
19953 ns = xmlNewNs(ctxt->validationRoot,
19954 attrDecl->targetNamespace, BAD_CAST prefix);
19955 xmlNewNsProp(elem, ns, attrDecl->name,
19956 curState->value);
19957 }
19958 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019959 xmlNewNsProp(elem, ns, attrDecl->name,
19960 curState->value);
19961 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019962 }
19963 }
19964 curState = curState->next;
19965 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019966 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019967 ret = ctxt->err;
19968 goto exit;
19969
19970fatal_exit:
19971 ret = -1;
19972
19973exit:
19974
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019975 if (defAttrStates != NULL)
19976 xmlSchemaFreeAttributeStates(defAttrStates);
19977
Daniel Veillard3646d642004-06-02 19:19:14 +000019978#ifdef DEBUG_ATTR_VALIDATION
19979 if (redundant)
19980 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019981 "xmlSchemaValidateAttributes: redundant call by "
19982 "type: %s\n", type->name);
Daniel Veillard3646d642004-06-02 19:19:14 +000019983#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019984 ctxt->nodeInfo = ctxt->elemInfos[ctxt->depth];
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019985 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019986 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019987}
19988
19989/**
19990 * xmlSchemaValidateElement:
19991 * @ctxt: a schema validation context
19992 * @elem: an element
19993 *
19994 * Validate an element in a tree
19995 *
19996 * Returns 0 if the element is schemas valid, a positive error code
19997 * number otherwise and -1 in case of internal or API error.
19998 */
19999static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020000xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020001{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020002 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020003 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020004
Daniel Veillardc0826a72004-08-10 14:17:33 +000020005 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020006 * This one is called by xmlSchemaValidateDocument and
20007 * xmlSchemaValidateOneElement.
20008 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020009 if (ctxt->schema == NULL) {
20010 /*
20011 * No schema was specified at time of creation of the validation
20012 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
20013 * of the instance to build a schema.
20014 */
20015 if (ctxt->pctxt == NULL)
20016 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
20017 if (ctxt->pctxt == NULL)
20018 return (-1);
20019 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
20020 if (ctxt->schema == NULL)
20021 return (-1);
20022 /* TODO: assign user data. */
20023 ctxt->pctxt->error = ctxt->error;
20024 ctxt->pctxt->warning = ctxt->warning;
20025 ctxt->xsiAssemble = 1;
20026 } else
20027 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020028 /*
20029 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000020030 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020031 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020032 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
20033 if (ret == -1) {
20034 xmlSchemaVCustomErr(ctxt,
20035 XML_SCHEMAV_INTERNAL,
20036 ctxt->node, NULL,
20037 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020038 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020039 }
20040 /*
20041 * NOTE: We won't react on schema parser errors here.
20042 * TODO: But a warning would be nice.
20043 */
20044 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020045 if (ret != -1) {
20046 if (ctxt->node->ns != NULL)
20047 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
20048 ctxt->node->ns->href);
20049 else
20050 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
20051
20052 if (elemDecl == NULL) {
20053 xmlSchemaVCustomErr(ctxt,
20054 XML_SCHEMAV_CVC_ELT_1,
20055 ctxt->node, NULL,
20056 "No matching global declaration available", NULL);
20057 ret = XML_SCHEMAV_CVC_ELT_1;
20058 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020059#ifdef IDC_ENABLED
20060 /*
20061 * Augment the IDC definitions.
20062 */
20063 if (ctxt->schema->idcDef != NULL) {
20064 xmlHashScan(ctxt->schema->idcDef,
20065 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
20066 }
20067#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020068#ifdef ELEM_INFO_ENABLED
20069 ctxt->depth = -1;
20070 xmlSchemaBeginElement(ctxt);
20071#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020072 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020073#ifdef ELEM_INFO_ENABLED
20074 xmlSchemaEndElement(ctxt);
20075#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020076 if (ret < 0) {
20077 xmlSchemaVCustomErr(ctxt,
20078 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
20079 "Internal error: xmlSchemaValidateElement, "
20080 "calling validation by declaration", NULL);
20081 }
20082 }
20083 }
20084 /* ctxt->xsiAssemble = 0; */
20085 if (ctxt->xsiAssemble) {
20086 if (ctxt->schema != NULL) {
20087 xmlSchemaFree(ctxt->schema);
20088 ctxt->schema = NULL;
20089 }
Daniel Veillard4255d502002-04-16 15:50:10 +000020090 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020091 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020092}
20093
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020094
Daniel Veillard4255d502002-04-16 15:50:10 +000020095/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020096 * xmlSchemaValidateOneElement:
20097 * @ctxt: a schema validation context
20098 * @elem: an element node
20099 *
20100 * Validate a branch of a tree, starting with the given @elem.
20101 *
20102 * Returns 0 if the element and its subtree is valid, a positive error
20103 * code number otherwise and -1 in case of an internal or API error.
20104 */
20105int
20106xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
20107{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020108 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020109 return (-1);
20110
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020111 if (ctxt->schema == NULL) {
20112 xmlSchemaVErr(ctxt, NULL,
20113 XML_SCHEMAV_INTERNAL,
20114 "API error: xmlSchemaValidateOneElement, "
20115 "no schema specified.\n", NULL, NULL);
20116 return (-1);
20117 }
20118
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020119 ctxt->doc = elem->doc;
20120 ctxt->err = 0;
20121 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020122 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020123 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020124 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020125}
20126
20127/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020128 * xmlSchemaValidateDocument:
20129 * @ctxt: a schema validation context
20130 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020131 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000020132 *
20133 * Validate a document tree in memory.
20134 *
20135 * Returns 0 if the document is schemas valid, a positive error code
20136 * number otherwise and -1 in case of internal or API error.
20137 */
20138static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020139xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
20140{
Daniel Veillard4255d502002-04-16 15:50:10 +000020141 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000020142
Daniel Veillard4255d502002-04-16 15:50:10 +000020143 root = xmlDocGetRootElement(doc);
20144 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020145 xmlSchemaVCustomErr(ctxt,
20146 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
20147 (xmlNodePtr) doc, NULL,
20148 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020149 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020150 }
Daniel Veillard4255d502002-04-16 15:50:10 +000020151 /*
20152 * Okay, start the recursive validation
20153 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020154 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020155 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020156 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000020157
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020158 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000020159}
20160
20161/************************************************************************
20162 * *
20163 * SAX Validation code *
20164 * *
20165 ************************************************************************/
20166
20167/************************************************************************
20168 * *
20169 * Validation interfaces *
20170 * *
20171 ************************************************************************/
20172
20173/**
20174 * xmlSchemaNewValidCtxt:
20175 * @schema: a precompiled XML Schemas
20176 *
20177 * Create an XML Schemas validation context based on the given schema
20178 *
20179 * Returns the validation context or NULL in case of error
20180 */
20181xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020182xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
20183{
Daniel Veillard4255d502002-04-16 15:50:10 +000020184 xmlSchemaValidCtxtPtr ret;
20185
20186 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
20187 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020188 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000020189 return (NULL);
20190 }
20191 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000020192 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000020193 ret->attrTop = NULL;
20194 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000020195 return (ret);
20196}
20197
20198/**
20199 * xmlSchemaFreeValidCtxt:
20200 * @ctxt: the schema validation context
20201 *
20202 * Free the resources associated to the schema validation context
20203 */
20204void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020205xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
20206{
Daniel Veillard4255d502002-04-16 15:50:10 +000020207 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020208 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000020209 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000020210 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000020211 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020212 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020213 if (ctxt->pctxt != NULL) {
20214 xmlSchemaFreeParserCtxt(ctxt->pctxt);
20215 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020216
20217#ifdef IDC_ENABLED
20218 if (ctxt->idcNodes != NULL) {
20219 int i;
20220 xmlSchemaPSVIIDCNodePtr item;
20221
20222 for (i = 0; i < ctxt->nbIdcNodes; i++) {
20223 item = ctxt->idcNodes[i];
20224 xmlFree(item->keys);
20225 xmlFree(item);
20226 }
20227 xmlFree(ctxt->idcNodes);
20228 }
20229
20230 if (ctxt->idcKeys != NULL) {
20231 int i;
20232 for (i = 0; i < ctxt->nbIdcKeys; i++)
20233 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
20234 xmlFree(ctxt->idcKeys);
20235 }
20236
20237 if (ctxt->xpathStates != NULL)
20238 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
20239 if (ctxt->xpathStatePool != NULL)
20240 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
20241
20242 /*
20243 * Augmented IDC information.
20244 */
20245 if (ctxt->aidcs != NULL) {
20246 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
20247 do {
20248 next = cur->next;
20249 xmlFree(cur);
20250 cur = next;
20251 } while (cur != NULL);
20252 }
20253#endif /* IDC_ENABLED */
20254#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020255 if (ctxt->attrInfo != NULL) {
20256 if (ctxt->attrInfo->value != NULL)
20257 xmlSchemaFreeValue(ctxt->attrInfo->value);
20258 xmlFree(ctxt->attrInfo);
20259 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020260 if (ctxt->elemInfos != NULL) {
20261 int i;
20262 xmlSchemaElemInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020263
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020264 for (i = 0; i < ctxt->sizeElemInfos; i++) {
20265 info = ctxt->elemInfos[i];
20266 if (info == NULL)
20267 continue;
20268 if (info->value != NULL)
20269 xmlSchemaFreeValue(info->value);
20270#ifdef IDC_ENABLED
20271 if (info->idcMatchers != NULL)
20272 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
20273#endif
20274 /*
20275 * TODO: Free the IDC table if still existent.
20276 */
20277
20278 /*
20279 xmlFree(info->localName);
20280 if (info->namespaceName != NULL)
20281 xmlFree(info->namespaceName);
20282 */
20283 xmlFree(info);
20284 }
20285 xmlFree(ctxt->elemInfos);
20286 }
20287#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000020288 xmlFree(ctxt);
20289}
20290
20291/**
20292 * xmlSchemaSetValidErrors:
20293 * @ctxt: a schema validation context
20294 * @err: the error function
20295 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000020296 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000020297 *
William M. Brack2f2a6632004-08-20 23:09:47 +000020298 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000020299 */
20300void
20301xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020302 xmlSchemaValidityErrorFunc err,
20303 xmlSchemaValidityWarningFunc warn, void *ctx)
20304{
Daniel Veillard4255d502002-04-16 15:50:10 +000020305 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020306 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000020307 ctxt->error = err;
20308 ctxt->warning = warn;
20309 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020310 if (ctxt->pctxt != NULL)
20311 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000020312}
20313
20314/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000020315 * xmlSchemaGetValidErrors:
20316 * @ctxt: a XML-Schema validation context
20317 * @err: the error function result
20318 * @warn: the warning function result
20319 * @ctx: the functions context result
20320 *
20321 * Get the error and warning callback informations
20322 *
20323 * Returns -1 in case of error and 0 otherwise
20324 */
20325int
20326xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
20327 xmlSchemaValidityErrorFunc * err,
20328 xmlSchemaValidityWarningFunc * warn, void **ctx)
20329{
20330 if (ctxt == NULL)
20331 return (-1);
20332 if (err != NULL)
20333 *err = ctxt->error;
20334 if (warn != NULL)
20335 *warn = ctxt->warning;
20336 if (ctx != NULL)
20337 *ctx = ctxt->userData;
20338 return (0);
20339}
20340
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020341
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020342/**
Daniel Veillard6927b102004-10-27 17:29:04 +000020343 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020344 * @ctxt: a schema validation context
20345 * @options: a combination of xmlSchemaValidOption
20346 *
20347 * Sets the options to be used during the validation.
20348 *
20349 * Returns 0 in case of success, -1 in case of an
20350 * API error.
20351 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020352int
20353xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
20354 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020355
20356{
20357 int i;
20358
20359 if (ctxt == NULL)
20360 return (-1);
20361 /*
20362 * WARNING: Change the start value if adding to the
20363 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020364 * TODO: Is there an other, more easy to maintain,
20365 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020366 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020367 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020368 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020369 xmlSchemaVErr(ctxt, NULL,
20370 XML_SCHEMAV_INTERNAL,
20371 "Internal error: xmlSchemaSetValidOptions, "
20372 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020373 return (-1);
20374 }
20375 }
20376 ctxt->options = options;
20377 return (0);
20378}
20379
20380/**
Daniel Veillard6927b102004-10-27 17:29:04 +000020381 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020382 * @ctxt: a schema validation context
20383 *
William M. Brack21e4ef22005-01-02 09:53:13 +000020384 * Get the validation context options.
20385 *
20386 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020387 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020388int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020389xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
20390
20391{
20392 if (ctxt == NULL)
20393 return (-1);
20394 else
20395 return (ctxt->options);
20396}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020397
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020398
Daniel Veillard259f0df2004-08-18 09:13:18 +000020399/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020400 * xmlSchemaValidateDoc:
20401 * @ctxt: a schema validation context
20402 * @doc: a parsed document tree
20403 *
20404 * Validate a document tree in memory.
20405 *
20406 * Returns 0 if the document is schemas valid, a positive error code
20407 * number otherwise and -1 in case of internal or API error.
20408 */
20409int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020410xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
20411{
Daniel Veillard4255d502002-04-16 15:50:10 +000020412 int ret;
20413
20414 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020415 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020416
20417 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000020418 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020419 ctxt->nberrors = 0;
20420
20421 /*
20422 if (ctxt->schema == NULL) {
20423 xmlSchemaVErr(ctxt, NULL,
20424 XML_SCHEMAV_INTERNAL,
20425 "API error: xmlSchemaValidateDoc, "
20426 "no schema specified and assembling of schemata "
20427 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
20428 "is not enabled.\n", NULL, NULL);
20429 return (-1);
20430 }
20431 */
Daniel Veillard4255d502002-04-16 15:50:10 +000020432 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020433 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020434}
20435
20436/**
20437 * xmlSchemaValidateStream:
20438 * @ctxt: a schema validation context
20439 * @input: the input to use for reading the data
20440 * @enc: an optional encoding information
20441 * @sax: a SAX handler for the resulting events
20442 * @user_data: the context to provide to the SAX handler.
20443 *
20444 * Validate a document tree in memory.
20445 *
20446 * Returns 0 if the document is schemas valid, a positive error code
20447 * number otherwise and -1 in case of internal or API error.
20448 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020449int
Daniel Veillard4255d502002-04-16 15:50:10 +000020450xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020451 xmlParserInputBufferPtr input, xmlCharEncoding enc,
20452 xmlSAXHandlerPtr sax, void *user_data)
20453{
Daniel Veillard4255d502002-04-16 15:50:10 +000020454 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020455 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020456 ctxt->input = input;
20457 ctxt->enc = enc;
20458 ctxt->sax = sax;
20459 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020460 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020461}
20462
20463#endif /* LIBXML_SCHEMAS_ENABLED */